node-sqlite-kv 0.3.0 → 0.4.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/README.md CHANGED
@@ -78,6 +78,9 @@ const { oldValues, newValues } = kv.transaction((tx) => {
78
78
 
79
79
  // delete all entries
80
80
  kv.clear();
81
+
82
+ // close the database
83
+ kv.close();
81
84
  ```
82
85
 
83
86
  ## Contributing
package/dist/index.cjs ADDED
@@ -0,0 +1,221 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+ let node_sqlite = require("node:sqlite");
29
+ let node_v8 = require("node:v8");
30
+ let node_fs = require("node:fs");
31
+ node_fs = __toESM(node_fs);
32
+ let node_path = require("node:path");
33
+ node_path = __toESM(node_path);
34
+
35
+ //#region src/classes/KVError.ts
36
+ /**
37
+ * Class representing a KVError
38
+ */
39
+ var KVError = class extends Error {
40
+ static name = "KVError";
41
+ scope;
42
+ constructor(scope, ...args) {
43
+ super(args.join(" "));
44
+ this.scope = scope;
45
+ Error.captureStackTrace?.(this, this.constructor);
46
+ }
47
+ get name() {
48
+ return `${this.constructor.name} (${this.scope})`;
49
+ }
50
+ };
51
+
52
+ //#endregion
53
+ //#region src/utils/index.ts
54
+ /**
55
+ * A list of journal modes SQLite supports
56
+ */
57
+ const journalModes = {
58
+ Delete: "DELETE",
59
+ Memory: "MEMORY",
60
+ Off: "OFF",
61
+ Persist: "PERSIST",
62
+ Truncate: "TRUNCATE",
63
+ WAL: "WAL"
64
+ };
65
+
66
+ //#endregion
67
+ //#region src/classes/KVSync.ts
68
+ /**
69
+ * Class representing a synchronous key-value store
70
+ */
71
+ var KVSync = class {
72
+ #db;
73
+ /**
74
+ * Instantiate a new key-value store
75
+ * @param options KVSync options
76
+ */
77
+ constructor(options) {
78
+ const dbPath = options?.path ?? ":memory:";
79
+ if (dbPath !== ":memory:") node_fs.default.mkdirSync(node_path.default.dirname(dbPath), { recursive: true });
80
+ this.#db = new node_sqlite.DatabaseSync(dbPath);
81
+ this.setJournalMode(options?.journalMode ?? (dbPath !== ":memory:" ? journalModes.WAL : journalModes.Delete));
82
+ this.#db.exec("CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY NOT NULL, value BLOB NOT NULL) STRICT;");
83
+ }
84
+ /**
85
+ * Set a key in the database
86
+ * @param key Key name
87
+ * @param value Key value
88
+ * @returns Provided value
89
+ */
90
+ set(key, value) {
91
+ if (!this.#db.isOpen) throw new KVError("set", "Database is not open");
92
+ if (!key || typeof key !== "string") throw new KVError("set", "Key must be provided and be a non-empty string");
93
+ if (value === void 0) throw new KVError("set", "Provided value is undefined, did you mean to use delete()?");
94
+ this.#db.prepare("INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)").run(key, (0, node_v8.serialize)(value));
95
+ return value;
96
+ }
97
+ /**
98
+ * Get a value from the database
99
+ * @param key Key name
100
+ * @returns Value or null
101
+ */
102
+ get(key) {
103
+ if (!this.#db.isOpen) throw new KVError("get", "Database is not open");
104
+ if (!key || typeof key !== "string") throw new KVError("get", "Key must be provided and be a non-empty string.");
105
+ const row = this.#db.prepare("SELECT value FROM kv WHERE key = ?;").get(key);
106
+ return row ? (0, node_v8.deserialize)(row.value) : null;
107
+ }
108
+ /**
109
+ * Delete a key from the database
110
+ * @param key Key name
111
+ * @returns KVSync instance
112
+ */
113
+ delete(key) {
114
+ if (!this.#db.isOpen) throw new KVError("delete", "Database is not open");
115
+ if (!key || typeof key !== "string") throw new KVError("delete", "Key must be provided and be a non-empty string.");
116
+ this.#db.prepare("DELETE FROM kv WHERE key = ?;").run(key);
117
+ return this;
118
+ }
119
+ /**
120
+ * Get all data in the database
121
+ * @returns Array of objects containing keys and values
122
+ */
123
+ all(filter) {
124
+ if (!this.#db.isOpen) throw new KVError("all", "Database is not open");
125
+ const rows = this.#db.prepare("SELECT key, value FROM kv").iterate();
126
+ const result = [];
127
+ for (const row of rows) {
128
+ const key = row.key;
129
+ const value = (0, node_v8.deserialize)(row.value);
130
+ if (!filter || filter(key, value)) result.push({
131
+ key,
132
+ value
133
+ });
134
+ }
135
+ return result;
136
+ }
137
+ /**
138
+ * Remove all entries from the database
139
+ */
140
+ clear() {
141
+ if (!this.#db.isOpen) throw new KVError("clear", "Database is not open");
142
+ this.#db.exec("DELETE FROM kv;");
143
+ return this;
144
+ }
145
+ /**
146
+ * Update the journal mode
147
+ * @param mode New journal mode
148
+ */
149
+ setJournalMode(mode) {
150
+ if (!this.#db.isOpen) throw new KVError("setJournalMode", "Database is not open");
151
+ if (!Object.values(journalModes).includes(mode)) throw new KVError("setJournalMode", `Invalid journal mode specified - received: "${mode}", expected one of: ${Object.values(journalModes).join(", ")}`);
152
+ this.#db.exec(`PRAGMA journal_mode = ${mode};`);
153
+ return this;
154
+ }
155
+ /**
156
+ * Perform a transaction
157
+ * @param callback Callback with KVSync instance
158
+ * @returns Object containing oldValues and newValues each containing arrays of keys and values
159
+ */
160
+ transaction(callback) {
161
+ if (!this.#db.isOpen) throw new KVError("transaction", "Database is not open");
162
+ if (!callback) throw new KVError("transaction", "A callback must be provided when using transaction().");
163
+ if (typeof callback !== "function") throw new KVError("transaction", `Transaction callback must be of type function. Received: ${typeof callback}`);
164
+ const oldMap = /* @__PURE__ */ new Map();
165
+ const newMap = /* @__PURE__ */ new Map();
166
+ const tx = Object.create(this);
167
+ tx.set = (key, value) => {
168
+ if (!oldMap.has(key)) {
169
+ const oldValue = this.get(key);
170
+ oldMap.set(key, oldValue === null ? void 0 : oldValue);
171
+ }
172
+ newMap.set(key, value);
173
+ return value ?? null;
174
+ };
175
+ tx.delete = (key) => {
176
+ if (!oldMap.has(key)) {
177
+ const oldValue = this.get(key);
178
+ oldMap.set(key, oldValue === null ? void 0 : oldValue);
179
+ }
180
+ newMap.set(key, null);
181
+ return tx;
182
+ };
183
+ try {
184
+ this.#db.exec("BEGIN TRANSACTION;");
185
+ callback(tx);
186
+ for (const [key, value] of newMap.entries()) if (value === null) this.delete(key);
187
+ else this.set(key, value);
188
+ this.#db.exec("COMMIT;");
189
+ } catch (error) {
190
+ this.#db.exec("ROLLBACK;");
191
+ throw error;
192
+ }
193
+ return {
194
+ oldValues: Array.from(oldMap.entries()).map(([key, value]) => ({
195
+ key,
196
+ value
197
+ })),
198
+ newValues: Array.from(newMap.entries()).map(([key, value]) => ({
199
+ key,
200
+ value
201
+ }))
202
+ };
203
+ }
204
+ /**
205
+ * Open the database
206
+ */
207
+ open() {
208
+ if (this.#db.isOpen) throw new KVError("open", "Database is open");
209
+ }
210
+ /**
211
+ * Close the database
212
+ */
213
+ close() {
214
+ if (!this.#db.isOpen) throw new KVError("close", "Database is not open");
215
+ this.#db.close();
216
+ }
217
+ };
218
+
219
+ //#endregion
220
+ exports.KVSync = KVSync;
221
+ exports.journalModes = journalModes;
@@ -0,0 +1,46 @@
1
+ //#region src/utils/index.d.ts
2
+ declare const journalModes: {
3
+ readonly Delete: "DELETE";
4
+ readonly Memory: "MEMORY";
5
+ readonly Off: "OFF";
6
+ readonly Persist: "PERSIST";
7
+ readonly Truncate: "TRUNCATE";
8
+ readonly WAL: "WAL";
9
+ };
10
+ //#endregion
11
+ //#region src/types.d.ts
12
+ type JournalMode = (typeof journalModes)[keyof typeof journalModes];
13
+ interface KVSyncOptions {
14
+ path?: SQLitePath;
15
+ journalMode?: JournalMode;
16
+ }
17
+ type SQLitePath = ":memory:" | (string & {});
18
+ //#endregion
19
+ //#region src/classes/KVSync.d.ts
20
+ declare class KVSync<T = any> {
21
+ #private;
22
+ constructor(options?: KVSyncOptions);
23
+ set<K = T>(key: string, value: K | undefined): K;
24
+ get<K = T>(key: string): K | null;
25
+ delete(key: string): KVSync;
26
+ all<K = T>(filter?: (key: string, value: K) => boolean): {
27
+ key: string;
28
+ value: K;
29
+ }[];
30
+ clear(): KVSync;
31
+ setJournalMode(mode: JournalMode): this;
32
+ transaction<R>(callback: (kv: KVSync<T>) => R): {
33
+ oldValues: {
34
+ key: string;
35
+ value: T | null | undefined;
36
+ }[];
37
+ newValues: {
38
+ key: string;
39
+ value: T | null;
40
+ }[];
41
+ };
42
+ open(): void;
43
+ close(): void;
44
+ }
45
+ //#endregion
46
+ export { JournalMode, KVSync, KVSyncOptions, SQLitePath, journalModes };
package/dist/index.d.mts CHANGED
@@ -1,32 +1,46 @@
1
- type JournalMode = "DELETE" | "MEMORY" | "OFF" | "PERSIST" | "TRUNCATE" | "WAL";
1
+ //#region src/utils/index.d.ts
2
+ declare const journalModes: {
3
+ readonly Delete: "DELETE";
4
+ readonly Memory: "MEMORY";
5
+ readonly Off: "OFF";
6
+ readonly Persist: "PERSIST";
7
+ readonly Truncate: "TRUNCATE";
8
+ readonly WAL: "WAL";
9
+ };
10
+ //#endregion
11
+ //#region src/types.d.ts
12
+ type JournalMode = (typeof journalModes)[keyof typeof journalModes];
2
13
  interface KVSyncOptions {
3
- path?: SQLitePath;
4
- journalMode?: JournalMode;
14
+ path?: SQLitePath;
15
+ journalMode?: JournalMode;
5
16
  }
6
17
  type SQLitePath = ":memory:" | (string & {});
7
- declare const journalModes: JournalMode[];
18
+ //#endregion
19
+ //#region src/classes/KVSync.d.ts
8
20
  declare class KVSync<T = any> {
9
- #private;
10
- constructor(options?: KVSyncOptions);
11
- set<K = T>(key: string, value: K | undefined): K | null;
12
- get<K = T>(key: string): K | null;
13
- delete(key: string): KVSync;
14
- all<K = T>(filter?: (key: string, value: K) => boolean): {
15
- key: string;
16
- value: K;
21
+ #private;
22
+ constructor(options?: KVSyncOptions);
23
+ set<K = T>(key: string, value: K | undefined): K;
24
+ get<K = T>(key: string): K | null;
25
+ delete(key: string): KVSync;
26
+ all<K = T>(filter?: (key: string, value: K) => boolean): {
27
+ key: string;
28
+ value: K;
29
+ }[];
30
+ clear(): KVSync;
31
+ setJournalMode(mode: JournalMode): this;
32
+ transaction<R>(callback: (kv: KVSync<T>) => R): {
33
+ oldValues: {
34
+ key: string;
35
+ value: T | null | undefined;
17
36
  }[];
18
- clear(): KVSync;
19
- setJournalMode(mode: JournalMode): this;
20
- transaction<R>(callback: (kv: KVSync<T>) => R): {
21
- oldValues: {
22
- key: string;
23
- value: T | null | undefined;
24
- }[];
25
- newValues: {
26
- key: string;
27
- value: T | null;
28
- }[];
29
- };
37
+ newValues: {
38
+ key: string;
39
+ value: T | null;
40
+ }[];
41
+ };
42
+ open(): void;
43
+ close(): void;
30
44
  }
31
-
32
- export { type JournalMode, KVSync, type KVSyncOptions, type SQLitePath, journalModes };
45
+ //#endregion
46
+ export { JournalMode, KVSync, KVSyncOptions, SQLitePath, journalModes };
package/dist/index.mjs CHANGED
@@ -1,183 +1,191 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/index.ts
5
1
  import { DatabaseSync } from "node:sqlite";
6
- import { serialize, deserialize } from "node:v8";
2
+ import { deserialize, serialize } from "node:v8";
7
3
  import fs from "node:fs";
8
4
  import path from "node:path";
9
- var journalModes = [
10
- "DELETE",
11
- "MEMORY",
12
- "OFF",
13
- "PERSIST",
14
- "TRUNCATE",
15
- "WAL"
16
- ];
17
- var KVSync = class {
18
- static {
19
- __name(this, "KVSync");
20
- }
21
- #db;
22
- /**
23
- * Instantiate a new key-value store
24
- * @param path Where the database is stored, or `:memory:` for in-memory storage
25
- */
26
- constructor(options) {
27
- const dbPath = options?.path ?? ":memory:";
28
- if (dbPath !== ":memory:") {
29
- fs.mkdirSync(path.dirname(dbPath), { recursive: true });
30
- }
31
- this.#db = new DatabaseSync(dbPath);
32
- this.setJournalMode(options?.journalMode ?? "DELETE");
33
- this.#db.exec(`
34
- CREATE TABLE IF NOT EXISTS kv (
35
- key TEXT PRIMARY KEY NOT NULL,
36
- value BLOB NOT NULL
37
- ) STRICT;
38
- `);
39
- }
40
- /**
41
- * Set a key in the database
42
- * @param key Key name
43
- * @param value Key value
44
- * @returns Provided value
45
- */
46
- set(key, value) {
47
- if (!key || typeof key !== "string") {
48
- throw new Error(
49
- "[KVSync]: Key must be provided and be a non-empty string."
50
- );
51
- }
52
- if (value === void 0) {
53
- this.delete(key);
54
- return null;
55
- }
56
- this.#db.prepare("INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)").run(key, serialize(value));
57
- return value;
58
- }
59
- /**
60
- * Get a value from the database
61
- * @param key Key name
62
- * @returns Value or null
63
- */
64
- get(key) {
65
- if (!key || typeof key !== "string") {
66
- throw new Error(
67
- "[KVSync]: Key must be provided and be a non-empty string."
68
- );
69
- }
70
- const row = this.#db.prepare("SELECT value FROM kv WHERE key = ?").get(key);
71
- return row ? deserialize(row.value) : null;
72
- }
73
- /**
74
- * Delete a key from the database
75
- * @param key Key name
76
- * @returns KVSync instance
77
- */
78
- delete(key) {
79
- if (!key || typeof key !== "string") {
80
- throw new Error(
81
- "[KVSync]: Key must be provided and be a non-empty string."
82
- );
83
- }
84
- this.#db.prepare("DELETE FROM kv WHERE key = ?").run(key);
85
- return this;
86
- }
87
- /**
88
- * Get all data in the database
89
- * @returns Array of objects containing keys and values
90
- */
91
- all(filter) {
92
- const rows = this.#db.prepare("SELECT key, value FROM kv").iterate();
93
- const result = [];
94
- for (const row of rows) {
95
- const key = row.key;
96
- const value = deserialize(row.value);
97
- if (!filter || filter(key, value)) {
98
- result.push({ key, value });
99
- }
100
- }
101
- return result;
102
- }
103
- /**
104
- * Remove all entries from the database
105
- */
106
- clear() {
107
- this.#db.exec("DELETE FROM kv;");
108
- return this;
109
- }
110
- /**
111
- * Update the journal mode
112
- * @param mode New journal mode
113
- */
114
- setJournalMode(mode) {
115
- if (!journalModes.includes(mode)) {
116
- throw new Error(
117
- `[KVSync]: Invalid journal mode specified. Received: "${mode}", expected one of: ${journalModes.join(", ")}`
118
- );
119
- }
120
- this.#db.exec(`PRAGMA journal_mode = ${mode};`);
121
- return this;
122
- }
123
- /**
124
- * Perform a transaction
125
- * @param callback Callback with KVSync instance
126
- * @returns Object containing oldValues and newValues each containing arrays of keys and values
127
- */
128
- transaction(callback) {
129
- if (!callback) {
130
- throw new Error(
131
- "[KVSync]: A callback must be provided when using transaction()."
132
- );
133
- }
134
- if (typeof callback !== "function") {
135
- throw new Error(
136
- `[KVSync]: Transaction callback must be of type function. Received: ${typeof callback}`
137
- );
138
- }
139
- this.#db.exec("BEGIN TRANSACTION;");
140
- const oldMap = /* @__PURE__ */ new Map();
141
- const newMap = /* @__PURE__ */ new Map();
142
- const tx = Object.create(this);
143
- tx.set = (key, value) => {
144
- if (!oldMap.has(key)) {
145
- const oldValue = this.get(key);
146
- oldMap.set(key, oldValue === null ? void 0 : oldValue);
147
- }
148
- const result = this.set(key, value);
149
- newMap.set(key, result);
150
- return result;
151
- };
152
- tx.delete = (key) => {
153
- if (!oldMap.has(key)) {
154
- const oldValue = this.get(key);
155
- oldMap.set(key, oldValue === null ? void 0 : oldValue);
156
- }
157
- newMap.set(key, null);
158
- this.delete(key);
159
- return tx;
160
- };
161
- try {
162
- callback(tx);
163
- this.#db.exec("COMMIT;");
164
- } catch (error) {
165
- this.#db.exec("ROLLBACK;");
166
- throw error;
167
- }
168
- return {
169
- oldValues: Array.from(oldMap.entries()).map(([key, value]) => ({
170
- key,
171
- value
172
- })),
173
- newValues: Array.from(newMap.entries()).map(([key, value]) => ({
174
- key,
175
- value
176
- }))
177
- };
178
- }
5
+
6
+ //#region src/classes/KVError.ts
7
+ /**
8
+ * Class representing a KVError
9
+ */
10
+ var KVError = class extends Error {
11
+ static name = "KVError";
12
+ scope;
13
+ constructor(scope, ...args) {
14
+ super(args.join(" "));
15
+ this.scope = scope;
16
+ Error.captureStackTrace?.(this, this.constructor);
17
+ }
18
+ get name() {
19
+ return `${this.constructor.name} (${this.scope})`;
20
+ }
21
+ };
22
+
23
+ //#endregion
24
+ //#region src/utils/index.ts
25
+ /**
26
+ * A list of journal modes SQLite supports
27
+ */
28
+ const journalModes = {
29
+ Delete: "DELETE",
30
+ Memory: "MEMORY",
31
+ Off: "OFF",
32
+ Persist: "PERSIST",
33
+ Truncate: "TRUNCATE",
34
+ WAL: "WAL"
179
35
  };
180
- export {
181
- KVSync,
182
- journalModes
36
+
37
+ //#endregion
38
+ //#region src/classes/KVSync.ts
39
+ /**
40
+ * Class representing a synchronous key-value store
41
+ */
42
+ var KVSync = class {
43
+ #db;
44
+ /**
45
+ * Instantiate a new key-value store
46
+ * @param options KVSync options
47
+ */
48
+ constructor(options) {
49
+ const dbPath = options?.path ?? ":memory:";
50
+ if (dbPath !== ":memory:") fs.mkdirSync(path.dirname(dbPath), { recursive: true });
51
+ this.#db = new DatabaseSync(dbPath);
52
+ this.setJournalMode(options?.journalMode ?? (dbPath !== ":memory:" ? journalModes.WAL : journalModes.Delete));
53
+ this.#db.exec("CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY NOT NULL, value BLOB NOT NULL) STRICT;");
54
+ }
55
+ /**
56
+ * Set a key in the database
57
+ * @param key Key name
58
+ * @param value Key value
59
+ * @returns Provided value
60
+ */
61
+ set(key, value) {
62
+ if (!this.#db.isOpen) throw new KVError("set", "Database is not open");
63
+ if (!key || typeof key !== "string") throw new KVError("set", "Key must be provided and be a non-empty string");
64
+ if (value === void 0) throw new KVError("set", "Provided value is undefined, did you mean to use delete()?");
65
+ this.#db.prepare("INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)").run(key, serialize(value));
66
+ return value;
67
+ }
68
+ /**
69
+ * Get a value from the database
70
+ * @param key Key name
71
+ * @returns Value or null
72
+ */
73
+ get(key) {
74
+ if (!this.#db.isOpen) throw new KVError("get", "Database is not open");
75
+ if (!key || typeof key !== "string") throw new KVError("get", "Key must be provided and be a non-empty string.");
76
+ const row = this.#db.prepare("SELECT value FROM kv WHERE key = ?;").get(key);
77
+ return row ? deserialize(row.value) : null;
78
+ }
79
+ /**
80
+ * Delete a key from the database
81
+ * @param key Key name
82
+ * @returns KVSync instance
83
+ */
84
+ delete(key) {
85
+ if (!this.#db.isOpen) throw new KVError("delete", "Database is not open");
86
+ if (!key || typeof key !== "string") throw new KVError("delete", "Key must be provided and be a non-empty string.");
87
+ this.#db.prepare("DELETE FROM kv WHERE key = ?;").run(key);
88
+ return this;
89
+ }
90
+ /**
91
+ * Get all data in the database
92
+ * @returns Array of objects containing keys and values
93
+ */
94
+ all(filter) {
95
+ if (!this.#db.isOpen) throw new KVError("all", "Database is not open");
96
+ const rows = this.#db.prepare("SELECT key, value FROM kv").iterate();
97
+ const result = [];
98
+ for (const row of rows) {
99
+ const key = row.key;
100
+ const value = deserialize(row.value);
101
+ if (!filter || filter(key, value)) result.push({
102
+ key,
103
+ value
104
+ });
105
+ }
106
+ return result;
107
+ }
108
+ /**
109
+ * Remove all entries from the database
110
+ */
111
+ clear() {
112
+ if (!this.#db.isOpen) throw new KVError("clear", "Database is not open");
113
+ this.#db.exec("DELETE FROM kv;");
114
+ return this;
115
+ }
116
+ /**
117
+ * Update the journal mode
118
+ * @param mode New journal mode
119
+ */
120
+ setJournalMode(mode) {
121
+ if (!this.#db.isOpen) throw new KVError("setJournalMode", "Database is not open");
122
+ if (!Object.values(journalModes).includes(mode)) throw new KVError("setJournalMode", `Invalid journal mode specified - received: "${mode}", expected one of: ${Object.values(journalModes).join(", ")}`);
123
+ this.#db.exec(`PRAGMA journal_mode = ${mode};`);
124
+ return this;
125
+ }
126
+ /**
127
+ * Perform a transaction
128
+ * @param callback Callback with KVSync instance
129
+ * @returns Object containing oldValues and newValues each containing arrays of keys and values
130
+ */
131
+ transaction(callback) {
132
+ if (!this.#db.isOpen) throw new KVError("transaction", "Database is not open");
133
+ if (!callback) throw new KVError("transaction", "A callback must be provided when using transaction().");
134
+ if (typeof callback !== "function") throw new KVError("transaction", `Transaction callback must be of type function. Received: ${typeof callback}`);
135
+ const oldMap = /* @__PURE__ */ new Map();
136
+ const newMap = /* @__PURE__ */ new Map();
137
+ const tx = Object.create(this);
138
+ tx.set = (key, value) => {
139
+ if (!oldMap.has(key)) {
140
+ const oldValue = this.get(key);
141
+ oldMap.set(key, oldValue === null ? void 0 : oldValue);
142
+ }
143
+ newMap.set(key, value);
144
+ return value ?? null;
145
+ };
146
+ tx.delete = (key) => {
147
+ if (!oldMap.has(key)) {
148
+ const oldValue = this.get(key);
149
+ oldMap.set(key, oldValue === null ? void 0 : oldValue);
150
+ }
151
+ newMap.set(key, null);
152
+ return tx;
153
+ };
154
+ try {
155
+ this.#db.exec("BEGIN TRANSACTION;");
156
+ callback(tx);
157
+ for (const [key, value] of newMap.entries()) if (value === null) this.delete(key);
158
+ else this.set(key, value);
159
+ this.#db.exec("COMMIT;");
160
+ } catch (error) {
161
+ this.#db.exec("ROLLBACK;");
162
+ throw error;
163
+ }
164
+ return {
165
+ oldValues: Array.from(oldMap.entries()).map(([key, value]) => ({
166
+ key,
167
+ value
168
+ })),
169
+ newValues: Array.from(newMap.entries()).map(([key, value]) => ({
170
+ key,
171
+ value
172
+ }))
173
+ };
174
+ }
175
+ /**
176
+ * Open the database
177
+ */
178
+ open() {
179
+ if (this.#db.isOpen) throw new KVError("open", "Database is open");
180
+ }
181
+ /**
182
+ * Close the database
183
+ */
184
+ close() {
185
+ if (!this.#db.isOpen) throw new KVError("close", "Database is not open");
186
+ this.#db.close();
187
+ }
183
188
  };
189
+
190
+ //#endregion
191
+ export { KVSync, journalModes };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "node-sqlite-kv",
3
3
  "description": "Key-value store with node:sqlite",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "repository": {
6
6
  "url": "https://github.com/e60m5ss/node-sqlite-kv"
7
7
  },
@@ -9,16 +9,23 @@
9
9
  "name": "e60m5ss",
10
10
  "url": "https://github.com/e60m5ss"
11
11
  },
12
- "main": "./dist/index.js",
12
+ "main": "./dist/index.mjs",
13
13
  "module": "./dist/index.mjs",
14
- "types": "./dist/index.d.ts",
14
+ "types": "./dist/index.d.mts",
15
+ "type": "module",
16
+ "exports": {
17
+ "default": "./dist/index.cjs",
18
+ "import": "./dist/index.mjs",
19
+ "require": "./dist/index.cjs",
20
+ "types": "./dist/index.d.cts"
21
+ },
15
22
  "engineStrict": true,
16
23
  "engines": {
17
24
  "node": ">=22.5.0"
18
25
  },
19
26
  "prettier": {
20
27
  "jsxSingleQuote": false,
21
- "printWidth": 85,
28
+ "printWidth": 80,
22
29
  "semi": true,
23
30
  "singleQuote": false,
24
31
  "tabWidth": 4,
@@ -26,15 +33,15 @@
26
33
  "useTabs": false
27
34
  },
28
35
  "devDependencies": {
29
- "@types/node": "^25.1.0",
36
+ "@types/node": "^25.2.0",
30
37
  "prettier": "^3.8.1",
31
- "tsup": "^8.5.1",
38
+ "tsdown": "^0.20.1",
32
39
  "typescript": "^5.9.3"
33
40
  },
34
41
  "scripts": {
35
- "build": "tsup",
42
+ "build": "tsdown",
36
43
  "format": "prettier ./src --write --ignore-path=.prettierignore",
37
44
  "lint": "tsc --noEmit; prettier ./src --check --ignore-path=.prettierignore",
38
- "prepublish": "tsup"
45
+ "prepublish": "tsdown"
39
46
  }
40
47
  }
package/dist/index.d.ts DELETED
@@ -1,32 +0,0 @@
1
- type JournalMode = "DELETE" | "MEMORY" | "OFF" | "PERSIST" | "TRUNCATE" | "WAL";
2
- interface KVSyncOptions {
3
- path?: SQLitePath;
4
- journalMode?: JournalMode;
5
- }
6
- type SQLitePath = ":memory:" | (string & {});
7
- declare const journalModes: JournalMode[];
8
- declare class KVSync<T = any> {
9
- #private;
10
- constructor(options?: KVSyncOptions);
11
- set<K = T>(key: string, value: K | undefined): K | null;
12
- get<K = T>(key: string): K | null;
13
- delete(key: string): KVSync;
14
- all<K = T>(filter?: (key: string, value: K) => boolean): {
15
- key: string;
16
- value: K;
17
- }[];
18
- clear(): KVSync;
19
- setJournalMode(mode: JournalMode): this;
20
- transaction<R>(callback: (kv: KVSync<T>) => R): {
21
- oldValues: {
22
- key: string;
23
- value: T | null | undefined;
24
- }[];
25
- newValues: {
26
- key: string;
27
- value: T | null;
28
- }[];
29
- };
30
- }
31
-
32
- export { type JournalMode, KVSync, type KVSyncOptions, type SQLitePath, journalModes };
package/dist/index.js DELETED
@@ -1,217 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
- var __export = (target, all) => {
10
- for (var name in all)
11
- __defProp(target, name, { get: all[name], enumerable: true });
12
- };
13
- var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
20
- };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
-
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- KVSync: () => KVSync,
35
- journalModes: () => journalModes
36
- });
37
- module.exports = __toCommonJS(index_exports);
38
- var import_node_sqlite = require("node:sqlite");
39
- var import_node_v8 = require("node:v8");
40
- var import_node_fs = __toESM(require("node:fs"));
41
- var import_node_path = __toESM(require("node:path"));
42
- var journalModes = [
43
- "DELETE",
44
- "MEMORY",
45
- "OFF",
46
- "PERSIST",
47
- "TRUNCATE",
48
- "WAL"
49
- ];
50
- var KVSync = class {
51
- static {
52
- __name(this, "KVSync");
53
- }
54
- #db;
55
- /**
56
- * Instantiate a new key-value store
57
- * @param path Where the database is stored, or `:memory:` for in-memory storage
58
- */
59
- constructor(options) {
60
- const dbPath = options?.path ?? ":memory:";
61
- if (dbPath !== ":memory:") {
62
- import_node_fs.default.mkdirSync(import_node_path.default.dirname(dbPath), { recursive: true });
63
- }
64
- this.#db = new import_node_sqlite.DatabaseSync(dbPath);
65
- this.setJournalMode(options?.journalMode ?? "DELETE");
66
- this.#db.exec(`
67
- CREATE TABLE IF NOT EXISTS kv (
68
- key TEXT PRIMARY KEY NOT NULL,
69
- value BLOB NOT NULL
70
- ) STRICT;
71
- `);
72
- }
73
- /**
74
- * Set a key in the database
75
- * @param key Key name
76
- * @param value Key value
77
- * @returns Provided value
78
- */
79
- set(key, value) {
80
- if (!key || typeof key !== "string") {
81
- throw new Error(
82
- "[KVSync]: Key must be provided and be a non-empty string."
83
- );
84
- }
85
- if (value === void 0) {
86
- this.delete(key);
87
- return null;
88
- }
89
- this.#db.prepare("INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)").run(key, (0, import_node_v8.serialize)(value));
90
- return value;
91
- }
92
- /**
93
- * Get a value from the database
94
- * @param key Key name
95
- * @returns Value or null
96
- */
97
- get(key) {
98
- if (!key || typeof key !== "string") {
99
- throw new Error(
100
- "[KVSync]: Key must be provided and be a non-empty string."
101
- );
102
- }
103
- const row = this.#db.prepare("SELECT value FROM kv WHERE key = ?").get(key);
104
- return row ? (0, import_node_v8.deserialize)(row.value) : null;
105
- }
106
- /**
107
- * Delete a key from the database
108
- * @param key Key name
109
- * @returns KVSync instance
110
- */
111
- delete(key) {
112
- if (!key || typeof key !== "string") {
113
- throw new Error(
114
- "[KVSync]: Key must be provided and be a non-empty string."
115
- );
116
- }
117
- this.#db.prepare("DELETE FROM kv WHERE key = ?").run(key);
118
- return this;
119
- }
120
- /**
121
- * Get all data in the database
122
- * @returns Array of objects containing keys and values
123
- */
124
- all(filter) {
125
- const rows = this.#db.prepare("SELECT key, value FROM kv").iterate();
126
- const result = [];
127
- for (const row of rows) {
128
- const key = row.key;
129
- const value = (0, import_node_v8.deserialize)(row.value);
130
- if (!filter || filter(key, value)) {
131
- result.push({ key, value });
132
- }
133
- }
134
- return result;
135
- }
136
- /**
137
- * Remove all entries from the database
138
- */
139
- clear() {
140
- this.#db.exec("DELETE FROM kv;");
141
- return this;
142
- }
143
- /**
144
- * Update the journal mode
145
- * @param mode New journal mode
146
- */
147
- setJournalMode(mode) {
148
- if (!journalModes.includes(mode)) {
149
- throw new Error(
150
- `[KVSync]: Invalid journal mode specified. Received: "${mode}", expected one of: ${journalModes.join(", ")}`
151
- );
152
- }
153
- this.#db.exec(`PRAGMA journal_mode = ${mode};`);
154
- return this;
155
- }
156
- /**
157
- * Perform a transaction
158
- * @param callback Callback with KVSync instance
159
- * @returns Object containing oldValues and newValues each containing arrays of keys and values
160
- */
161
- transaction(callback) {
162
- if (!callback) {
163
- throw new Error(
164
- "[KVSync]: A callback must be provided when using transaction()."
165
- );
166
- }
167
- if (typeof callback !== "function") {
168
- throw new Error(
169
- `[KVSync]: Transaction callback must be of type function. Received: ${typeof callback}`
170
- );
171
- }
172
- this.#db.exec("BEGIN TRANSACTION;");
173
- const oldMap = /* @__PURE__ */ new Map();
174
- const newMap = /* @__PURE__ */ new Map();
175
- const tx = Object.create(this);
176
- tx.set = (key, value) => {
177
- if (!oldMap.has(key)) {
178
- const oldValue = this.get(key);
179
- oldMap.set(key, oldValue === null ? void 0 : oldValue);
180
- }
181
- const result = this.set(key, value);
182
- newMap.set(key, result);
183
- return result;
184
- };
185
- tx.delete = (key) => {
186
- if (!oldMap.has(key)) {
187
- const oldValue = this.get(key);
188
- oldMap.set(key, oldValue === null ? void 0 : oldValue);
189
- }
190
- newMap.set(key, null);
191
- this.delete(key);
192
- return tx;
193
- };
194
- try {
195
- callback(tx);
196
- this.#db.exec("COMMIT;");
197
- } catch (error) {
198
- this.#db.exec("ROLLBACK;");
199
- throw error;
200
- }
201
- return {
202
- oldValues: Array.from(oldMap.entries()).map(([key, value]) => ({
203
- key,
204
- value
205
- })),
206
- newValues: Array.from(newMap.entries()).map(([key, value]) => ({
207
- key,
208
- value
209
- }))
210
- };
211
- }
212
- };
213
- // Annotate the CommonJS export names for ESM import in node:
214
- 0 && (module.exports = {
215
- KVSync,
216
- journalModes
217
- });