@liorandb/core 1.0.4 → 1.0.6

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.
@@ -0,0 +1,73 @@
1
+ import { ClassicLevel } from 'classic-level';
2
+
3
+ interface UpdateOptions$1 {
4
+ upsert?: boolean;
5
+ }
6
+ declare class Collection<T = any> {
7
+ dir: string;
8
+ db: ClassicLevel<string, string>;
9
+ private queue;
10
+ constructor(dir: string);
11
+ private _enqueue;
12
+ close(): Promise<void>;
13
+ insertOne(doc: T & {
14
+ _id?: string;
15
+ }): Promise<T>;
16
+ insertMany(docs?: (T & {
17
+ _id?: string;
18
+ })[]): Promise<T[]>;
19
+ find(query?: any): Promise<T[]>;
20
+ findOne(query?: any): Promise<T | null>;
21
+ updateOne(filter?: any, update?: any, options?: UpdateOptions$1): Promise<T | null>;
22
+ updateMany(filter?: any, update?: any): Promise<T[]>;
23
+ deleteOne(filter?: any): Promise<boolean>;
24
+ deleteMany(filter?: any): Promise<number>;
25
+ countDocuments(filter?: any): Promise<number>;
26
+ }
27
+
28
+ declare class LioranDB {
29
+ basePath: string;
30
+ dbName: string;
31
+ manager: LioranManager;
32
+ collections: Map<string, Collection>;
33
+ constructor(basePath: string, dbName: string, manager: LioranManager);
34
+ collection<T = any>(name: string): Collection<T>;
35
+ createCollection(name: string): Promise<boolean>;
36
+ deleteCollection(name: string): Promise<boolean>;
37
+ renameCollection(oldName: string, newName: string): Promise<boolean>;
38
+ dropCollection(name: string): Promise<boolean>;
39
+ listCollections(): Promise<string[]>;
40
+ }
41
+
42
+ interface LioranManagerOptions$1 {
43
+ rootPath?: string;
44
+ encryptionKey?: string | Buffer;
45
+ }
46
+ declare class LioranManager {
47
+ rootPath: string;
48
+ openDBs: Map<string, LioranDB>;
49
+ constructor(options?: LioranManagerOptions$1);
50
+ db(name: string): Promise<LioranDB>;
51
+ createDatabase(name: string): Promise<LioranDB>;
52
+ openDatabase(name: string): Promise<LioranDB>;
53
+ closeDatabase(name: string): Promise<void>;
54
+ renameDatabase(oldName: string, newName: string): Promise<boolean>;
55
+ deleteDatabase(name: string): Promise<boolean>;
56
+ dropDatabase(name: string): Promise<boolean>;
57
+ listDatabases(): Promise<string[]>;
58
+ }
59
+
60
+ declare function getBaseDBFolder(): string;
61
+
62
+ interface LioranManagerOptions {
63
+ rootPath?: string;
64
+ encryptionKey?: string | Buffer;
65
+ }
66
+ interface UpdateOptions {
67
+ upsert?: boolean;
68
+ }
69
+ type Query<T = any> = Partial<T> & {
70
+ [key: string]: any;
71
+ };
72
+
73
+ export { LioranDB, LioranManager, type LioranManagerOptions, type Query, type UpdateOptions, getBaseDBFolder };
package/dist/index.js ADDED
@@ -0,0 +1,440 @@
1
+ // src/LioranManager.ts
2
+ import path3 from "path";
3
+ import fs3 from "fs";
4
+
5
+ // src/core/database.ts
6
+ import path from "path";
7
+ import fs from "fs";
8
+
9
+ // src/core/collection.ts
10
+ import { ClassicLevel } from "classic-level";
11
+
12
+ // src/core/query.ts
13
+ function getByPath(obj, path4) {
14
+ return path4.split(".").reduce((o, p) => o ? o[p] : void 0, obj);
15
+ }
16
+ function matchDocument(doc, query) {
17
+ for (const key of Object.keys(query)) {
18
+ const cond = query[key];
19
+ const val = getByPath(doc, key);
20
+ if (cond && typeof cond === "object" && !Array.isArray(cond)) {
21
+ for (const op of Object.keys(cond)) {
22
+ const v = cond[op];
23
+ if (op === "$gt" && !(val > v)) return false;
24
+ if (op === "$gte" && !(val >= v)) return false;
25
+ if (op === "$lt" && !(val < v)) return false;
26
+ if (op === "$lte" && !(val <= v)) return false;
27
+ if (op === "$ne" && val === v) return false;
28
+ if (op === "$eq" && val !== v) return false;
29
+ if (op === "$in" && (!Array.isArray(v) || !v.includes(val)))
30
+ return false;
31
+ }
32
+ } else {
33
+ if (val !== cond) return false;
34
+ }
35
+ }
36
+ return true;
37
+ }
38
+ function applyUpdate(oldDoc, update) {
39
+ const doc = structuredClone(oldDoc);
40
+ if (update.$set) {
41
+ for (const k in update.$set) {
42
+ const parts = k.split(".");
43
+ let cur = doc;
44
+ for (let i = 0; i < parts.length - 1; i++) {
45
+ cur[parts[i]] ??= {};
46
+ cur = cur[parts[i]];
47
+ }
48
+ cur[parts.at(-1)] = update.$set[k];
49
+ }
50
+ }
51
+ if (update.$inc) {
52
+ for (const k in update.$inc) {
53
+ const val = getByPath(doc, k) ?? 0;
54
+ const parts = k.split(".");
55
+ let cur = doc;
56
+ for (let i = 0; i < parts.length - 1; i++) {
57
+ cur[parts[i]] ??= {};
58
+ cur = cur[parts[i]];
59
+ }
60
+ cur[parts.at(-1)] = val + update.$inc[k];
61
+ }
62
+ }
63
+ const hasOp = Object.keys(update).some((k) => k.startsWith("$"));
64
+ if (!hasOp) {
65
+ return { ...doc, ...update };
66
+ }
67
+ return doc;
68
+ }
69
+
70
+ // src/core/collection.ts
71
+ import { v4 as uuid } from "uuid";
72
+
73
+ // src/utils/encryption.ts
74
+ import crypto2 from "crypto";
75
+
76
+ // src/utils/secureKey.ts
77
+ import crypto from "crypto";
78
+ import os from "os";
79
+ function getMasterKey() {
80
+ const fingerprint = [
81
+ os.hostname(),
82
+ os.platform(),
83
+ os.arch(),
84
+ os.cpus()?.[0]?.model ?? "unknown",
85
+ os.cpus()?.length ?? 0,
86
+ os.totalmem()
87
+ ].join("|");
88
+ return crypto.createHash("sha256").update(fingerprint).digest();
89
+ }
90
+
91
+ // src/utils/encryption.ts
92
+ var algorithm = "aes-256-gcm";
93
+ var ACTIVE_KEY = getMasterKey();
94
+ function setEncryptionKey(key) {
95
+ if (!key) return;
96
+ if (typeof key === "string") {
97
+ ACTIVE_KEY = crypto2.createHash("sha256").update(key).digest();
98
+ return;
99
+ }
100
+ if (Buffer.isBuffer(key)) {
101
+ if (key.length !== 32) {
102
+ throw new Error("Encryption key must be 32 bytes");
103
+ }
104
+ ACTIVE_KEY = key;
105
+ return;
106
+ }
107
+ throw new Error("Invalid encryption key format");
108
+ }
109
+ function encryptData(obj) {
110
+ const iv = crypto2.randomBytes(16);
111
+ const data = Buffer.from(JSON.stringify(obj), "utf8");
112
+ const cipher = crypto2.createCipheriv(algorithm, ACTIVE_KEY, iv);
113
+ const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
114
+ const tag = cipher.getAuthTag();
115
+ return Buffer.concat([iv, tag, encrypted]).toString("base64");
116
+ }
117
+ function decryptData(enc) {
118
+ const buf = Buffer.from(enc, "base64");
119
+ const iv = buf.subarray(0, 16);
120
+ const tag = buf.subarray(16, 32);
121
+ const encrypted = buf.subarray(32);
122
+ const decipher = crypto2.createDecipheriv(algorithm, ACTIVE_KEY, iv);
123
+ decipher.setAuthTag(tag);
124
+ const decrypted = Buffer.concat([
125
+ decipher.update(encrypted),
126
+ decipher.final()
127
+ ]);
128
+ return JSON.parse(decrypted.toString("utf8"));
129
+ }
130
+
131
+ // src/core/collection.ts
132
+ var Collection = class {
133
+ dir;
134
+ db;
135
+ queue;
136
+ constructor(dir) {
137
+ this.dir = dir;
138
+ this.db = new ClassicLevel(dir);
139
+ this.queue = Promise.resolve();
140
+ }
141
+ _enqueue(task) {
142
+ this.queue = this.queue.then(task).catch(console.error);
143
+ return this.queue;
144
+ }
145
+ async close() {
146
+ try {
147
+ await this.db.close();
148
+ } catch {
149
+ }
150
+ }
151
+ async insertOne(doc) {
152
+ return this._enqueue(async () => {
153
+ const _id = doc._id ?? uuid();
154
+ const final = { _id, ...doc };
155
+ await this.db.put(String(_id), encryptData(final));
156
+ return final;
157
+ });
158
+ }
159
+ async insertMany(docs = []) {
160
+ return this._enqueue(async () => {
161
+ const ops = [];
162
+ const out = [];
163
+ for (const d of docs) {
164
+ const _id = d._id ?? uuid();
165
+ const final = { _id, ...d };
166
+ ops.push({
167
+ type: "put",
168
+ key: String(_id),
169
+ value: encryptData(final)
170
+ });
171
+ out.push(final);
172
+ }
173
+ await this.db.batch(ops);
174
+ return out;
175
+ });
176
+ }
177
+ async find(query = {}) {
178
+ return this._enqueue(async () => {
179
+ const out = [];
180
+ for await (const [, enc] of this.db.iterator()) {
181
+ const value = decryptData(enc);
182
+ if (matchDocument(value, query)) out.push(value);
183
+ }
184
+ return out;
185
+ });
186
+ }
187
+ async findOne(query = {}) {
188
+ return this._enqueue(async () => {
189
+ for await (const [, enc] of this.db.iterator()) {
190
+ const value = decryptData(enc);
191
+ if (matchDocument(value, query)) return value;
192
+ }
193
+ return null;
194
+ });
195
+ }
196
+ async updateOne(filter = {}, update = {}, options = { upsert: false }) {
197
+ return this._enqueue(async () => {
198
+ for await (const [key, enc] of this.db.iterator()) {
199
+ const value = decryptData(enc);
200
+ if (matchDocument(value, filter)) {
201
+ const updated = applyUpdate(value, update);
202
+ updated._id = value._id;
203
+ await this.db.put(key, encryptData(updated));
204
+ return updated;
205
+ }
206
+ }
207
+ if (options.upsert) {
208
+ const doc = applyUpdate(filter, update);
209
+ doc._id ??= uuid();
210
+ await this.db.put(String(doc._id), encryptData(doc));
211
+ return doc;
212
+ }
213
+ return null;
214
+ });
215
+ }
216
+ async updateMany(filter = {}, update = {}) {
217
+ return this._enqueue(async () => {
218
+ const updated = [];
219
+ for await (const [key, enc] of this.db.iterator()) {
220
+ const value = decryptData(enc);
221
+ if (matchDocument(value, filter)) {
222
+ const doc = applyUpdate(value, update);
223
+ doc._id = value._id;
224
+ await this.db.put(key, encryptData(doc));
225
+ updated.push(doc);
226
+ }
227
+ }
228
+ return updated;
229
+ });
230
+ }
231
+ async deleteOne(filter = {}) {
232
+ return this._enqueue(async () => {
233
+ for await (const [key, enc] of this.db.iterator()) {
234
+ const value = decryptData(enc);
235
+ if (matchDocument(value, filter)) {
236
+ await this.db.del(key);
237
+ return true;
238
+ }
239
+ }
240
+ return false;
241
+ });
242
+ }
243
+ async deleteMany(filter = {}) {
244
+ return this._enqueue(async () => {
245
+ let count = 0;
246
+ for await (const [key, enc] of this.db.iterator()) {
247
+ const value = decryptData(enc);
248
+ if (matchDocument(value, filter)) {
249
+ await this.db.del(key);
250
+ count++;
251
+ }
252
+ }
253
+ return count;
254
+ });
255
+ }
256
+ async countDocuments(filter = {}) {
257
+ return this._enqueue(async () => {
258
+ let c = 0;
259
+ for await (const [, enc] of this.db.iterator()) {
260
+ const value = decryptData(enc);
261
+ if (matchDocument(value, filter)) c++;
262
+ }
263
+ return c;
264
+ });
265
+ }
266
+ };
267
+
268
+ // src/core/database.ts
269
+ var LioranDB = class {
270
+ basePath;
271
+ dbName;
272
+ manager;
273
+ collections;
274
+ constructor(basePath, dbName, manager) {
275
+ this.basePath = basePath;
276
+ this.dbName = dbName;
277
+ this.manager = manager;
278
+ this.collections = /* @__PURE__ */ new Map();
279
+ if (!fs.existsSync(basePath)) {
280
+ fs.mkdirSync(basePath, { recursive: true });
281
+ }
282
+ }
283
+ collection(name) {
284
+ if (this.collections.has(name)) {
285
+ return this.collections.get(name);
286
+ }
287
+ const colPath = path.join(this.basePath, name);
288
+ if (!fs.existsSync(colPath)) {
289
+ fs.mkdirSync(colPath, { recursive: true });
290
+ }
291
+ const col = new Collection(colPath);
292
+ this.collections.set(name, col);
293
+ return col;
294
+ }
295
+ async createCollection(name) {
296
+ const colPath = path.join(this.basePath, name);
297
+ if (fs.existsSync(colPath)) {
298
+ throw new Error("Collection already exists");
299
+ }
300
+ await fs.promises.mkdir(colPath, { recursive: true });
301
+ this.collections.set(name, new Collection(colPath));
302
+ return true;
303
+ }
304
+ async deleteCollection(name) {
305
+ const colPath = path.join(this.basePath, name);
306
+ if (!fs.existsSync(colPath)) {
307
+ throw new Error("Collection does not exist");
308
+ }
309
+ if (this.collections.has(name)) {
310
+ await this.collections.get(name).close();
311
+ this.collections.delete(name);
312
+ }
313
+ await fs.promises.rm(colPath, { recursive: true, force: true });
314
+ return true;
315
+ }
316
+ async renameCollection(oldName, newName) {
317
+ const oldPath = path.join(this.basePath, oldName);
318
+ const newPath = path.join(this.basePath, newName);
319
+ if (!fs.existsSync(oldPath)) throw new Error("Collection does not exist");
320
+ if (fs.existsSync(newPath)) throw new Error("New collection name exists");
321
+ if (this.collections.has(oldName)) {
322
+ await this.collections.get(oldName).close();
323
+ this.collections.delete(oldName);
324
+ }
325
+ await fs.promises.rename(oldPath, newPath);
326
+ this.collections.set(newName, new Collection(newPath));
327
+ return true;
328
+ }
329
+ async dropCollection(name) {
330
+ return this.deleteCollection(name);
331
+ }
332
+ async listCollections() {
333
+ const dirs = await fs.promises.readdir(this.basePath, {
334
+ withFileTypes: true
335
+ });
336
+ return dirs.filter((d) => d.isDirectory()).map((d) => d.name);
337
+ }
338
+ };
339
+
340
+ // src/utils/rootpath.ts
341
+ import os2 from "os";
342
+ import path2 from "path";
343
+ import fs2 from "fs";
344
+ function getDefaultRootPath() {
345
+ let dbPath = process.env.LIORANDB_PATH;
346
+ if (!dbPath) {
347
+ const homeDir = os2.homedir();
348
+ dbPath = path2.join(homeDir, "LioranDB", "db");
349
+ if (!fs2.existsSync(dbPath)) {
350
+ fs2.mkdirSync(dbPath, { recursive: true });
351
+ }
352
+ process.env.LIORANDB_PATH = dbPath;
353
+ }
354
+ return dbPath;
355
+ }
356
+ function getBaseDBFolder() {
357
+ return getDefaultRootPath();
358
+ }
359
+
360
+ // src/LioranManager.ts
361
+ var LioranManager = class {
362
+ rootPath;
363
+ openDBs;
364
+ constructor(options = {}) {
365
+ const { rootPath, encryptionKey } = options;
366
+ this.rootPath = rootPath || getDefaultRootPath();
367
+ if (!fs3.existsSync(this.rootPath)) {
368
+ fs3.mkdirSync(this.rootPath, { recursive: true });
369
+ }
370
+ if (encryptionKey) {
371
+ setEncryptionKey(encryptionKey);
372
+ }
373
+ this.openDBs = /* @__PURE__ */ new Map();
374
+ }
375
+ async db(name) {
376
+ return this.openDatabase(name);
377
+ }
378
+ async createDatabase(name) {
379
+ const dbPath = path3.join(this.rootPath, name);
380
+ if (fs3.existsSync(dbPath)) {
381
+ throw new Error(`Database "${name}" already exists`);
382
+ }
383
+ await fs3.promises.mkdir(dbPath, { recursive: true });
384
+ return this.openDatabase(name);
385
+ }
386
+ async openDatabase(name) {
387
+ const dbPath = path3.join(this.rootPath, name);
388
+ if (!fs3.existsSync(dbPath)) {
389
+ await fs3.promises.mkdir(dbPath, { recursive: true });
390
+ }
391
+ if (this.openDBs.has(name)) {
392
+ return this.openDBs.get(name);
393
+ }
394
+ const db = new LioranDB(dbPath, name, this);
395
+ this.openDBs.set(name, db);
396
+ return db;
397
+ }
398
+ async closeDatabase(name) {
399
+ if (!this.openDBs.has(name)) return;
400
+ const db = this.openDBs.get(name);
401
+ for (const [, col] of db.collections.entries()) {
402
+ await col.close();
403
+ }
404
+ this.openDBs.delete(name);
405
+ }
406
+ async renameDatabase(oldName, newName) {
407
+ const oldPath = path3.join(this.rootPath, oldName);
408
+ const newPath = path3.join(this.rootPath, newName);
409
+ if (!fs3.existsSync(oldPath)) {
410
+ throw new Error(`Database "${oldName}" not found`);
411
+ }
412
+ if (fs3.existsSync(newPath)) {
413
+ throw new Error(`Database "${newName}" already exists`);
414
+ }
415
+ await this.closeDatabase(oldName);
416
+ await fs3.promises.rename(oldPath, newPath);
417
+ return true;
418
+ }
419
+ async deleteDatabase(name) {
420
+ return this.dropDatabase(name);
421
+ }
422
+ async dropDatabase(name) {
423
+ const dbPath = path3.join(this.rootPath, name);
424
+ if (!fs3.existsSync(dbPath)) return false;
425
+ await this.closeDatabase(name);
426
+ await fs3.promises.rm(dbPath, { recursive: true, force: true });
427
+ return true;
428
+ }
429
+ async listDatabases() {
430
+ const items = await fs3.promises.readdir(this.rootPath, {
431
+ withFileTypes: true
432
+ });
433
+ return items.filter((i) => i.isDirectory()).map((i) => i.name);
434
+ }
435
+ };
436
+ export {
437
+ LioranDB,
438
+ LioranManager,
439
+ getBaseDBFolder
440
+ };
package/package.json CHANGED
@@ -1,27 +1,38 @@
1
- {
2
- "name": "@liorandb/core",
3
- "version": "1.0.4",
4
- "description": "LioranDB is a lightweight, local-first, peer-to-peer, file-based database with a MongoDB-style Node.js API and a simple CLI for seamless distributed development.",
5
- "main": "./src/index.js",
6
- "types": "./src/index.d.ts",
7
- "type": "module",
8
- "scripts": {},
9
- "bin": {},
10
- "keywords": [
11
- "p2p-database",
12
- "lioran",
13
- "liorandb",
14
- "p2p-db",
15
- "peer-to-peer-db",
16
- "peer-to-peer-database",
17
- "localfirst-db",
18
- "localfirst-database"
19
- ],
20
- "author": "Swaraj Puppalwar",
21
- "license": "LIORANDB LICENSE",
22
- "dependencies": {
23
- "classic-level": "^1.3.0",
24
- "crypto": "^1.0.1",
25
- "uuid": "^9.0.0"
26
- }
27
- }
1
+ {
2
+ "name": "@liorandb/core",
3
+ "version": "1.0.6",
4
+ "description": "**LioranDB Core Module** – Lightweight, local-first, peer-to-peer database management for Node.js.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup src/index.ts --dts --format esm",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/LioranGroups/Liorandb.git"
20
+ },
21
+ "keywords": [],
22
+ "author": "",
23
+ "license": "ISC",
24
+ "type": "module",
25
+ "bugs": {
26
+ "url": "https://github.com/LioranGroups/Liorandb/issues"
27
+ },
28
+ "homepage": "https://github.com/LioranGroups/Liorandb#readme",
29
+ "dependencies": {
30
+ "classic-level": "^3.0.0",
31
+ "uuid": "^13.0.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.2.0",
35
+ "tsup": "^8.5.1",
36
+ "typescript": "^5.9.3"
37
+ }
38
+ }
@@ -4,21 +4,24 @@ import { LioranDB } from "./core/database.js";
4
4
  import { setEncryptionKey } from "./utils/encryption.js";
5
5
  import { getDefaultRootPath } from "./utils/rootpath.js";
6
6
 
7
+ export interface LioranManagerOptions {
8
+ rootPath?: string;
9
+ encryptionKey?: string | Buffer;
10
+ }
11
+
7
12
  export class LioranManager {
8
- constructor(options = {}) {
9
- const {
10
- rootPath,
11
- encryptionKey
12
- } = options;
13
+ rootPath: string;
14
+ openDBs: Map<string, LioranDB>;
15
+
16
+ constructor(options: LioranManagerOptions = {}) {
17
+ const { rootPath, encryptionKey } = options;
13
18
 
14
- // Root DB path (custom OR default)
15
19
  this.rootPath = rootPath || getDefaultRootPath();
16
20
 
17
21
  if (!fs.existsSync(this.rootPath)) {
18
22
  fs.mkdirSync(this.rootPath, { recursive: true });
19
23
  }
20
24
 
21
- // Optional custom encryption key
22
25
  if (encryptionKey) {
23
26
  setEncryptionKey(encryptionKey);
24
27
  }
@@ -26,11 +29,11 @@ export class LioranManager {
26
29
  this.openDBs = new Map();
27
30
  }
28
31
 
29
- async db(name) {
32
+ async db(name: string): Promise<LioranDB> {
30
33
  return this.openDatabase(name);
31
34
  }
32
35
 
33
- async createDatabase(name) {
36
+ async createDatabase(name: string): Promise<LioranDB> {
34
37
  const dbPath = path.join(this.rootPath, name);
35
38
 
36
39
  if (fs.existsSync(dbPath)) {
@@ -41,7 +44,7 @@ export class LioranManager {
41
44
  return this.openDatabase(name);
42
45
  }
43
46
 
44
- async openDatabase(name) {
47
+ async openDatabase(name: string): Promise<LioranDB> {
45
48
  const dbPath = path.join(this.rootPath, name);
46
49
 
47
50
  if (!fs.existsSync(dbPath)) {
@@ -49,19 +52,18 @@ export class LioranManager {
49
52
  }
50
53
 
51
54
  if (this.openDBs.has(name)) {
52
- return this.openDBs.get(name);
55
+ return this.openDBs.get(name)!;
53
56
  }
54
57
 
55
58
  const db = new LioranDB(dbPath, name, this);
56
59
  this.openDBs.set(name, db);
57
-
58
60
  return db;
59
61
  }
60
62
 
61
- async closeDatabase(name) {
63
+ async closeDatabase(name: string): Promise<void> {
62
64
  if (!this.openDBs.has(name)) return;
63
65
 
64
- const db = this.openDBs.get(name);
66
+ const db = this.openDBs.get(name)!;
65
67
 
66
68
  for (const [, col] of db.collections.entries()) {
67
69
  await col.close();
@@ -70,7 +72,7 @@ export class LioranManager {
70
72
  this.openDBs.delete(name);
71
73
  }
72
74
 
73
- async renameDatabase(oldName, newName) {
75
+ async renameDatabase(oldName: string, newName: string): Promise<boolean> {
74
76
  const oldPath = path.join(this.rootPath, oldName);
75
77
  const newPath = path.join(this.rootPath, newName);
76
78
 
@@ -86,11 +88,11 @@ export class LioranManager {
86
88
  return true;
87
89
  }
88
90
 
89
- async deleteDatabase(name) {
91
+ async deleteDatabase(name: string): Promise<boolean> {
90
92
  return this.dropDatabase(name);
91
93
  }
92
94
 
93
- async dropDatabase(name) {
95
+ async dropDatabase(name: string): Promise<boolean> {
94
96
  const dbPath = path.join(this.rootPath, name);
95
97
 
96
98
  if (!fs.existsSync(dbPath)) return false;
@@ -100,8 +102,11 @@ export class LioranManager {
100
102
  return true;
101
103
  }
102
104
 
103
- async listDatabases() {
104
- const items = await fs.promises.readdir(this.rootPath, { withFileTypes: true });
105
+ async listDatabases(): Promise<string[]> {
106
+ const items = await fs.promises.readdir(this.rootPath, {
107
+ withFileTypes: true
108
+ });
109
+
105
110
  return items.filter(i => i.isDirectory()).map(i => i.name);
106
111
  }
107
112
  }