@jsonkit/db 4.1.0 → 5.0.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 +9 -13
- package/dist/cjs/index.cjs +62 -60
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +62 -60
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +12 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,9 @@ All multi-entry implementations expose the same methods:
|
|
|
35
35
|
- `getFirstWhereOrThrow(predicate)`
|
|
36
36
|
- `getAll(ids?)`
|
|
37
37
|
- `getAllIds()`
|
|
38
|
-
- `
|
|
38
|
+
- `updateById(id, updater)`
|
|
39
|
+
- `updateFirstWhere(predicate, updater)`
|
|
40
|
+
- `updateWhere(predicate, updater, pagination?)`
|
|
39
41
|
- `deleteById(id)`
|
|
40
42
|
- `deleteByIds(ids)`
|
|
41
43
|
- `deleteWhere(predicate)`
|
|
@@ -76,6 +78,7 @@ new MultiEntryFileDb<T>(dirpath, options?)
|
|
|
76
78
|
| --------------- | -------------------------------------- | ------- |
|
|
77
79
|
| `noPathlikeIds` | Reject IDs containing `/` or `\` | `true` |
|
|
78
80
|
| `parser` | Custom JSON parser (`{ parse(text) }`) | `JSON` |
|
|
81
|
+
| `disableLogs` | Stops logging errors | `false` |
|
|
79
82
|
|
|
80
83
|
#### Notes
|
|
81
84
|
|
|
@@ -160,7 +163,6 @@ const db = new SingleEntryMemDb<AppConfig>()
|
|
|
160
163
|
- `read()` throws if uninitialized.
|
|
161
164
|
- `delete()` resets the entry to `null`.
|
|
162
165
|
|
|
163
|
-
---
|
|
164
166
|
|
|
165
167
|
## Example
|
|
166
168
|
|
|
@@ -178,16 +180,6 @@ const allUsers = await users.getAll()
|
|
|
178
180
|
|
|
179
181
|
---
|
|
180
182
|
|
|
181
|
-
## Use Cases
|
|
182
|
-
|
|
183
|
-
- Rapid application prototyping
|
|
184
|
-
- CLI tools
|
|
185
|
-
- Small internal services
|
|
186
|
-
- Tests and mocks
|
|
187
|
-
- Configuration and state persistence
|
|
188
|
-
|
|
189
|
-
---
|
|
190
|
-
|
|
191
183
|
## Core Types
|
|
192
184
|
|
|
193
185
|
### `Identifiable`
|
|
@@ -235,12 +227,16 @@ type DeleteManyOutput = {
|
|
|
235
227
|
|
|
236
228
|
---
|
|
237
229
|
|
|
230
|
+
## Goals
|
|
231
|
+
|
|
232
|
+
- Fast and simple backend prototyping
|
|
233
|
+
- No dependancies
|
|
234
|
+
|
|
238
235
|
## Non-goals
|
|
239
236
|
|
|
240
237
|
- Concurrency control
|
|
241
238
|
- High-performance querying
|
|
242
239
|
- Large datasets
|
|
243
|
-
- ACID guarantees
|
|
244
240
|
|
|
245
241
|
For these, a dedicated database is recommended.
|
|
246
242
|
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -47,6 +47,37 @@ class UninitError extends DbError {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
class MultiEntryDb {
|
|
50
|
+
async *iterWhere(predicate, pagination) {
|
|
51
|
+
if (!pagination) {
|
|
52
|
+
for await (const entry of this.iterEntries()) {
|
|
53
|
+
const isMatch = await predicate(entry);
|
|
54
|
+
if (isMatch)
|
|
55
|
+
yield entry;
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const { take, page } = pagination;
|
|
60
|
+
this.validatePaginationField(take, 'take');
|
|
61
|
+
this.validatePaginationField(page, 'page');
|
|
62
|
+
const startIndex = page * take;
|
|
63
|
+
const endIndex = startIndex + take;
|
|
64
|
+
let totalMatched = 0;
|
|
65
|
+
for await (const entry of this.iterEntries()) {
|
|
66
|
+
if (totalMatched >= endIndex)
|
|
67
|
+
break;
|
|
68
|
+
const isMatch = await predicate(entry);
|
|
69
|
+
totalMatched++;
|
|
70
|
+
if (isMatch && totalMatched - 1 >= startIndex) {
|
|
71
|
+
yield entry;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
validatePaginationField(field, fieldName) {
|
|
76
|
+
if (isNaN(field))
|
|
77
|
+
throw new Error(`PaginationInput.${fieldName} must not be NaN`);
|
|
78
|
+
if (field < 0)
|
|
79
|
+
throw new Error(`PaginationInput.${fieldName} must not be less than 0, got ${field}`);
|
|
80
|
+
}
|
|
50
81
|
async getByIdOrThrow(id) {
|
|
51
82
|
const entry = await this.getById(id);
|
|
52
83
|
if (!entry)
|
|
@@ -64,30 +95,9 @@ class MultiEntryDb {
|
|
|
64
95
|
return match;
|
|
65
96
|
}
|
|
66
97
|
async getWhere(predicate, pagination) {
|
|
67
|
-
let totalMatched = 0;
|
|
68
98
|
const entries = [];
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const isMatch = predicate(entry);
|
|
72
|
-
if (isMatch)
|
|
73
|
-
entries.push(entry);
|
|
74
|
-
}
|
|
75
|
-
return entries;
|
|
76
|
-
}
|
|
77
|
-
const { take, page } = pagination;
|
|
78
|
-
const skip = pagination.skip ?? 0;
|
|
79
|
-
const startIndex = (page - 1) * take + skip;
|
|
80
|
-
const endIndex = startIndex + take;
|
|
81
|
-
for await (const entry of this.iterEntries()) {
|
|
82
|
-
const isMatch = predicate(entry);
|
|
83
|
-
if (isMatch) {
|
|
84
|
-
if (totalMatched >= startIndex && totalMatched < endIndex) {
|
|
85
|
-
entries.push(entry);
|
|
86
|
-
}
|
|
87
|
-
totalMatched++;
|
|
88
|
-
if (totalMatched >= endIndex)
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
99
|
+
for await (const entry of this.iterWhere(predicate, pagination)) {
|
|
100
|
+
entries.push(entry);
|
|
91
101
|
}
|
|
92
102
|
return entries;
|
|
93
103
|
}
|
|
@@ -101,15 +111,27 @@ class MultiEntryDb {
|
|
|
101
111
|
}
|
|
102
112
|
return ids;
|
|
103
113
|
}
|
|
114
|
+
async updateById(id, updater) {
|
|
115
|
+
const entry = await this.getByIdOrThrow(id);
|
|
116
|
+
return this.updateEntry(entry, updater);
|
|
117
|
+
}
|
|
118
|
+
async updateFirstWhere(predicate, updater) {
|
|
119
|
+
return this.updateWhere(predicate, updater, { page: 0, take: 1 });
|
|
120
|
+
}
|
|
121
|
+
async updateWhere(predicate, updater, pagination) {
|
|
122
|
+
const result = [];
|
|
123
|
+
for await (const entry of this.iterWhere(predicate, pagination)) {
|
|
124
|
+
result.push(await this.updateEntry(entry, updater));
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
104
128
|
deleteByIds(ids) {
|
|
105
129
|
return this.deleteWhere((entry) => ids.includes(entry.id));
|
|
106
130
|
}
|
|
107
131
|
async deleteWhere(predicate) {
|
|
108
132
|
const deletedIds = [];
|
|
109
133
|
const ignoredIds = [];
|
|
110
|
-
for await (const entry of this.
|
|
111
|
-
if (!predicate(entry))
|
|
112
|
-
continue;
|
|
134
|
+
for await (const entry of this.iterWhere(predicate)) {
|
|
113
135
|
const didDelete = await this.deleteById(entry.id);
|
|
114
136
|
if (didDelete) {
|
|
115
137
|
deletedIds.push(entry.id);
|
|
@@ -121,37 +143,15 @@ class MultiEntryDb {
|
|
|
121
143
|
return { deletedIds, ignoredIds };
|
|
122
144
|
}
|
|
123
145
|
async exists(id) {
|
|
124
|
-
|
|
125
|
-
return entry !== null;
|
|
146
|
+
return (await this.getById(id)) !== null;
|
|
126
147
|
}
|
|
127
148
|
countAll() {
|
|
128
149
|
return this.countWhere(() => true);
|
|
129
150
|
}
|
|
130
151
|
async countWhere(predicate, pagination) {
|
|
131
|
-
let totalMatched = 0;
|
|
132
152
|
let count = 0;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const isMatch = predicate(entry);
|
|
136
|
-
if (isMatch)
|
|
137
|
-
count++;
|
|
138
|
-
}
|
|
139
|
-
return count;
|
|
140
|
-
}
|
|
141
|
-
const { take, page } = pagination;
|
|
142
|
-
const skip = pagination.skip ?? 0;
|
|
143
|
-
const startIndex = (page - 1) * take + skip;
|
|
144
|
-
const endIndex = startIndex + take;
|
|
145
|
-
for await (const entry of this.iterEntries()) {
|
|
146
|
-
const isMatch = predicate(entry);
|
|
147
|
-
if (isMatch) {
|
|
148
|
-
if (totalMatched >= startIndex && totalMatched < endIndex)
|
|
149
|
-
count++;
|
|
150
|
-
totalMatched++;
|
|
151
|
-
if (totalMatched >= endIndex)
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
153
|
+
for await (const _ of this.iterWhere(predicate, pagination))
|
|
154
|
+
count++;
|
|
155
155
|
return count;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -383,6 +383,7 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
383
383
|
dirpath;
|
|
384
384
|
files;
|
|
385
385
|
parser;
|
|
386
|
+
disableLogs;
|
|
386
387
|
noPathlikeIds;
|
|
387
388
|
constructor(dirpath, options) {
|
|
388
389
|
super();
|
|
@@ -390,6 +391,7 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
390
391
|
this.files = new Files();
|
|
391
392
|
this.parser = options?.parser ?? JSON;
|
|
392
393
|
this.noPathlikeIds = options?.noPathlikeIds ?? true;
|
|
394
|
+
this.disableLogs = options?.disableLogs ?? false;
|
|
393
395
|
}
|
|
394
396
|
async create(entry) {
|
|
395
397
|
await this.writeEntry(entry);
|
|
@@ -405,18 +407,18 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
405
407
|
return entry;
|
|
406
408
|
}
|
|
407
409
|
catch (error) {
|
|
408
|
-
|
|
410
|
+
if (!this.disableLogs)
|
|
411
|
+
console.error('Failed to read entry', error);
|
|
409
412
|
// File doesn't exist or invalid JSON
|
|
410
413
|
return null;
|
|
411
414
|
}
|
|
412
415
|
}
|
|
413
|
-
async
|
|
414
|
-
const entry = await this.getByIdOrThrow(id);
|
|
416
|
+
async updateEntry(entry, updater) {
|
|
415
417
|
const updatedEntryFields = await updater(entry);
|
|
416
418
|
const updatedEntry = { ...entry, ...updatedEntryFields };
|
|
417
419
|
await this.writeEntry(updatedEntry);
|
|
418
|
-
if (updatedEntry.id !== id) {
|
|
419
|
-
await this.deleteById(id);
|
|
420
|
+
if (updatedEntry.id !== entry.id) {
|
|
421
|
+
await this.deleteById(entry.id);
|
|
420
422
|
}
|
|
421
423
|
return updatedEntry;
|
|
422
424
|
}
|
|
@@ -523,13 +525,13 @@ class MultiEntryMemDb extends MultiEntryDb {
|
|
|
523
525
|
async getById(id) {
|
|
524
526
|
return this.entries.get(id) ?? null;
|
|
525
527
|
}
|
|
526
|
-
async
|
|
527
|
-
const entry = await this.getByIdOrThrow(id);
|
|
528
|
+
async updateEntry(entry, updater) {
|
|
528
529
|
const updatedEntryFields = await updater(entry);
|
|
529
530
|
const updatedEntry = { ...entry, ...updatedEntryFields };
|
|
530
531
|
this.entries.set(updatedEntry.id, updatedEntry);
|
|
531
|
-
if (updatedEntry.id !== id)
|
|
532
|
-
this.
|
|
532
|
+
if (updatedEntry.id !== entry.id) {
|
|
533
|
+
await this.deleteById(entry.id);
|
|
534
|
+
}
|
|
533
535
|
return updatedEntry;
|
|
534
536
|
}
|
|
535
537
|
async deleteById(id) {
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","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":["FileType","fs","path","fsSync","readline"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAM,MAAO,OAAQ,SAAQ,KAAK,CAAA;AAAG;AAE/B,MAAO,aAAc,SAAQ,OAAO,CAAA;AAAG;AAEvC,MAAO,aAAc,SAAQ,OAAO,CAAA;AAAG;AAEvC,MAAO,WAAY,SAAQ,OAAO,CAAA;AAAG;AAErC,MAAO,cAAe,SAAQ,OAAO,CAAA;AACzC,IAAA,WAAA,CAAY,EAAW,EAAA;AACrB,QAAA,KAAK,CAAC,CAAA,kBAAA,EAAqB,EAAE,CAAA,CAAA,CAAG,CAAC;IACnC;AACD;AAEK,MAAO,WAAY,SAAQ,OAAO,CAAA;AACtC,IAAA,WAAA,GAAA;QACE,KAAK,CAAC,iFAAiF,CAAC;IAC1F;AACD;;MCTqB,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,aAAa,CAAC,kBAAkB,EAAE,CAAA,gBAAA,CAAkB,CAAC;AAC3E,QAAA,OAAO,KAAK;IACd;IAEA,MAAM,aAAa,CAAC,SAAyB,EAAA;AAC3C,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACpE,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;IAC9B;IAEA,MAAM,oBAAoB,CAAC,SAAyB,EAAA;QAClD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;AACjD,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,MAAM,IAAI,aAAa,CAAC,4BAA4B,CAAC;AACjE,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;;MC/IqB,aAAa,CAAA;AAKlC;;ACLK,SAAU,kBAAkB,CAAI,MAA0B,EAAE,IAAY,EAAA;IAC5E,OAAO,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;AACzE;;ACoDYA;AAAZ,CAAA,UAAY,QAAQ,EAAA;AAClB,IAAA,QAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACb,IAAA,QAAA,CAAA,WAAA,CAAA,GAAA,WAAuB;;AAEzB,CAAC,EAJWA,gBAAQ,KAARA,gBAAQ,GAAA,EAAA,CAAA,CAAA;;ACzBpB,MAAM,gBAAgB,GAAmB,OAAO;MAEnC,KAAK,CAAA;AAChB,IAAA,MAAM,IAAI,CAAC,OAAe,EAAE,OAAe,EAAA;QACzC,MAAMC,aAAE,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,WAAW,CAAC,gBAAgB,eAAe,CAAA,gBAAA,CAAkB,CAAC;QAC1E;QAEA,MAAM,WAAW,GAAG,MAAMA,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC;AAE7C,QAAA,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,cAAc,GAAGC,eAAI,CAAC,OAAO,CAAC,eAAe,CAAC;AACpD,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;YACtC,MAAMD,aAAE,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,WAAW,CAAC,IAAI,UAAU,CAAA,uCAAA,CAAyC,CAAC;YAChF;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,MAAMA,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC;AAE7C,QAAA,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,cAAc,GAAGC,eAAI,CAAC,OAAO,CAAC,eAAe,CAAC;AACpD,YAAA,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;YACtC,MAAMD,aAAE,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,MAAMA,aAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAE5C,YAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;gBAC3B,MAAM,eAAe,GAAGC,eAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC;gBACpD,MAAM,aAAa,GAAGA,eAAI,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,MAAMD,aAAE,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,GAAGC,eAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;AACzC,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;QAElC,MAAMD,aAAE,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,MAAMA,aAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;QAC9C;AAEA,QAAA,MAAM,MAAM,GAAGE,iBAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC9D,QAAA,MAAM,MAAM,GAAGC,mBAAQ,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,MAAMH,aAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC7C;IAEA,MAAM,MAAM,CAAC,QAAgB,EAAA;AAC3B,QAAA,IAAI;AACF,YAAA,MAAMA,aAAE,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,MAAMA,aAAE,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,MAAMA,aAAE,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,MAAMA,aAAE,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,MAAMA,aAAE,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,CAACC,eAAI,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,EAAEF,gBAAQ,CAAC,SAAS;gBACxB,QAAQ;aACT;QACH;AACA,QAAA,IAAI,MAAM;YACR,OAAO;AACL,gBAAA,GAAG,UAAU;gBACb,IAAI,EAAEA,gBAAQ,CAAC,IAAI;aACpB;AAEH,QAAA,MAAM,IAAI,WAAW,CAAC,WAAW,QAAQ,CAAA,gCAAA,CAAkC,CAAC;IAC9E;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,MAAMC,aAAE,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,MAAMA,aAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAElE,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;AAC3B,YAAA,MAAM,QAAQ,GAAGC,eAAI,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;;AC7QK,MAAO,gBAAyC,SAAQ,YAAe,CAAA;AACxD,IAAA,OAAO;AACP,IAAA,KAAK;AACL,IAAA,MAAM;AAChB,IAAA,aAAa;IAEtB,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,cAAc,CAAC,EAAE,CAAC;AAErD,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,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACnD,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,OAAOA,eAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA,EAAG,MAAM,CAAC,EAAE,CAAC,CAAA,KAAA,CAAO,CAAC;IACtD;IAEU,MAAM,UAAU,CAAC,KAAQ,EAAA;QACjC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AAAE,YAAA,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAEjE,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,KAAc,EAAA;QACtB,IAAI,CAAC,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,IAAI;AAEpC,QAAA,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;AACxB,QAAA,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;AAAE,YAAA,OAAO,KAAK;AAEvD,QAAA,OAAO,IAAI;IACb;IAEA,OAAO,WAAW,GAAA;QAChB,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;AAEA,IAAA,OAAO,OAAO,CAAC,cAAyC,EAAA;AACtD,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,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;AAChD,YAAA,MAAM,EAAE,GAAG,cAAc,GAAG,kBAAkB,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG,QAAQ;AACnF,YAAA,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAAE,gBAAA,MAAM,EAAE;QAClC;IACF;AACD;;AClHK,MAAO,iBAAqB,SAAQ,aAAgB,CAAA;AAInC,IAAA,QAAA;AACA,IAAA,MAAA;AAJF,IAAA,KAAK,GAAU,IAAI,KAAK,EAAE;IAE7C,WAAA,CACqB,QAAgB,EAChB,MAAA,GAA6B,IAAI,EAAA;AAEpD,QAAA,KAAK,EAAE;QAHY,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,MAAM,GAAN,MAAM;IAG3B;IAEA,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,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACnD,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;;AC7CK,MAAO,eAAwC,SAAQ,YAAe,CAAA;AAChE,IAAA,OAAO,GAAoB,IAAI,GAAG,EAAE;IAE9C,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;IAEA,OAAO,WAAW,GAAA;QAChB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE;AACzC,YAAA,MAAM,KAAK;QACb;IACF;IAEA,OAAO,OAAO,GAAA;QACZ,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;AACpC,YAAA,MAAM,EAAE;QACV;IACF;IAEA,MAAM,OAAO,CAAC,OAAe,EAAA;AAC3B,QAAA,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAI,OAAO,CAAC;AAC/C,QAAA,MAAM,MAAM,CAAC,OAAO,EAAE;QAEtB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE;AAEA,IAAA,MAAM,IAAI,CAAC,OAAe,EAAE,MAA2B,EAAA;QACrD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAI,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC;AAE3D,QAAA,MAAM,IAAI,CAAC,OAAO,EAAE;QACpB,WAAW,MAAM,KAAK,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE;AAC9C,YAAA,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAC1B;IACF;AACD;;AC7DK,MAAO,gBAAoB,SAAQ,aAAgB,CAAA;IAC7C,KAAK,GAAa,IAAI;AAEhC,IAAA,WAAA,CAAY,eAAyB,IAAI,EAAA;AACvC,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,KAAK,GAAG,YAAY;IAC3B;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI;IAC5B;AAEA,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE,MAAM,IAAI,WAAW,EAAE;QAChD,OAAO,IAAI,CAAC,KAAK;IACnB;IAEA,MAAM,KAAK,CAAC,cAAgC,EAAA;AAC1C,QAAA,IAAI,KAAQ;AAEZ,QAAA,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE;YACxC,MAAM,OAAO,GAAG,cAA0C;AAE1D,YAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;gBAAE,MAAM,IAAI,WAAW,EAAE;YAEhD,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;AAEA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;IAEA,MAAM,OAAO,CAAC,QAAgB,EAAA;AAC5B,QAAA,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAI,QAAQ,CAAC;QACjD,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACvC;AAEA,IAAA,MAAM,IAAI,CAAC,QAAgB,EAAE,MAA2B,EAAA;QACtD,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAI,QAAQ,EAAE,MAAM,CAAC;AACzD,QAAA,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE;AAC1C,QAAA,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;IAC5B;AACD;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs","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 abstract getById(id: T['id']): Promise<T | null>\n protected abstract updateEntry(entry: T, updater: UpdaterFn<T>): Promise<T>\n abstract deleteById(id: T['id']): Promise<boolean>\n abstract destroy(): Promise<void>\n abstract iterEntries(): AsyncIterable<T>\n abstract iterIds(): AsyncIterable<T['id']>\n\n private async *iterWhere(\n predicate: PredicateFn<T>,\n pagination?: PaginationInput,\n ): AsyncIterable<T> {\n if (!pagination) {\n for await (const entry of this.iterEntries()) {\n const isMatch = await predicate(entry)\n if (isMatch) yield entry\n }\n return\n }\n\n const { take, page } = pagination\n this.validatePaginationField(take, 'take')\n this.validatePaginationField(page, 'page')\n\n const startIndex = page * take\n const endIndex = startIndex + take\n let totalMatched = 0\n\n for await (const entry of this.iterEntries()) {\n if (totalMatched >= endIndex) break\n\n const isMatch = await predicate(entry)\n totalMatched++\n if (isMatch && totalMatched - 1 >= startIndex) {\n yield entry\n }\n }\n }\n\n private validatePaginationField(field: number, fieldName: string) {\n if (isNaN(field)) throw new Error(`PaginationInput.${fieldName} must not be NaN`)\n if (field < 0)\n throw new Error(`PaginationInput.${fieldName} must not be less than 0, got ${field}`)\n }\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 const entries: T[] = []\n for await (const entry of this.iterWhere(predicate, pagination)) {\n entries.push(entry)\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 async updateById(id: T['id'], updater: UpdaterFn<T>): Promise<T> {\n const entry = await this.getByIdOrThrow(id)\n return this.updateEntry(entry, updater)\n }\n\n async updateFirstWhere(predicate: PredicateFn<T>, updater: UpdaterFn<T>) {\n return this.updateWhere(predicate, updater, { page: 0, take: 1 })\n }\n\n async updateWhere(\n predicate: PredicateFn<T>,\n updater: UpdaterFn<T>,\n pagination?: PaginationInput,\n ): Promise<T[]> {\n const result: T[] = []\n for await (const entry of this.iterWhere(predicate, pagination)) {\n result.push(await this.updateEntry(entry, updater))\n }\n return result\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.iterWhere(predicate)) {\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 return (await this.getById(id)) !== 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 count = 0\n for await (const _ of this.iterWhere(predicate, pagination)) count++\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}\n\nexport type DeleteManyOutput = {\n deletedIds: Id[]\n ignoredIds: Id[]\n}\n\nexport type PredicateFn<T extends Identifiable> = (entry: T) => boolean | Promise<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 disableLogs?: boolean\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 JsonEntryParser,\n MultiEntryFileDbOptions,\n MultiEntryDb,\n InvalidIdError,\n runJsonEntryParser,\n UpdaterFn,\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 protected readonly disableLogs: boolean\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 this.disableLogs = options?.disableLogs ?? false\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 if (!this.disableLogs) console.error('Failed to read entry', error)\n // File doesn't exist or invalid JSON\n return null\n }\n }\n\n protected async updateEntry(entry: T, updater: UpdaterFn<T>): Promise<T> {\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n await this.writeEntry(updatedEntry)\n\n if (updatedEntry.id !== entry.id) {\n await this.deleteById(entry.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","import { SingleEntryDb, JsonEntryParser, runJsonEntryParser, UpdaterFn } 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 | UpdaterFn<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, MultiEntryDb, JsonEntryParser, UpdaterFn } 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 protected async updateEntry(entry: T, updater: UpdaterFn<T>): Promise<T> {\n const updatedEntryFields = await updater(entry)\n const updatedEntry = { ...entry, ...updatedEntryFields }\n\n this.entries.set(updatedEntry.id, updatedEntry)\n\n if (updatedEntry.id !== entry.id) {\n await this.deleteById(entry.id)\n }\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":["FileType","fs","path","fsSync","readline"],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -23,6 +23,37 @@ class UninitError extends DbError {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
class MultiEntryDb {
|
|
26
|
+
async *iterWhere(predicate, pagination) {
|
|
27
|
+
if (!pagination) {
|
|
28
|
+
for await (const entry of this.iterEntries()) {
|
|
29
|
+
const isMatch = await predicate(entry);
|
|
30
|
+
if (isMatch)
|
|
31
|
+
yield entry;
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const { take, page } = pagination;
|
|
36
|
+
this.validatePaginationField(take, 'take');
|
|
37
|
+
this.validatePaginationField(page, 'page');
|
|
38
|
+
const startIndex = page * take;
|
|
39
|
+
const endIndex = startIndex + take;
|
|
40
|
+
let totalMatched = 0;
|
|
41
|
+
for await (const entry of this.iterEntries()) {
|
|
42
|
+
if (totalMatched >= endIndex)
|
|
43
|
+
break;
|
|
44
|
+
const isMatch = await predicate(entry);
|
|
45
|
+
totalMatched++;
|
|
46
|
+
if (isMatch && totalMatched - 1 >= startIndex) {
|
|
47
|
+
yield entry;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
validatePaginationField(field, fieldName) {
|
|
52
|
+
if (isNaN(field))
|
|
53
|
+
throw new Error(`PaginationInput.${fieldName} must not be NaN`);
|
|
54
|
+
if (field < 0)
|
|
55
|
+
throw new Error(`PaginationInput.${fieldName} must not be less than 0, got ${field}`);
|
|
56
|
+
}
|
|
26
57
|
async getByIdOrThrow(id) {
|
|
27
58
|
const entry = await this.getById(id);
|
|
28
59
|
if (!entry)
|
|
@@ -40,30 +71,9 @@ class MultiEntryDb {
|
|
|
40
71
|
return match;
|
|
41
72
|
}
|
|
42
73
|
async getWhere(predicate, pagination) {
|
|
43
|
-
let totalMatched = 0;
|
|
44
74
|
const entries = [];
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const isMatch = predicate(entry);
|
|
48
|
-
if (isMatch)
|
|
49
|
-
entries.push(entry);
|
|
50
|
-
}
|
|
51
|
-
return entries;
|
|
52
|
-
}
|
|
53
|
-
const { take, page } = pagination;
|
|
54
|
-
const skip = pagination.skip ?? 0;
|
|
55
|
-
const startIndex = (page - 1) * take + skip;
|
|
56
|
-
const endIndex = startIndex + take;
|
|
57
|
-
for await (const entry of this.iterEntries()) {
|
|
58
|
-
const isMatch = predicate(entry);
|
|
59
|
-
if (isMatch) {
|
|
60
|
-
if (totalMatched >= startIndex && totalMatched < endIndex) {
|
|
61
|
-
entries.push(entry);
|
|
62
|
-
}
|
|
63
|
-
totalMatched++;
|
|
64
|
-
if (totalMatched >= endIndex)
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
75
|
+
for await (const entry of this.iterWhere(predicate, pagination)) {
|
|
76
|
+
entries.push(entry);
|
|
67
77
|
}
|
|
68
78
|
return entries;
|
|
69
79
|
}
|
|
@@ -77,15 +87,27 @@ class MultiEntryDb {
|
|
|
77
87
|
}
|
|
78
88
|
return ids;
|
|
79
89
|
}
|
|
90
|
+
async updateById(id, updater) {
|
|
91
|
+
const entry = await this.getByIdOrThrow(id);
|
|
92
|
+
return this.updateEntry(entry, updater);
|
|
93
|
+
}
|
|
94
|
+
async updateFirstWhere(predicate, updater) {
|
|
95
|
+
return this.updateWhere(predicate, updater, { page: 0, take: 1 });
|
|
96
|
+
}
|
|
97
|
+
async updateWhere(predicate, updater, pagination) {
|
|
98
|
+
const result = [];
|
|
99
|
+
for await (const entry of this.iterWhere(predicate, pagination)) {
|
|
100
|
+
result.push(await this.updateEntry(entry, updater));
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
80
104
|
deleteByIds(ids) {
|
|
81
105
|
return this.deleteWhere((entry) => ids.includes(entry.id));
|
|
82
106
|
}
|
|
83
107
|
async deleteWhere(predicate) {
|
|
84
108
|
const deletedIds = [];
|
|
85
109
|
const ignoredIds = [];
|
|
86
|
-
for await (const entry of this.
|
|
87
|
-
if (!predicate(entry))
|
|
88
|
-
continue;
|
|
110
|
+
for await (const entry of this.iterWhere(predicate)) {
|
|
89
111
|
const didDelete = await this.deleteById(entry.id);
|
|
90
112
|
if (didDelete) {
|
|
91
113
|
deletedIds.push(entry.id);
|
|
@@ -97,37 +119,15 @@ class MultiEntryDb {
|
|
|
97
119
|
return { deletedIds, ignoredIds };
|
|
98
120
|
}
|
|
99
121
|
async exists(id) {
|
|
100
|
-
|
|
101
|
-
return entry !== null;
|
|
122
|
+
return (await this.getById(id)) !== null;
|
|
102
123
|
}
|
|
103
124
|
countAll() {
|
|
104
125
|
return this.countWhere(() => true);
|
|
105
126
|
}
|
|
106
127
|
async countWhere(predicate, pagination) {
|
|
107
|
-
let totalMatched = 0;
|
|
108
128
|
let count = 0;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const isMatch = predicate(entry);
|
|
112
|
-
if (isMatch)
|
|
113
|
-
count++;
|
|
114
|
-
}
|
|
115
|
-
return count;
|
|
116
|
-
}
|
|
117
|
-
const { take, page } = pagination;
|
|
118
|
-
const skip = pagination.skip ?? 0;
|
|
119
|
-
const startIndex = (page - 1) * take + skip;
|
|
120
|
-
const endIndex = startIndex + take;
|
|
121
|
-
for await (const entry of this.iterEntries()) {
|
|
122
|
-
const isMatch = predicate(entry);
|
|
123
|
-
if (isMatch) {
|
|
124
|
-
if (totalMatched >= startIndex && totalMatched < endIndex)
|
|
125
|
-
count++;
|
|
126
|
-
totalMatched++;
|
|
127
|
-
if (totalMatched >= endIndex)
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
129
|
+
for await (const _ of this.iterWhere(predicate, pagination))
|
|
130
|
+
count++;
|
|
131
131
|
return count;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -359,6 +359,7 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
359
359
|
dirpath;
|
|
360
360
|
files;
|
|
361
361
|
parser;
|
|
362
|
+
disableLogs;
|
|
362
363
|
noPathlikeIds;
|
|
363
364
|
constructor(dirpath, options) {
|
|
364
365
|
super();
|
|
@@ -366,6 +367,7 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
366
367
|
this.files = new Files();
|
|
367
368
|
this.parser = options?.parser ?? JSON;
|
|
368
369
|
this.noPathlikeIds = options?.noPathlikeIds ?? true;
|
|
370
|
+
this.disableLogs = options?.disableLogs ?? false;
|
|
369
371
|
}
|
|
370
372
|
async create(entry) {
|
|
371
373
|
await this.writeEntry(entry);
|
|
@@ -381,18 +383,18 @@ class MultiEntryFileDb extends MultiEntryDb {
|
|
|
381
383
|
return entry;
|
|
382
384
|
}
|
|
383
385
|
catch (error) {
|
|
384
|
-
|
|
386
|
+
if (!this.disableLogs)
|
|
387
|
+
console.error('Failed to read entry', error);
|
|
385
388
|
// File doesn't exist or invalid JSON
|
|
386
389
|
return null;
|
|
387
390
|
}
|
|
388
391
|
}
|
|
389
|
-
async
|
|
390
|
-
const entry = await this.getByIdOrThrow(id);
|
|
392
|
+
async updateEntry(entry, updater) {
|
|
391
393
|
const updatedEntryFields = await updater(entry);
|
|
392
394
|
const updatedEntry = { ...entry, ...updatedEntryFields };
|
|
393
395
|
await this.writeEntry(updatedEntry);
|
|
394
|
-
if (updatedEntry.id !== id) {
|
|
395
|
-
await this.deleteById(id);
|
|
396
|
+
if (updatedEntry.id !== entry.id) {
|
|
397
|
+
await this.deleteById(entry.id);
|
|
396
398
|
}
|
|
397
399
|
return updatedEntry;
|
|
398
400
|
}
|
|
@@ -499,13 +501,13 @@ class MultiEntryMemDb extends MultiEntryDb {
|
|
|
499
501
|
async getById(id) {
|
|
500
502
|
return this.entries.get(id) ?? null;
|
|
501
503
|
}
|
|
502
|
-
async
|
|
503
|
-
const entry = await this.getByIdOrThrow(id);
|
|
504
|
+
async updateEntry(entry, updater) {
|
|
504
505
|
const updatedEntryFields = await updater(entry);
|
|
505
506
|
const updatedEntry = { ...entry, ...updatedEntryFields };
|
|
506
507
|
this.entries.set(updatedEntry.id, updatedEntry);
|
|
507
|
-
if (updatedEntry.id !== id)
|
|
508
|
-
this.
|
|
508
|
+
if (updatedEntry.id !== entry.id) {
|
|
509
|
+
await this.deleteById(entry.id);
|
|
510
|
+
}
|
|
509
511
|
return updatedEntry;
|
|
510
512
|
}
|
|
511
513
|
async deleteById(id) {
|