@jsonkit/db 3.0.2 → 4.1.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/dist/esm/index.js CHANGED
@@ -3,13 +3,42 @@ import * as path from 'path';
3
3
  import * as fsSync from 'fs';
4
4
  import * as readline from 'readline';
5
5
 
6
+ class DbError extends Error {
7
+ }
8
+ class NotFoundError extends DbError {
9
+ }
10
+ class ConflictError extends DbError {
11
+ }
12
+ class FileIoError extends DbError {
13
+ }
14
+ class InvalidIdError extends DbError {
15
+ constructor(id) {
16
+ super(`Invalid entry id '${id}'`);
17
+ }
18
+ }
19
+ class UninitError extends DbError {
20
+ constructor() {
21
+ super('Cannot read or update uninitialized entry. Use write(entry) to initialize first');
22
+ }
23
+ }
24
+
6
25
  class MultiEntryDb {
7
26
  async getByIdOrThrow(id) {
8
27
  const entry = await this.getById(id);
9
28
  if (!entry)
10
- throw new Error(`Entry with id '${id}' does not exist`);
29
+ throw new NotFoundError(`Entry with id '${id}' does not exist`);
11
30
  return entry;
12
31
  }
32
+ async getFirstWhere(predicate) {
33
+ const matches = await this.getWhere(predicate, { page: 0, take: 1 });
34
+ return matches.at(0) ?? null;
35
+ }
36
+ async getFirstWhereOrThrow(predicate) {
37
+ const match = await this.getFirstWhere(predicate);
38
+ if (!match)
39
+ throw new NotFoundError('No entry matches predicate');
40
+ return match;
41
+ }
13
42
  async getWhere(predicate, pagination) {
14
43
  let totalMatched = 0;
15
44
  const entries = [];
@@ -103,6 +132,13 @@ class MultiEntryDb {
103
132
  }
104
133
  }
105
134
 
135
+ class SingleEntryDb {
136
+ }
137
+
138
+ function runJsonEntryParser(parser, text) {
139
+ return typeof parser === 'function' ? parser(text) : parser.parse(text);
140
+ }
141
+
106
142
  var FileType;
107
143
  (function (FileType) {
108
144
  FileType["File"] = "file";
@@ -119,7 +155,7 @@ class Files {
119
155
  const { recursive = false, overwrite = true } = options ?? {};
120
156
  // Check if destination exists and handle overwrite
121
157
  if (!overwrite && (await this.exists(destinationPath))) {
122
- throw new Error(`Destination '${destinationPath}' already exists`);
158
+ throw new FileIoError(`Destination '${destinationPath}' already exists`);
123
159
  }
124
160
  const sourceStats = await fs.stat(sourcePath);
125
161
  if (sourceStats.isFile()) {
@@ -130,7 +166,7 @@ class Files {
130
166
  }
131
167
  if (sourceStats.isDirectory()) {
132
168
  if (!recursive) {
133
- throw new Error(`'${sourcePath}' is a directory (use recursive option)`);
169
+ throw new FileIoError(`'${sourcePath}' is a directory (use recursive option)`);
134
170
  }
135
171
  await this.copyRecursive(sourcePath, destinationPath);
136
172
  }
@@ -267,7 +303,7 @@ class Files {
267
303
  ...commonMeta,
268
304
  type: FileType.File,
269
305
  };
270
- throw new Error(`File at ${filepath} is not normal file or directory`);
306
+ throw new FileIoError(`File at ${filepath} is not normal file or directory`);
271
307
  }
272
308
  async list(dirpath, options) {
273
309
  const { depth = 0, stripBasepath } = options ?? {};
@@ -320,6 +356,10 @@ class Files {
320
356
  }
321
357
 
322
358
  class MultiEntryFileDb extends MultiEntryDb {
359
+ dirpath;
360
+ files;
361
+ parser;
362
+ noPathlikeIds;
323
363
  constructor(dirpath, options) {
324
364
  super();
325
365
  this.dirpath = dirpath;
@@ -333,11 +373,11 @@ class MultiEntryFileDb extends MultiEntryDb {
333
373
  }
334
374
  async getById(id) {
335
375
  if (!this.isIdValid(id))
336
- throw new Error(`Invalid id: ${id}`);
376
+ throw new InvalidIdError(id);
337
377
  try {
338
378
  const filepath = this.getFilePath(id);
339
379
  const text = await this.files.read(filepath);
340
- const entry = this.parser.parse(text);
380
+ const entry = runJsonEntryParser(this.parser, text);
341
381
  return entry;
342
382
  }
343
383
  catch (error) {
@@ -374,19 +414,18 @@ class MultiEntryFileDb extends MultiEntryDb {
374
414
  await this.files.delete(this.dirpath);
375
415
  }
376
416
  getFilePath(id) {
377
- return path.join(this.dirpath, `${id}.json`);
417
+ return path.join(this.dirpath, `${String(id)}.json`);
378
418
  }
379
419
  async writeEntry(entry) {
380
420
  if (!this.isIdValid(entry.id))
381
- throw new Error(`Invalid id: ${entry.id}`);
421
+ throw new InvalidIdError(entry.id);
382
422
  const filepath = this.getFilePath(entry.id);
383
423
  await this.files.write(filepath, JSON.stringify(entry, null, 2));
384
424
  }
385
- isIdValid(id) {
386
- if (typeof id !== 'string')
387
- return false;
425
+ isIdValid(rawId) {
388
426
  if (!this.noPathlikeIds)
389
427
  return true;
428
+ const id = String(rawId);
390
429
  if (id.includes('/') || id.includes('\\'))
391
430
  return false;
392
431
  return true;
@@ -398,23 +437,27 @@ class MultiEntryFileDb extends MultiEntryDb {
398
437
  yield entry;
399
438
  }
400
439
  }
401
- async *iterIds() {
440
+ async *iterIds(objectIdParser) {
402
441
  const filenames = await this.files.list(this.dirpath);
403
442
  for (const filename of filenames) {
404
443
  if (!filename.endsWith('.json'))
405
444
  continue;
406
- const id = filename.replace(/\.json$/, '');
445
+ const stringId = filename.replace(/\.json$/, '');
446
+ const id = objectIdParser ? runJsonEntryParser(objectIdParser, stringId) : stringId;
407
447
  if (this.isIdValid(id))
408
448
  yield id;
409
449
  }
410
450
  }
411
451
  }
412
452
 
413
- class SingleEntryFileDb {
453
+ class SingleEntryFileDb extends SingleEntryDb {
454
+ filepath;
455
+ parser;
456
+ files = new Files();
414
457
  constructor(filepath, parser = JSON) {
458
+ super();
415
459
  this.filepath = filepath;
416
460
  this.parser = parser;
417
- this.files = new Files();
418
461
  }
419
462
  path() {
420
463
  return this.filepath;
@@ -425,7 +468,7 @@ class SingleEntryFileDb {
425
468
  }
426
469
  async read() {
427
470
  const text = await this.files.read(this.filepath);
428
- const entry = this.parser.parse(text);
471
+ const entry = runJsonEntryParser(this.parser, text);
429
472
  return entry;
430
473
  }
431
474
  async write(updaterOrEntry) {
@@ -448,10 +491,7 @@ class SingleEntryFileDb {
448
491
  }
449
492
 
450
493
  class MultiEntryMemDb extends MultiEntryDb {
451
- constructor() {
452
- super(...arguments);
453
- this.entries = new Map();
454
- }
494
+ entries = new Map();
455
495
  async create(entry) {
456
496
  this.entries.set(entry.id, entry);
457
497
  return entry;
@@ -484,28 +524,41 @@ class MultiEntryMemDb extends MultiEntryDb {
484
524
  yield id;
485
525
  }
486
526
  }
527
+ async persist(dirpath) {
528
+ const fileDb = new MultiEntryFileDb(dirpath);
529
+ await fileDb.destroy();
530
+ const values = [...this.entries.values()];
531
+ await Promise.all(values.map((entry) => fileDb.create(entry)));
532
+ }
533
+ async load(dirpath, parser) {
534
+ const fileDb = new MultiEntryFileDb(dirpath, { parser });
535
+ await this.destroy();
536
+ for await (const entry of fileDb.iterEntries()) {
537
+ await this.create(entry);
538
+ }
539
+ }
487
540
  }
488
541
 
489
- class SingleEntryMemDb {
542
+ class SingleEntryMemDb extends SingleEntryDb {
543
+ entry = null;
490
544
  constructor(initialEntry = null) {
491
- this.entry = null;
545
+ super();
492
546
  this.entry = initialEntry;
493
547
  }
494
- isInited() {
548
+ async isInited() {
495
549
  return this.entry !== null;
496
550
  }
497
- read() {
551
+ async read() {
498
552
  if (this.entry === null)
499
- throw new Error('Entry not initialized');
553
+ throw new UninitError();
500
554
  return this.entry;
501
555
  }
502
- write(updaterOrEntry) {
556
+ async write(updaterOrEntry) {
503
557
  let entry;
504
558
  if (typeof updaterOrEntry === 'function') {
505
559
  const updater = updaterOrEntry;
506
- if (this.entry === null) {
507
- throw new Error('Cannot update uninitialized entry. Use write(entry) to initialize first.');
508
- }
560
+ if (this.entry === null)
561
+ throw new UninitError();
509
562
  const updatedFields = updater(this.entry);
510
563
  entry = { ...this.entry, ...updatedFields };
511
564
  }
@@ -515,10 +568,19 @@ class SingleEntryMemDb {
515
568
  this.entry = entry;
516
569
  return entry;
517
570
  }
518
- delete() {
571
+ async delete() {
519
572
  this.entry = null;
520
573
  }
574
+ async persist(filepath) {
575
+ const fileDb = new SingleEntryFileDb(filepath);
576
+ await fileDb.write(await this.read());
577
+ }
578
+ async load(filepath, parser) {
579
+ const fileDb = new SingleEntryFileDb(filepath, parser);
580
+ const persistedEntry = await fileDb.read();
581
+ this.write(persistedEntry);
582
+ }
521
583
  }
522
584
 
523
- export { FileType, MultiEntryFileDb, MultiEntryMemDb, SingleEntryFileDb, SingleEntryMemDb };
585
+ export { ConflictError, DbError, FileIoError, FileType, InvalidIdError, MultiEntryFileDb, MultiEntryMemDb, NotFoundError, SingleEntryFileDb, SingleEntryMemDb, UninitError };
524
586
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/common/multiEntryDb.ts","../../../src/common/types.ts","../../../src/file/files.ts","../../../src/file/multiEntryFileDb.ts","../../../src/file/singleEntryFileDb.ts","../../../src/memory/multiEntryMemDb.ts","../../../src/memory/singleEntryMemDb.ts"],"sourcesContent":["import type {\n Identifiable,\n DeleteManyOutput,\n PaginationInput,\n PredicateFn,\n Promisable,\n} from './types'\n\nexport abstract class MultiEntryDb<T extends Identifiable> {\n abstract create(entry: T): Promise<T>\n\n abstract getById(id: T['id']): Promise<T | null>\n\n abstract update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T>\n\n abstract deleteById(id: T['id']): Promise<boolean>\n\n abstract destroy(): Promise<void>\n\n protected abstract iterEntries(): AsyncIterable<T>\n\n protected abstract iterIds(): AsyncIterable<T['id']>\n\n async getByIdOrThrow(id: T['id']): Promise<T> {\n const entry = await this.getById(id)\n if (!entry) throw new Error(`Entry with id '${id}' does not exist`)\n return entry\n }\n\n async getWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<T[]> {\n let totalMatched = 0\n const entries: T[] = []\n\n if (!pagination) {\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) entries.push(entry)\n }\n return entries\n }\n\n const { take, page } = pagination\n const skip = pagination.skip ?? 0\n const startIndex = (page - 1) * take + skip\n const endIndex = startIndex + take\n\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) {\n if (totalMatched >= startIndex && totalMatched < endIndex) {\n entries.push(entry)\n }\n totalMatched++\n\n if (totalMatched >= endIndex) break\n }\n }\n\n return entries\n }\n\n getAll(): Promise<T[]> {\n return this.getWhere(() => true)\n }\n\n async getAllIds(): Promise<T['id'][]> {\n const ids: T['id'][] = []\n for await (const id of this.iterIds()) {\n ids.push(id)\n }\n return ids\n }\n\n deleteByIds(ids: T['id'][]): Promise<DeleteManyOutput> {\n return this.deleteWhere((entry) => ids.includes(entry.id))\n }\n\n async deleteWhere(predicate: PredicateFn<T>): Promise<DeleteManyOutput> {\n const deletedIds: T['id'][] = []\n const ignoredIds: T['id'][] = []\n\n for await (const entry of this.iterEntries()) {\n if (!predicate(entry)) continue\n\n const didDelete = await this.deleteById(entry.id)\n if (didDelete) {\n deletedIds.push(entry.id)\n } else {\n ignoredIds.push(entry.id)\n }\n }\n\n return { deletedIds, ignoredIds }\n }\n\n async exists(id: T['id']): Promise<boolean> {\n const entry = await this.getById(id)\n return entry !== null\n }\n\n countAll(): Promise<number> {\n return this.countWhere(() => true)\n }\n\n async countWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<number> {\n let totalMatched = 0\n let count = 0\n\n if (!pagination) {\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) count++\n }\n return count\n }\n\n const { take, page } = pagination\n const skip = pagination.skip ?? 0\n const startIndex = (page - 1) * take + skip\n const endIndex = startIndex + take\n\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) {\n if (totalMatched >= startIndex && totalMatched < endIndex) count++\n totalMatched++\n\n if (totalMatched >= endIndex) break\n }\n }\n\n return count\n }\n}\n","export type Identifiable = {\n id: Id\n}\n\nexport type Id = string\n\nexport type Promisable<T> = T | Promise<T>\n\nexport type PaginationInput = {\n take: number\n page: number\n skip?: number | undefined | null\n}\n\nexport type DeleteManyOutput = {\n deletedIds: Id[]\n ignoredIds: Id[]\n}\n\nexport type PredicateFn<T extends Identifiable> = (entry: T) => boolean\n\nexport type JsonEntryParser<T> = {\n parse: (text: string) => T\n}\n\nexport type MultiEntryFileDbOptions<T> = {\n noPathlikeIds?: boolean\n parser?: JsonEntryParser<T>\n}\n\nexport type FileMeta = {\n path: string\n size: number\n created: Date\n modified: Date\n accessed: Date\n} & (\n | {\n type: FileType.File\n }\n | {\n type: FileType.Directory\n children: FileMeta[]\n }\n)\n\nexport enum FileType {\n File = 'file',\n Directory = 'directory',\n //Symlink: 'symlink'\n}\n","import type { FileMeta } from '../common/types'\nimport { FileType } from '../common/types'\nimport * as fs from 'fs/promises'\nimport * as path from 'path'\nimport * as fsSync from 'fs'\nimport * as readline from 'readline'\n\ntype ListOptions = {\n depth?: number\n stripBasepath?: string\n}\n\ntype DeleteOptions = {\n force?: boolean\n recursive?: boolean\n}\n\ntype WriteOptions = {\n encoding?: BufferEncoding\n}\n\ntype ReadOptions = {\n encoding?: BufferEncoding\n lines?: number\n}\n\ntype CopyOptions = {\n recursive?: boolean\n overwrite?: boolean\n}\n\nconst DEFUALT_ENCODING: BufferEncoding = 'utf-8'\n\nexport class Files {\n async move(oldPath: string, newPath: string) {\n await fs.rename(oldPath, newPath)\n }\n\n async copy(sourcePath: string, destinationPath: string, options?: CopyOptions) {\n const { recursive = false, overwrite = true } = options ?? {}\n\n // Check if destination exists and handle overwrite\n if (!overwrite && (await this.exists(destinationPath))) {\n throw new Error(`Destination '${destinationPath}' already exists`)\n }\n\n const sourceStats = await fs.stat(sourcePath)\n\n if (sourceStats.isFile()) {\n const destinationDir = path.dirname(destinationPath)\n await this.mkdirUnsafe(destinationDir)\n await fs.copyFile(sourcePath, destinationPath)\n return\n }\n\n if (sourceStats.isDirectory()) {\n if (!recursive) {\n throw new Error(`'${sourcePath}' is a directory (use recursive option)`)\n }\n await this.copyRecursive(sourcePath, destinationPath)\n }\n }\n\n async copyRecursive(sourcePath: string, destinationPath: string) {\n const sourceStats = await fs.stat(sourcePath)\n\n if (sourceStats.isFile()) {\n const destinationDir = path.dirname(destinationPath)\n await this.mkdirUnsafe(destinationDir)\n await fs.copyFile(sourcePath, destinationPath)\n return\n }\n\n if (sourceStats.isDirectory()) {\n await this.mkdirUnsafe(destinationPath)\n const entries = await fs.readdir(sourcePath)\n\n for (const entry of entries) {\n const sourceEntryPath = path.join(sourcePath, entry)\n const destEntryPath = path.join(destinationPath, entry)\n await this.copyRecursive(sourceEntryPath, destEntryPath)\n }\n }\n }\n\n async mkdir(filepath: string) {\n await this.mkdirUnsafe(filepath)\n }\n\n protected async mkdirUnsafe(filepath: string) {\n await fs.mkdir(filepath, { recursive: true })\n }\n\n async write(filepath: string, content: string, options?: WriteOptions) {\n const { encoding = DEFUALT_ENCODING } = options ?? {}\n\n const parentDirs = path.dirname(filepath)\n await this.mkdirUnsafe(parentDirs)\n\n await fs.writeFile(filepath, content, encoding)\n }\n\n async touch(filepath: string) {\n const exists = await this.exists(filepath)\n if (!exists) await this.write(filepath, '')\n }\n\n async read(filepath: string, options?: ReadOptions) {\n const { encoding = DEFUALT_ENCODING, lines } = options ?? {}\n\n if (lines === undefined) {\n return await fs.readFile(filepath, encoding)\n }\n\n const stream = fsSync.createReadStream(filepath, { encoding })\n const reader = readline.createInterface({\n input: stream,\n crlfDelay: Infinity,\n })\n\n let result = ''\n let linesRead = 0\n for await (const line of reader) {\n if (linesRead >= lines) break\n result += line + '\\n'\n linesRead++\n }\n\n return result\n }\n\n async delete(filepath: string, options?: DeleteOptions) {\n const { force = true, recursive = true } = options ?? {}\n await fs.rm(filepath, { force, recursive })\n }\n\n async exists(filepath: string) {\n try {\n await fs.access(filepath)\n return true\n } catch {\n return false\n }\n }\n\n async isDir(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isDirectory()\n } catch {\n return false\n }\n }\n\n async isFile(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isFile()\n } catch {\n return false\n }\n }\n\n async isSymlink(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isSymbolicLink()\n } catch {\n return false\n }\n }\n\n async getMeta(filepath: string, options?: ListOptions): Promise<FileMeta> {\n const { depth = 0, stripBasepath } = options ?? {}\n const stats = await fs.stat(filepath)\n const isDir = stats.isDirectory()\n const isFile = stats.isFile()\n\n const { size, ctime, mtime, atime } = stats\n const commonMeta = {\n path: this.stripBasepath(filepath, stripBasepath),\n size,\n created: ctime,\n modified: mtime,\n accessed: atime,\n }\n\n if (isDir) {\n const children: FileMeta[] = []\n\n if (depth > 0) {\n const childNames = await this.list(filepath)\n\n for (const child of childNames) {\n const childDepth = Math.max(0, depth - 1)\n const childMeta = await this.getMeta(path.join(filepath, child), {\n depth: childDepth,\n stripBasepath,\n })\n children.push(childMeta)\n }\n }\n\n return {\n ...commonMeta,\n type: FileType.Directory,\n children,\n }\n }\n if (isFile)\n return {\n ...commonMeta,\n type: FileType.File,\n }\n\n throw new Error(`File at ${filepath} is not normal file or directory`)\n }\n\n async list(dirpath: string, options?: ListOptions) {\n const { depth = 0, stripBasepath } = options ?? {}\n if (depth > 0) {\n return await this.listRecursive(dirpath, depth, 0, stripBasepath)\n }\n return await fs.readdir(dirpath)\n }\n\n async *listRead(dirpath: string, options?: ListOptions) {\n const { depth = 0 } = options ?? {}\n\n const files = await this.list(dirpath, { depth })\n\n for (const filepath of files) {\n const isFile = await this.isFile(filepath)\n if (!isFile) continue\n\n try {\n const content = await this.read(filepath)\n yield {\n filepath,\n content,\n }\n } catch {\n // Skip files that can't be read\n continue\n }\n }\n }\n\n protected async listRecursive(\n dirpath: string,\n maxDepth: number,\n currentDepth: number,\n stripBasepath: string | undefined,\n ): Promise<string[]> {\n const results: string[] = []\n const entries = await fs.readdir(dirpath, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dirpath, entry.name)\n const strippedPath = this.stripBasepath(fullPath, stripBasepath)\n results.push(strippedPath)\n\n if (entry.isDirectory() && currentDepth < maxDepth) {\n const subResults = await this.listRecursive(\n fullPath,\n maxDepth,\n currentDepth + 1,\n stripBasepath,\n )\n results.push(...subResults)\n }\n }\n\n return results\n }\n\n protected stripBasepath(original: string, pathToStrip: string | undefined): string {\n if (!pathToStrip) return original\n const base = pathToStrip.replace(/^\\/+/, '/').replace(/\\/+$/, '/')\n const stripped = original.replace(base, '')\n return `/${stripped}`\n }\n}\n","import {\n Identifiable,\n DeleteManyOutput,\n Promisable,\n JsonEntryParser,\n MultiEntryFileDbOptions,\n MultiEntryDb,\n} from '../common'\nimport { Files } from './files'\nimport * as path from 'path'\n\nexport class MultiEntryFileDb<T extends Identifiable> extends MultiEntryDb<T> {\n protected readonly dirpath: string\n protected readonly files: Files\n protected readonly parser: JsonEntryParser<T>\n readonly noPathlikeIds: boolean\n\n constructor(dirpath: string, options?: MultiEntryFileDbOptions<T>) {\n super()\n this.dirpath = dirpath\n this.files = new Files()\n this.parser = options?.parser ?? JSON\n this.noPathlikeIds = options?.noPathlikeIds ?? true\n }\n\n async create(entry: T): Promise<T> {\n await this.writeEntry(entry)\n return entry\n }\n\n async getById(id: T['id']): Promise<T | null> {\n if (!this.isIdValid(id)) throw new Error(`Invalid id: ${id}`)\n\n try {\n const filepath = this.getFilePath(id)\n const text = await this.files.read(filepath)\n const entry = this.parser.parse(text)\n return entry\n } catch (error) {\n console.error('Failed to read entry', error)\n // File doesn't exist or invalid JSON\n return null\n }\n }\n\n async update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T> {\n const entry = await this.getByIdOrThrow(id)\n\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n await this.writeEntry(updatedEntry)\n\n if (updatedEntry.id !== id) {\n await this.deleteById(id)\n }\n\n return updatedEntry\n }\n\n async deleteById(id: T['id']): Promise<boolean> {\n try {\n const filepath = this.getFilePath(id)\n await this.files.delete(filepath, { force: false })\n return true\n } catch {\n // File might not exist, ignore error\n return false\n }\n }\n\n async deleteByIds(ids: T['id'][]): Promise<DeleteManyOutput> {\n return this.deleteWhere((entry) => ids.includes(entry.id))\n }\n\n async destroy() {\n await this.files.delete(this.dirpath)\n }\n\n protected getFilePath(id: T['id']) {\n return path.join(this.dirpath, `${id}.json`)\n }\n\n protected async writeEntry(entry: T) {\n if (!this.isIdValid(entry.id)) throw new Error(`Invalid id: ${entry.id}`)\n\n const filepath = this.getFilePath(entry.id)\n await this.files.write(filepath, JSON.stringify(entry, null, 2))\n }\n\n isIdValid(id: T['id']): boolean {\n if (typeof id !== 'string') return false\n\n if (!this.noPathlikeIds) return true\n\n if (id.includes('/') || id.includes('\\\\')) return false\n\n return true\n }\n\n protected async *iterEntries() {\n for await (const id of this.iterIds()) {\n const entry = await this.getById(id)\n if (entry) yield entry\n }\n }\n\n protected async *iterIds() {\n const filenames = await this.files.list(this.dirpath)\n for (const filename of filenames) {\n if (!filename.endsWith('.json')) continue\n\n const id = filename.replace(/\\.json$/, '')\n if (this.isIdValid(id)) yield id\n }\n }\n}\n","import { JsonEntryParser, Promisable } from '../common/types'\nimport { Files } from './files'\n\nexport class SingleEntryFileDb<T> {\n protected readonly files: Files = new Files()\n\n constructor(\n protected readonly filepath: string,\n protected readonly parser: JsonEntryParser<T> = JSON,\n ) {}\n\n path() {\n return this.filepath\n }\n\n async isInited() {\n const exists = await this.files.exists(this.filepath)\n return exists\n }\n\n async read() {\n const text = await this.files.read(this.filepath)\n const entry = this.parser.parse(text)\n return entry\n }\n\n async write(updaterOrEntry: T | ((entry: T) => Promisable<Partial<T>>)): Promise<T> {\n let entry: T\n if (typeof updaterOrEntry === 'function') {\n const updater = updaterOrEntry as (entry: T) => T\n const existing = await this.read()\n\n const updatedFields = await updater(existing)\n entry = { ...existing, ...updatedFields }\n } else {\n entry = updaterOrEntry\n }\n\n await this.files.write(this.filepath, JSON.stringify(entry, null, 2))\n\n return entry\n }\n\n async delete(): Promise<void> {\n await this.files.delete(this.filepath)\n }\n}\n","import { Identifiable, Promisable, MultiEntryDb } from '../common'\n\nexport class MultiEntryMemDb<T extends Identifiable> extends MultiEntryDb<T> {\n protected entries: Map<T['id'], T> = new Map()\n\n async create(entry: T): Promise<T> {\n this.entries.set(entry.id, entry)\n return entry\n }\n\n async getById(id: T['id']): Promise<T | null> {\n return this.entries.get(id) ?? null\n }\n\n async update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T> {\n const entry = await this.getByIdOrThrow(id)\n\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n\n this.entries.set(updatedEntry.id, updatedEntry)\n\n if (updatedEntry.id !== id) this.entries.delete(id)\n\n return updatedEntry\n }\n\n async deleteById(id: T['id']): Promise<boolean> {\n return this.entries.delete(id)\n }\n\n async destroy() {\n this.entries.clear()\n }\n\n protected async *iterEntries() {\n for (const entry of this.entries.values()) {\n yield entry\n }\n }\n\n protected async *iterIds() {\n for (const id of this.entries.keys()) {\n yield id\n }\n }\n}\n","export class SingleEntryMemDb<T> {\n protected entry: T | null = null\n\n constructor(initialEntry: T | null = null) {\n this.entry = initialEntry\n }\n\n isInited() {\n return this.entry !== null\n }\n\n read(): T {\n if (this.entry === null) throw new Error('Entry not initialized')\n return this.entry\n }\n\n write(updaterOrEntry: T | ((entry: T) => Partial<T>)): T {\n let entry: T\n\n if (typeof updaterOrEntry === 'function') {\n const updater = updaterOrEntry as (entry: T) => Partial<T>\n\n if (this.entry === null) {\n throw new Error('Cannot update uninitialized entry. Use write(entry) to initialize first.')\n }\n\n const updatedFields = updater(this.entry)\n entry = { ...this.entry, ...updatedFields }\n } else {\n entry = updaterOrEntry\n }\n\n this.entry = entry\n return entry\n }\n\n delete() {\n this.entry = null\n }\n}\n"],"names":[],"mappings":";;;;;MAQsB,YAAY,CAAA;IAehC,MAAM,cAAc,CAAC,EAAW,EAAA;QAC9B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;AACpC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,MAAM,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAA,gBAAA,CAAkB,CAAC;AACnE,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,MAAM,QAAQ,CAAC,SAAyB,EAAE,UAA4B,EAAA;QACpE,IAAI,YAAY,GAAG,CAAC;QACpB,MAAM,OAAO,GAAQ,EAAE;QAEvB,IAAI,CAAC,UAAU,EAAE;YACf,WAAW,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5C,gBAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;AAChC,gBAAA,IAAI,OAAO;AAAE,oBAAA,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAClC;AACA,YAAA,OAAO,OAAO;QAChB;AAEA,QAAA,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,UAAU;AACjC,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC;QACjC,MAAM,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI;AAC3C,QAAA,MAAM,QAAQ,GAAG,UAAU,GAAG,IAAI;QAElC,WAAW,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5C,YAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;YAChC,IAAI,OAAO,EAAE;gBACX,IAAI,YAAY,IAAI,UAAU,IAAI,YAAY,GAAG,QAAQ,EAAE;AACzD,oBAAA,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;gBACrB;AACA,gBAAA,YAAY,EAAE;gBAEd,IAAI,YAAY,IAAI,QAAQ;oBAAE;YAChC;QACF;AAEA,QAAA,OAAO,OAAO;IAChB;IAEA,MAAM,GAAA;QACJ,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;IAClC;AAEA,IAAA,MAAM,SAAS,GAAA;QACb,MAAM,GAAG,GAAc,EAAE;QACzB,WAAW,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;AACrC,YAAA,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACd;AACA,QAAA,OAAO,GAAG;IACZ;AAEA,IAAA,WAAW,CAAC,GAAc,EAAA;AACxB,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5D;IAEA,MAAM,WAAW,CAAC,SAAyB,EAAA;QACzC,MAAM,UAAU,GAAc,EAAE;QAChC,MAAM,UAAU,GAAc,EAAE;QAEhC,WAAW,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5C,YAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE;YAEvB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,SAAS,EAAE;AACb,gBAAA,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B;iBAAO;AACL,gBAAA,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B;QACF;AAEA,QAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE;IACnC;IAEA,MAAM,MAAM,CAAC,EAAW,EAAA;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,KAAK,KAAK,IAAI;IACvB;IAEA,QAAQ,GAAA;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC;IACpC;AAEA,IAAA,MAAM,UAAU,CAAC,SAAyB,EAAE,UAA4B,EAAA;QACtE,IAAI,YAAY,GAAG,CAAC;QACpB,IAAI,KAAK,GAAG,CAAC;QAEb,IAAI,CAAC,UAAU,EAAE;YACf,WAAW,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5C,gBAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;AAChC,gBAAA,IAAI,OAAO;AAAE,oBAAA,KAAK,EAAE;YACtB;AACA,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,UAAU;AACjC,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC;QACjC,MAAM,UAAU,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI;AAC3C,QAAA,MAAM,QAAQ,GAAG,UAAU,GAAG,IAAI;QAElC,WAAW,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;AAC5C,YAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;YAChC,IAAI,OAAO,EAAE;AACX,gBAAA,IAAI,YAAY,IAAI,UAAU,IAAI,YAAY,GAAG,QAAQ;AAAE,oBAAA,KAAK,EAAE;AAClE,gBAAA,YAAY,EAAE;gBAEd,IAAI,YAAY,IAAI,QAAQ;oBAAE;YAChC;QACF;AAEA,QAAA,OAAO,KAAK;IACd;AACD;;ICvFW;AAAZ,CAAA,UAAY,QAAQ,EAAA;AAClB,IAAA,QAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb,IAAA,QAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;;AAEzB,CAAC,EAJW,QAAQ,KAAR,QAAQ,GAAA,EAAA,CAAA,CAAA;;ACfpB,MAAM,gBAAgB,GAAmB,OAAO;MAEnC,KAAK,CAAA;AAChB,IAAA,MAAM,IAAI,CAAC,OAAe,EAAE,OAAe,EAAA;QACzC,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;IACnC;AAEA,IAAA,MAAM,IAAI,CAAC,UAAkB,EAAE,eAAuB,EAAE,OAAqB,EAAA;AAC3E,QAAA,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE;;AAG7D,QAAA,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE;AACtD,YAAA,MAAM,IAAI,KAAK,CAAC,gBAAgB,eAAe,CAAA,gBAAA,CAAkB,CAAC;QACpE;QAEA,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;AAE7C,QAAA,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;AACpD,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;YACtC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;YAC9C;QACF;AAEA,QAAA,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE;YAC7B,IAAI,CAAC,SAAS,EAAE;AACd,gBAAA,MAAM,IAAI,KAAK,CAAC,IAAI,UAAU,CAAA,uCAAA,CAAyC,CAAC;YAC1E;YACA,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,eAAe,CAAC;QACvD;IACF;AAEA,IAAA,MAAM,aAAa,CAAC,UAAkB,EAAE,eAAuB,EAAA;QAC7D,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;AAE7C,QAAA,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;AACpD,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;YACtC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;YAC9C;QACF;AAEA,QAAA,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE;AAC7B,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC;YACvC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAE5C,YAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;gBAC3B,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;gBACpD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC;gBACvD,MAAM,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC;YAC1D;QACF;IACF;IAEA,MAAM,KAAK,CAAC,QAAgB,EAAA;AAC1B,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;IAClC;IAEU,MAAM,WAAW,CAAC,QAAgB,EAAA;AAC1C,QAAA,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/C;AAEA,IAAA,MAAM,KAAK,CAAC,QAAgB,EAAE,OAAe,EAAE,OAAsB,EAAA;QACnE,MAAM,EAAE,QAAQ,GAAG,gBAAgB,EAAE,GAAG,OAAO,IAAI,EAAE;QAErD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;AACzC,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;QAElC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;IACjD;IAEA,MAAM,KAAK,CAAC,QAAgB,EAAA;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC1C,QAAA,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC7C;AAEA,IAAA,MAAM,IAAI,CAAC,QAAgB,EAAE,OAAqB,EAAA;QAChD,MAAM,EAAE,QAAQ,GAAG,gBAAgB,EAAE,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE;AAE5D,QAAA,IAAI,KAAK,KAAK,SAAS,EAAE;YACvB,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;QAC9C;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC9D,QAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,CAAC;AACtC,YAAA,KAAK,EAAE,MAAM;AACb,YAAA,SAAS,EAAE,QAAQ;AACpB,SAAA,CAAC;QAEF,IAAI,MAAM,GAAG,EAAE;QACf,IAAI,SAAS,GAAG,CAAC;AACjB,QAAA,WAAW,MAAM,IAAI,IAAI,MAAM,EAAE;YAC/B,IAAI,SAAS,IAAI,KAAK;gBAAE;AACxB,YAAA,MAAM,IAAI,IAAI,GAAG,IAAI;AACrB,YAAA,SAAS,EAAE;QACb;AAEA,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,MAAM,MAAM,CAAC,QAAgB,EAAE,OAAuB,EAAA;AACpD,QAAA,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE;AACxD,QAAA,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC7C;IAEA,MAAM,MAAM,CAAC,QAAgB,EAAA;AAC3B,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;AACzB,YAAA,OAAO,IAAI;QACb;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;IAEA,MAAM,KAAK,CAAC,QAAgB,EAAA;AAC1B,QAAA,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrC,YAAA,OAAO,KAAK,CAAC,WAAW,EAAE;QAC5B;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;IAEA,MAAM,MAAM,CAAC,QAAgB,EAAA;AAC3B,QAAA,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrC,YAAA,OAAO,KAAK,CAAC,MAAM,EAAE;QACvB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;IAEA,MAAM,SAAS,CAAC,QAAgB,EAAA;AAC9B,QAAA,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrC,YAAA,OAAO,KAAK,CAAC,cAAc,EAAE;QAC/B;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;AAEA,IAAA,MAAM,OAAO,CAAC,QAAgB,EAAE,OAAqB,EAAA;QACnD,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,IAAI,EAAE;QAClD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE;AACjC,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE;QAE7B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK;AAC3C,QAAA,MAAM,UAAU,GAAG;YACjB,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC;YACjD,IAAI;AACJ,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,QAAQ,EAAE,KAAK;SAChB;QAED,IAAI,KAAK,EAAE;YACT,MAAM,QAAQ,GAAe,EAAE;AAE/B,YAAA,IAAI,KAAK,GAAG,CAAC,EAAE;gBACb,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;AAE5C,gBAAA,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE;AAC9B,oBAAA,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;AACzC,oBAAA,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE;AAC/D,wBAAA,KAAK,EAAE,UAAU;wBACjB,aAAa;AACd,qBAAA,CAAC;AACF,oBAAA,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC1B;YACF;YAEA,OAAO;AACL,gBAAA,GAAG,UAAU;gBACb,IAAI,EAAE,QAAQ,CAAC,SAAS;gBACxB,QAAQ;aACT;QACH;AACA,QAAA,IAAI,MAAM;YACR,OAAO;AACL,gBAAA,GAAG,UAAU;gBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;aACpB;AAEH,QAAA,MAAM,IAAI,KAAK,CAAC,WAAW,QAAQ,CAAA,gCAAA,CAAkC,CAAC;IACxE;AAEA,IAAA,MAAM,IAAI,CAAC,OAAe,EAAE,OAAqB,EAAA;QAC/C,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,IAAI,EAAE;AAClD,QAAA,IAAI,KAAK,GAAG,CAAC,EAAE;AACb,YAAA,OAAO,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,aAAa,CAAC;QACnE;AACA,QAAA,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAClC;AAEA,IAAA,OAAO,QAAQ,CAAC,OAAe,EAAE,OAAqB,EAAA;QACpD,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,OAAO,IAAI,EAAE;AAEnC,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC;AAEjD,QAAA,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE;YAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC1C,YAAA,IAAI,CAAC,MAAM;gBAAE;AAEb,YAAA,IAAI;gBACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACzC,MAAM;oBACJ,QAAQ;oBACR,OAAO;iBACR;YACH;AAAE,YAAA,MAAM;;gBAEN;YACF;QACF;IACF;IAEU,MAAM,aAAa,CAC3B,OAAe,EACf,QAAgB,EAChB,YAAoB,EACpB,aAAiC,EAAA;QAEjC,MAAM,OAAO,GAAa,EAAE;AAC5B,QAAA,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAElE,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;AAC3B,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC;YAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC;AAChE,YAAA,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;YAE1B,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,YAAY,GAAG,QAAQ,EAAE;AAClD,gBAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CACzC,QAAQ,EACR,QAAQ,EACR,YAAY,GAAG,CAAC,EAChB,aAAa,CACd;AACD,gBAAA,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;YAC7B;QACF;AAEA,QAAA,OAAO,OAAO;IAChB;IAEU,aAAa,CAAC,QAAgB,EAAE,WAA+B,EAAA;AACvE,QAAA,IAAI,CAAC,WAAW;AAAE,YAAA,OAAO,QAAQ;AACjC,QAAA,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;QAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE;IACvB;AACD;;AC/QK,MAAO,gBAAyC,SAAQ,YAAe,CAAA;IAM3E,WAAA,CAAY,OAAe,EAAE,OAAoC,EAAA;AAC/D,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;AACtB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE;QACxB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,IAAI;QACrC,IAAI,CAAC,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,IAAI;IACrD;IAEA,MAAM,MAAM,CAAC,KAAQ,EAAA;AACnB,QAAA,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;AAC5B,QAAA,OAAO,KAAK;IACd;IAEA,MAAM,OAAO,CAAC,EAAW,EAAA;AACvB,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAAE,YAAA,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,CAAA,CAAE,CAAC;AAE7D,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;AACrC,YAAA,OAAO,KAAK;QACd;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;;AAE5C,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,MAAM,MAAM,CAAC,EAAW,EAAE,OAA6C,EAAA;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;AAE3C,QAAA,MAAM,kBAAkB,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;QAC/C,MAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,kBAAkB,EAAE;AACxD,QAAA,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;AAEnC,QAAA,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE;AAC1B,YAAA,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B;AAEA,QAAA,OAAO,YAAY;IACrB;IAEA,MAAM,UAAU,CAAC,EAAW,EAAA;AAC1B,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;AACrC,YAAA,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACnD,YAAA,OAAO,IAAI;QACb;AAAE,QAAA,MAAM;;AAEN,YAAA,OAAO,KAAK;QACd;IACF;IAEA,MAAM,WAAW,CAAC,GAAc,EAAA;AAC9B,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5D;AAEA,IAAA,MAAM,OAAO,GAAA;QACX,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IACvC;AAEU,IAAA,WAAW,CAAC,EAAW,EAAA;AAC/B,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA,EAAG,EAAE,CAAA,KAAA,CAAO,CAAC;IAC9C;IAEU,MAAM,UAAU,CAAC,KAAQ,EAAA;QACjC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,CAAA,YAAA,EAAe,KAAK,CAAC,EAAE,CAAA,CAAE,CAAC;QAEzE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3C,QAAA,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE;AAEA,IAAA,SAAS,CAAC,EAAW,EAAA;QACnB,IAAI,OAAO,EAAE,KAAK,QAAQ;AAAE,YAAA,OAAO,KAAK;QAExC,IAAI,CAAC,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,IAAI;AAEpC,QAAA,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;AAAE,YAAA,OAAO,KAAK;AAEvD,QAAA,OAAO,IAAI;IACb;IAEU,OAAO,WAAW,GAAA;QAC1B,WAAW,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;AACpC,YAAA,IAAI,KAAK;AAAE,gBAAA,MAAM,KAAK;QACxB;IACF;IAEU,OAAO,OAAO,GAAA;AACtB,QAAA,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;AACrD,QAAA,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;AAChC,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE;YAEjC,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;AAC1C,YAAA,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAAE,gBAAA,MAAM,EAAE;QAClC;IACF;AACD;;MChHY,iBAAiB,CAAA;IAG5B,WAAA,CACqB,QAAgB,EAChB,MAAA,GAA6B,IAAI,EAAA;QADjC,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,MAAM,GAAN,MAAM;AAJR,QAAA,IAAA,CAAA,KAAK,GAAU,IAAI,KAAK,EAAE;IAK1C;IAEH,IAAI,GAAA;QACF,OAAO,IAAI,CAAC,QAAQ;IACtB;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrD,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;AACrC,QAAA,OAAO,KAAK;IACd;IAEA,MAAM,KAAK,CAAC,cAA0D,EAAA;AACpE,QAAA,IAAI,KAAQ;AACZ,QAAA,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE;YACxC,MAAM,OAAO,GAAG,cAAiC;AACjD,YAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAElC,YAAA,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC;YAC7C,KAAK,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,aAAa,EAAE;QAC3C;aAAO;YACL,KAAK,GAAG,cAAc;QACxB;QAEA,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAErE,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,MAAM,MAAM,GAAA;QACV,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;IACxC;AACD;;AC5CK,MAAO,eAAwC,SAAQ,YAAe,CAAA;AAA5E,IAAA,WAAA,GAAA;;AACY,QAAA,IAAA,CAAA,OAAO,GAAoB,IAAI,GAAG,EAAE;IA2ChD;IAzCE,MAAM,MAAM,CAAC,KAAQ,EAAA;QACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC;AACjC,QAAA,OAAO,KAAK;IACd;IAEA,MAAM,OAAO,CAAC,EAAW,EAAA;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI;IACrC;AAEA,IAAA,MAAM,MAAM,CAAC,EAAW,EAAE,OAA6C,EAAA;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;AAE3C,QAAA,MAAM,kBAAkB,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;QAC/C,MAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,kBAAkB,EAAE;QAExD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,EAAE,YAAY,CAAC;AAE/C,QAAA,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE;AAAE,YAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AAEnD,QAAA,OAAO,YAAY;IACrB;IAEA,MAAM,UAAU,CAAC,EAAW,EAAA;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IAChC;AAEA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;IACtB;IAEU,OAAO,WAAW,GAAA;QAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE;AACzC,YAAA,MAAM,KAAK;QACb;IACF;IAEU,OAAO,OAAO,GAAA;QACtB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;AACpC,YAAA,MAAM,EAAE;QACV;IACF;AACD;;MC9CY,gBAAgB,CAAA;AAG3B,IAAA,WAAA,CAAY,eAAyB,IAAI,EAAA;QAF/B,IAAA,CAAA,KAAK,GAAa,IAAI;AAG9B,QAAA,IAAI,CAAC,KAAK,GAAG,YAAY;IAC3B;IAEA,QAAQ,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI;IAC5B;IAEA,IAAI,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;AAAE,YAAA,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC;QACjE,OAAO,IAAI,CAAC,KAAK;IACnB;AAEA,IAAA,KAAK,CAAC,cAA8C,EAAA;AAClD,QAAA,IAAI,KAAQ;AAEZ,QAAA,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE;YACxC,MAAM,OAAO,GAAG,cAA0C;AAE1D,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE;AACvB,gBAAA,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC;YAC7F;YAEA,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YACzC,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,aAAa,EAAE;QAC7C;aAAO;YACL,KAAK,GAAG,cAAc;QACxB;AAEA,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;AAClB,QAAA,OAAO,KAAK;IACd;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;AACD;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/common/errors.ts","../../../src/common/multiEntryDb.ts","../../../src/common/singleEntryDb.ts","../../../src/common/runJsonEntryParser.ts","../../../src/common/types.ts","../../../src/file/files.ts","../../../src/file/multiEntryFileDb.ts","../../../src/file/singleEntryFileDb.ts","../../../src/memory/multiEntryMemDb.ts","../../../src/memory/singleEntryMemDb.ts"],"sourcesContent":["export class DbError extends Error {}\n\nexport class NotFoundError extends DbError {}\n\nexport class ConflictError extends DbError {}\n\nexport class FileIoError extends DbError {}\n\nexport class InvalidIdError extends DbError {\n constructor(id: unknown) {\n super(`Invalid entry id '${id}'`)\n }\n}\n\nexport class UninitError extends DbError {\n constructor() {\n super('Cannot read or update uninitialized entry. Use write(entry) to initialize first')\n }\n}\n","import { NotFoundError } from './errors'\nimport type {\n Identifiable,\n DeleteManyOutput,\n PaginationInput,\n PredicateFn,\n UpdaterFn,\n} from './types'\n\nexport abstract class MultiEntryDb<T extends Identifiable> {\n abstract create(entry: T): Promise<T>\n\n abstract getById(id: T['id']): Promise<T | null>\n\n abstract update(id: T['id'], updater: UpdaterFn<T>): Promise<T>\n\n abstract deleteById(id: T['id']): Promise<boolean>\n\n abstract destroy(): Promise<void>\n\n abstract iterEntries(): AsyncIterable<T>\n\n abstract iterIds(): AsyncIterable<T['id']>\n\n async getByIdOrThrow(id: T['id']): Promise<T> {\n const entry = await this.getById(id)\n if (!entry) throw new NotFoundError(`Entry with id '${id}' does not exist`)\n return entry\n }\n\n async getFirstWhere(predicate: PredicateFn<T>): Promise<T | null> {\n const matches = await this.getWhere(predicate, { page: 0, take: 1 })\n return matches.at(0) ?? null\n }\n\n async getFirstWhereOrThrow(predicate: PredicateFn<T>): Promise<T | null> {\n const match = await this.getFirstWhere(predicate)\n if (!match) throw new NotFoundError('No entry matches predicate')\n return match\n }\n\n async getWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<T[]> {\n let totalMatched = 0\n const entries: T[] = []\n\n if (!pagination) {\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) entries.push(entry)\n }\n return entries\n }\n\n const { take, page } = pagination\n const skip = pagination.skip ?? 0\n const startIndex = (page - 1) * take + skip\n const endIndex = startIndex + take\n\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) {\n if (totalMatched >= startIndex && totalMatched < endIndex) {\n entries.push(entry)\n }\n totalMatched++\n\n if (totalMatched >= endIndex) break\n }\n }\n\n return entries\n }\n\n getAll(): Promise<T[]> {\n return this.getWhere(() => true)\n }\n\n async getAllIds(): Promise<T['id'][]> {\n const ids: T['id'][] = []\n for await (const id of this.iterIds()) {\n ids.push(id)\n }\n return ids\n }\n\n deleteByIds(ids: T['id'][]): Promise<DeleteManyOutput> {\n return this.deleteWhere((entry) => ids.includes(entry.id))\n }\n\n async deleteWhere(predicate: PredicateFn<T>): Promise<DeleteManyOutput> {\n const deletedIds: T['id'][] = []\n const ignoredIds: T['id'][] = []\n\n for await (const entry of this.iterEntries()) {\n if (!predicate(entry)) continue\n\n const didDelete = await this.deleteById(entry.id)\n if (didDelete) {\n deletedIds.push(entry.id)\n } else {\n ignoredIds.push(entry.id)\n }\n }\n\n return { deletedIds, ignoredIds }\n }\n\n async exists(id: T['id']): Promise<boolean> {\n const entry = await this.getById(id)\n return entry !== null\n }\n\n countAll(): Promise<number> {\n return this.countWhere(() => true)\n }\n\n async countWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<number> {\n let totalMatched = 0\n let count = 0\n\n if (!pagination) {\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) count++\n }\n return count\n }\n\n const { take, page } = pagination\n const skip = pagination.skip ?? 0\n const startIndex = (page - 1) * take + skip\n const endIndex = startIndex + take\n\n for await (const entry of this.iterEntries()) {\n const isMatch = predicate(entry)\n if (isMatch) {\n if (totalMatched >= startIndex && totalMatched < endIndex) count++\n totalMatched++\n\n if (totalMatched >= endIndex) break\n }\n }\n\n return count\n }\n}\n","import type { UpdaterFn } from './types'\n\nexport abstract class SingleEntryDb<T> {\n abstract isInited(): Promise<boolean>\n abstract read(): Promise<T>\n abstract write(updaterOrEntry: T | UpdaterFn<T>): Promise<T>\n abstract delete(): Promise<void>\n}\n","import { JsonEntryParser } from './types'\n\nexport function runJsonEntryParser<T>(parser: JsonEntryParser<T>, text: string): T {\n return typeof parser === 'function' ? parser(text) : parser.parse(text)\n}\n","export type Identifiable = {\n id: Id\n}\n\nexport type Id =\n | string\n | number\n | {\n toString: () => string\n }\n\nexport type Promisable<T> = T | Promise<T>\n\nexport type PaginationInput = {\n take: number\n page: number\n skip?: number | undefined | null\n}\n\nexport type DeleteManyOutput = {\n deletedIds: Id[]\n ignoredIds: Id[]\n}\n\nexport type PredicateFn<T extends Identifiable> = (entry: T) => boolean\n\nexport type UpdaterFn<T> = (entry: T) => Promisable<Partial<T>>\n\nexport type JsonEntryParser<T> = JsonEntryParserFn<T> | JsonEntryParserObj<T>\n\ntype JsonEntryParserFn<T> = (text: string) => T\ntype JsonEntryParserObj<T> = {\n parse: JsonEntryParserFn<T>\n}\n\nexport type MultiEntryFileDbOptions<T> = {\n noPathlikeIds?: boolean\n parser?: JsonEntryParser<T>\n}\n\nexport type FileMeta = {\n path: string\n size: number\n created: Date\n modified: Date\n accessed: Date\n} & (\n | {\n type: FileType.File\n }\n | {\n type: FileType.Directory\n children: FileMeta[]\n }\n)\n\nexport enum FileType {\n File = 'file',\n Directory = 'directory',\n //Symlink: 'symlink'\n}\n","import type { FileMeta } from '../common'\nimport { FileType, FileIoError } from '../common'\nimport * as fs from 'fs/promises'\nimport * as path from 'path'\nimport * as fsSync from 'fs'\nimport * as readline from 'readline'\n\ntype ListOptions = {\n depth?: number\n stripBasepath?: string\n}\n\ntype DeleteOptions = {\n force?: boolean\n recursive?: boolean\n}\n\ntype WriteOptions = {\n encoding?: BufferEncoding\n}\n\ntype ReadOptions = {\n encoding?: BufferEncoding\n lines?: number\n}\n\ntype CopyOptions = {\n recursive?: boolean\n overwrite?: boolean\n}\n\nconst DEFUALT_ENCODING: BufferEncoding = 'utf-8'\n\nexport class Files {\n async move(oldPath: string, newPath: string) {\n await fs.rename(oldPath, newPath)\n }\n\n async copy(sourcePath: string, destinationPath: string, options?: CopyOptions) {\n const { recursive = false, overwrite = true } = options ?? {}\n\n // Check if destination exists and handle overwrite\n if (!overwrite && (await this.exists(destinationPath))) {\n throw new FileIoError(`Destination '${destinationPath}' already exists`)\n }\n\n const sourceStats = await fs.stat(sourcePath)\n\n if (sourceStats.isFile()) {\n const destinationDir = path.dirname(destinationPath)\n await this.mkdirUnsafe(destinationDir)\n await fs.copyFile(sourcePath, destinationPath)\n return\n }\n\n if (sourceStats.isDirectory()) {\n if (!recursive) {\n throw new FileIoError(`'${sourcePath}' is a directory (use recursive option)`)\n }\n await this.copyRecursive(sourcePath, destinationPath)\n }\n }\n\n async copyRecursive(sourcePath: string, destinationPath: string) {\n const sourceStats = await fs.stat(sourcePath)\n\n if (sourceStats.isFile()) {\n const destinationDir = path.dirname(destinationPath)\n await this.mkdirUnsafe(destinationDir)\n await fs.copyFile(sourcePath, destinationPath)\n return\n }\n\n if (sourceStats.isDirectory()) {\n await this.mkdirUnsafe(destinationPath)\n const entries = await fs.readdir(sourcePath)\n\n for (const entry of entries) {\n const sourceEntryPath = path.join(sourcePath, entry)\n const destEntryPath = path.join(destinationPath, entry)\n await this.copyRecursive(sourceEntryPath, destEntryPath)\n }\n }\n }\n\n async mkdir(filepath: string) {\n await this.mkdirUnsafe(filepath)\n }\n\n protected async mkdirUnsafe(filepath: string) {\n await fs.mkdir(filepath, { recursive: true })\n }\n\n async write(filepath: string, content: string, options?: WriteOptions) {\n const { encoding = DEFUALT_ENCODING } = options ?? {}\n\n const parentDirs = path.dirname(filepath)\n await this.mkdirUnsafe(parentDirs)\n\n await fs.writeFile(filepath, content, encoding)\n }\n\n async touch(filepath: string) {\n const exists = await this.exists(filepath)\n if (!exists) await this.write(filepath, '')\n }\n\n async read(filepath: string, options?: ReadOptions) {\n const { encoding = DEFUALT_ENCODING, lines } = options ?? {}\n\n if (lines === undefined) {\n return await fs.readFile(filepath, encoding)\n }\n\n const stream = fsSync.createReadStream(filepath, { encoding })\n const reader = readline.createInterface({\n input: stream,\n crlfDelay: Infinity,\n })\n\n let result = ''\n let linesRead = 0\n for await (const line of reader) {\n if (linesRead >= lines) break\n result += line + '\\n'\n linesRead++\n }\n\n return result\n }\n\n async delete(filepath: string, options?: DeleteOptions) {\n const { force = true, recursive = true } = options ?? {}\n await fs.rm(filepath, { force, recursive })\n }\n\n async exists(filepath: string) {\n try {\n await fs.access(filepath)\n return true\n } catch {\n return false\n }\n }\n\n async isDir(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isDirectory()\n } catch {\n return false\n }\n }\n\n async isFile(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isFile()\n } catch {\n return false\n }\n }\n\n async isSymlink(filepath: string) {\n try {\n const stats = await fs.stat(filepath)\n return stats.isSymbolicLink()\n } catch {\n return false\n }\n }\n\n async getMeta(filepath: string, options?: ListOptions): Promise<FileMeta> {\n const { depth = 0, stripBasepath } = options ?? {}\n const stats = await fs.stat(filepath)\n const isDir = stats.isDirectory()\n const isFile = stats.isFile()\n\n const { size, ctime, mtime, atime } = stats\n const commonMeta = {\n path: this.stripBasepath(filepath, stripBasepath),\n size,\n created: ctime,\n modified: mtime,\n accessed: atime,\n }\n\n if (isDir) {\n const children: FileMeta[] = []\n\n if (depth > 0) {\n const childNames = await this.list(filepath)\n\n for (const child of childNames) {\n const childDepth = Math.max(0, depth - 1)\n const childMeta = await this.getMeta(path.join(filepath, child), {\n depth: childDepth,\n stripBasepath,\n })\n children.push(childMeta)\n }\n }\n\n return {\n ...commonMeta,\n type: FileType.Directory,\n children,\n }\n }\n if (isFile)\n return {\n ...commonMeta,\n type: FileType.File,\n }\n\n throw new FileIoError(`File at ${filepath} is not normal file or directory`)\n }\n\n async list(dirpath: string, options?: ListOptions) {\n const { depth = 0, stripBasepath } = options ?? {}\n if (depth > 0) {\n return await this.listRecursive(dirpath, depth, 0, stripBasepath)\n }\n return await fs.readdir(dirpath)\n }\n\n async *listRead(dirpath: string, options?: ListOptions) {\n const { depth = 0 } = options ?? {}\n\n const files = await this.list(dirpath, { depth })\n\n for (const filepath of files) {\n const isFile = await this.isFile(filepath)\n if (!isFile) continue\n\n try {\n const content = await this.read(filepath)\n yield {\n filepath,\n content,\n }\n } catch {\n // Skip files that can't be read\n continue\n }\n }\n }\n\n protected async listRecursive(\n dirpath: string,\n maxDepth: number,\n currentDepth: number,\n stripBasepath: string | undefined,\n ): Promise<string[]> {\n const results: string[] = []\n const entries = await fs.readdir(dirpath, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dirpath, entry.name)\n const strippedPath = this.stripBasepath(fullPath, stripBasepath)\n results.push(strippedPath)\n\n if (entry.isDirectory() && currentDepth < maxDepth) {\n const subResults = await this.listRecursive(\n fullPath,\n maxDepth,\n currentDepth + 1,\n stripBasepath,\n )\n results.push(...subResults)\n }\n }\n\n return results\n }\n\n protected stripBasepath(original: string, pathToStrip: string | undefined): string {\n if (!pathToStrip) return original\n const base = pathToStrip.replace(/^\\/+/, '/').replace(/\\/+$/, '/')\n const stripped = original.replace(base, '')\n return `/${stripped}`\n }\n}\n","import {\n Identifiable,\n DeleteManyOutput,\n Promisable,\n JsonEntryParser,\n MultiEntryFileDbOptions,\n MultiEntryDb,\n InvalidIdError,\n runJsonEntryParser,\n} from '../common'\nimport { Files } from './files'\nimport * as path from 'path'\n\nexport class MultiEntryFileDb<T extends Identifiable> extends MultiEntryDb<T> {\n protected readonly dirpath: string\n protected readonly files: Files\n protected readonly parser: JsonEntryParser<T>\n readonly noPathlikeIds: boolean\n\n constructor(dirpath: string, options?: MultiEntryFileDbOptions<T>) {\n super()\n this.dirpath = dirpath\n this.files = new Files()\n this.parser = options?.parser ?? JSON\n this.noPathlikeIds = options?.noPathlikeIds ?? true\n }\n\n async create(entry: T): Promise<T> {\n await this.writeEntry(entry)\n return entry\n }\n\n async getById(id: T['id']): Promise<T | null> {\n if (!this.isIdValid(id)) throw new InvalidIdError(id)\n\n try {\n const filepath = this.getFilePath(id)\n const text = await this.files.read(filepath)\n const entry = runJsonEntryParser(this.parser, text)\n return entry\n } catch (error) {\n console.error('Failed to read entry', error)\n // File doesn't exist or invalid JSON\n return null\n }\n }\n\n async update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T> {\n const entry = await this.getByIdOrThrow(id)\n\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n await this.writeEntry(updatedEntry)\n\n if (updatedEntry.id !== id) {\n await this.deleteById(id)\n }\n\n return updatedEntry\n }\n\n async deleteById(id: T['id']): Promise<boolean> {\n try {\n const filepath = this.getFilePath(id)\n await this.files.delete(filepath, { force: false })\n return true\n } catch {\n // File might not exist, ignore error\n return false\n }\n }\n\n async deleteByIds(ids: T['id'][]): Promise<DeleteManyOutput> {\n return this.deleteWhere((entry) => ids.includes(entry.id))\n }\n\n async destroy() {\n await this.files.delete(this.dirpath)\n }\n\n protected getFilePath(id: T['id']) {\n return path.join(this.dirpath, `${String(id)}.json`)\n }\n\n protected async writeEntry(entry: T) {\n if (!this.isIdValid(entry.id)) throw new InvalidIdError(entry.id)\n\n const filepath = this.getFilePath(entry.id)\n await this.files.write(filepath, JSON.stringify(entry, null, 2))\n }\n\n isIdValid(rawId: T['id']): boolean {\n if (!this.noPathlikeIds) return true\n\n const id = String(rawId)\n if (id.includes('/') || id.includes('\\\\')) return false\n\n return true\n }\n\n async *iterEntries() {\n for await (const id of this.iterIds()) {\n const entry = await this.getById(id)\n if (entry) yield entry\n }\n }\n\n async *iterIds(objectIdParser?: JsonEntryParser<T['id']>): AsyncGenerator<T['id']> {\n const filenames = await this.files.list(this.dirpath)\n for (const filename of filenames) {\n if (!filename.endsWith('.json')) continue\n\n const stringId = filename.replace(/\\.json$/, '')\n const id = objectIdParser ? runJsonEntryParser(objectIdParser, stringId) : stringId\n if (this.isIdValid(id)) yield id\n }\n }\n}\n\ntype ObjId = {\n value: string\n toString: () => string\n}\n\ntype Entry = {\n id: ObjId\n}\n\nconst test = async () => {\n const x = new MultiEntryFileDb<Entry>('test')\n const a = x.iterIds((y) => ({ value: y, toString: () => y }))\n\n for await (const c of a) {\n console.log(c)\n }\n}\n","import { SingleEntryDb, JsonEntryParser, Promisable, runJsonEntryParser } from '../common'\nimport { Files } from './files'\n\nexport class SingleEntryFileDb<T> extends SingleEntryDb<T> {\n protected readonly files: Files = new Files()\n\n constructor(\n protected readonly filepath: string,\n protected readonly parser: JsonEntryParser<T> = JSON,\n ) {\n super()\n }\n\n path() {\n return this.filepath\n }\n\n async isInited() {\n const exists = await this.files.exists(this.filepath)\n return exists\n }\n\n async read() {\n const text = await this.files.read(this.filepath)\n const entry = runJsonEntryParser(this.parser, text)\n return entry\n }\n\n async write(updaterOrEntry: T | ((entry: T) => Promisable<Partial<T>>)): Promise<T> {\n let entry: T\n if (typeof updaterOrEntry === 'function') {\n const updater = updaterOrEntry as (entry: T) => T\n const existing = await this.read()\n\n const updatedFields = await updater(existing)\n entry = { ...existing, ...updatedFields }\n } else {\n entry = updaterOrEntry\n }\n\n await this.files.write(this.filepath, JSON.stringify(entry, null, 2))\n\n return entry\n }\n\n async delete(): Promise<void> {\n await this.files.delete(this.filepath)\n }\n}\n","import { Identifiable, Promisable, MultiEntryDb, JsonEntryParser } from '../common'\nimport { MultiEntryFileDb } from '../file/multiEntryFileDb'\n\nexport class MultiEntryMemDb<T extends Identifiable> extends MultiEntryDb<T> {\n protected entries: Map<T['id'], T> = new Map()\n\n async create(entry: T): Promise<T> {\n this.entries.set(entry.id, entry)\n return entry\n }\n\n async getById(id: T['id']): Promise<T | null> {\n return this.entries.get(id) ?? null\n }\n\n async update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T> {\n const entry = await this.getByIdOrThrow(id)\n\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n\n this.entries.set(updatedEntry.id, updatedEntry)\n\n if (updatedEntry.id !== id) this.entries.delete(id)\n\n return updatedEntry\n }\n\n async deleteById(id: T['id']): Promise<boolean> {\n return this.entries.delete(id)\n }\n\n async destroy() {\n this.entries.clear()\n }\n\n async *iterEntries() {\n for (const entry of this.entries.values()) {\n yield entry\n }\n }\n\n async *iterIds() {\n for (const id of this.entries.keys()) {\n yield id\n }\n }\n\n async persist(dirpath: string) {\n const fileDb = new MultiEntryFileDb<T>(dirpath)\n await fileDb.destroy()\n\n const values = [...this.entries.values()]\n await Promise.all(values.map((entry) => fileDb.create(entry)))\n }\n\n async load(dirpath: string, parser?: JsonEntryParser<T>) {\n const fileDb = new MultiEntryFileDb<T>(dirpath, { parser })\n\n await this.destroy()\n for await (const entry of fileDb.iterEntries()) {\n await this.create(entry)\n }\n }\n}\n","import { JsonEntryParser, SingleEntryDb, UninitError, UpdaterFn } from '../common'\nimport { SingleEntryFileDb } from '../file/singleEntryFileDb'\n\nexport class SingleEntryMemDb<T> extends SingleEntryDb<T> {\n protected entry: T | null = null\n\n constructor(initialEntry: T | null = null) {\n super()\n this.entry = initialEntry\n }\n\n async isInited() {\n return this.entry !== null\n }\n\n async read() {\n if (this.entry === null) throw new UninitError()\n return this.entry\n }\n\n async write(updaterOrEntry: T | UpdaterFn<T>) {\n let entry: T\n\n if (typeof updaterOrEntry === 'function') {\n const updater = updaterOrEntry as (entry: T) => Partial<T>\n\n if (this.entry === null) throw new UninitError()\n\n const updatedFields = updater(this.entry)\n entry = { ...this.entry, ...updatedFields }\n } else {\n entry = updaterOrEntry\n }\n\n this.entry = entry\n return entry\n }\n\n async delete() {\n this.entry = null\n }\n\n async persist(filepath: string) {\n const fileDb = new SingleEntryFileDb<T>(filepath)\n await fileDb.write(await this.read())\n }\n\n async load(filepath: string, parser?: JsonEntryParser<T>) {\n const fileDb = new SingleEntryFileDb<T>(filepath, parser)\n const persistedEntry = await fileDb.read()\n this.write(persistedEntry)\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  type Identifiable = {
2
2
  id: Id;
3
3
  };
4
- type Id = string;
4
+ type Id = string | number | {
5
+ toString: () => string;
6
+ };
5
7
  type Promisable<T> = T | Promise<T>;
6
8
  type PaginationInput = {
7
9
  take: number;
@@ -13,8 +15,11 @@ type DeleteManyOutput = {
13
15
  ignoredIds: Id[];
14
16
  };
15
17
  type PredicateFn<T extends Identifiable> = (entry: T) => boolean;
16
- type JsonEntryParser<T> = {
17
- parse: (text: string) => T;
18
+ type UpdaterFn<T> = (entry: T) => Promisable<Partial<T>>;
19
+ type JsonEntryParser<T> = JsonEntryParserFn<T> | JsonEntryParserObj<T>;
20
+ type JsonEntryParserFn<T> = (text: string) => T;
21
+ type JsonEntryParserObj<T> = {
22
+ parse: JsonEntryParserFn<T>;
18
23
  };
19
24
  type MultiEntryFileDbOptions<T> = {
20
25
  noPathlikeIds?: boolean;
@@ -40,12 +45,14 @@ declare enum FileType {
40
45
  declare abstract class MultiEntryDb<T extends Identifiable> {
41
46
  abstract create(entry: T): Promise<T>;
42
47
  abstract getById(id: T['id']): Promise<T | null>;
43
- abstract update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T>;
48
+ abstract update(id: T['id'], updater: UpdaterFn<T>): Promise<T>;
44
49
  abstract deleteById(id: T['id']): Promise<boolean>;
45
50
  abstract destroy(): Promise<void>;
46
- protected abstract iterEntries(): AsyncIterable<T>;
47
- protected abstract iterIds(): AsyncIterable<T['id']>;
51
+ abstract iterEntries(): AsyncIterable<T>;
52
+ abstract iterIds(): AsyncIterable<T['id']>;
48
53
  getByIdOrThrow(id: T['id']): Promise<T>;
54
+ getFirstWhere(predicate: PredicateFn<T>): Promise<T | null>;
55
+ getFirstWhereOrThrow(predicate: PredicateFn<T>): Promise<T | null>;
49
56
  getWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<T[]>;
50
57
  getAll(): Promise<T[]>;
51
58
  getAllIds(): Promise<T['id'][]>;
@@ -56,6 +63,28 @@ declare abstract class MultiEntryDb<T extends Identifiable> {
56
63
  countWhere(predicate: PredicateFn<T>, pagination?: PaginationInput): Promise<number>;
57
64
  }
58
65
 
66
+ declare abstract class SingleEntryDb<T> {
67
+ abstract isInited(): Promise<boolean>;
68
+ abstract read(): Promise<T>;
69
+ abstract write(updaterOrEntry: T | UpdaterFn<T>): Promise<T>;
70
+ abstract delete(): Promise<void>;
71
+ }
72
+
73
+ declare class DbError extends Error {
74
+ }
75
+ declare class NotFoundError extends DbError {
76
+ }
77
+ declare class ConflictError extends DbError {
78
+ }
79
+ declare class FileIoError extends DbError {
80
+ }
81
+ declare class InvalidIdError extends DbError {
82
+ constructor(id: unknown);
83
+ }
84
+ declare class UninitError extends DbError {
85
+ constructor();
86
+ }
87
+
59
88
  type ListOptions = {
60
89
  depth?: number;
61
90
  stripBasepath?: string;
@@ -113,12 +142,12 @@ declare class MultiEntryFileDb<T extends Identifiable> extends MultiEntryDb<T> {
113
142
  destroy(): Promise<void>;
114
143
  protected getFilePath(id: T['id']): string;
115
144
  protected writeEntry(entry: T): Promise<void>;
116
- isIdValid(id: T['id']): boolean;
117
- protected iterEntries(): AsyncGenerator<T, void, unknown>;
118
- protected iterIds(): AsyncGenerator<string, void, unknown>;
145
+ isIdValid(rawId: T['id']): boolean;
146
+ iterEntries(): AsyncGenerator<T, void, unknown>;
147
+ iterIds(objectIdParser?: JsonEntryParser<T['id']>): AsyncGenerator<T['id']>;
119
148
  }
120
149
 
121
- declare class SingleEntryFileDb<T> {
150
+ declare class SingleEntryFileDb<T> extends SingleEntryDb<T> {
122
151
  protected readonly filepath: string;
123
152
  protected readonly parser: JsonEntryParser<T>;
124
153
  protected readonly files: Files;
@@ -137,18 +166,22 @@ declare class MultiEntryMemDb<T extends Identifiable> extends MultiEntryDb<T> {
137
166
  update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T>;
138
167
  deleteById(id: T['id']): Promise<boolean>;
139
168
  destroy(): Promise<void>;
140
- protected iterEntries(): AsyncGenerator<T, void, unknown>;
141
- protected iterIds(): AsyncGenerator<T["id"], void, unknown>;
169
+ iterEntries(): AsyncGenerator<T, void, unknown>;
170
+ iterIds(): AsyncGenerator<T["id"], void, unknown>;
171
+ persist(dirpath: string): Promise<void>;
172
+ load(dirpath: string, parser?: JsonEntryParser<T>): Promise<void>;
142
173
  }
143
174
 
144
- declare class SingleEntryMemDb<T> {
175
+ declare class SingleEntryMemDb<T> extends SingleEntryDb<T> {
145
176
  protected entry: T | null;
146
177
  constructor(initialEntry?: T | null);
147
- isInited(): boolean;
148
- read(): T;
149
- write(updaterOrEntry: T | ((entry: T) => Partial<T>)): T;
150
- delete(): void;
178
+ isInited(): Promise<boolean>;
179
+ read(): Promise<T & ({} | undefined)>;
180
+ write(updaterOrEntry: T | UpdaterFn<T>): Promise<T>;
181
+ delete(): Promise<void>;
182
+ persist(filepath: string): Promise<void>;
183
+ load(filepath: string, parser?: JsonEntryParser<T>): Promise<void>;
151
184
  }
152
185
 
153
- export { FileType, MultiEntryFileDb, MultiEntryMemDb, SingleEntryFileDb, SingleEntryMemDb };
154
- export type { DeleteManyOutput, FileMeta, Id, Identifiable, JsonEntryParser, MultiEntryFileDbOptions, PaginationInput, PredicateFn, Promisable };
186
+ export { ConflictError, DbError, FileIoError, FileType, InvalidIdError, MultiEntryFileDb, MultiEntryMemDb, NotFoundError, SingleEntryFileDb, SingleEntryMemDb, UninitError };
187
+ export type { DeleteManyOutput, FileMeta, Id, Identifiable, JsonEntryParser, MultiEntryFileDbOptions, PaginationInput, PredicateFn, Promisable, UpdaterFn };