@jsonkit/db 1.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 +3 -0
- package/dist/cjs/index.cjs +416 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/index.js +391 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/__tests__/multiEntryFileDb.test.d.ts +1 -0
- package/dist/types/__tests__/singleEntryFileDb.test.d.ts +1 -0
- package/dist/types/files.d.ts +44 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/multiEntryFileDb.d.ts +27 -0
- package/dist/types/singleEntryFileDb.d.ts +14 -0
- package/dist/types/types.d.ts +26 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs/promises');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var fsSync = require('fs');
|
|
6
|
+
var readline = require('readline');
|
|
7
|
+
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
26
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
27
|
+
var fsSync__namespace = /*#__PURE__*/_interopNamespaceDefault(fsSync);
|
|
28
|
+
var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
|
|
29
|
+
|
|
30
|
+
exports.FileType = void 0;
|
|
31
|
+
(function (FileType) {
|
|
32
|
+
FileType["File"] = "file";
|
|
33
|
+
FileType["Directory"] = "directory";
|
|
34
|
+
//Symlink: 'symlink'
|
|
35
|
+
})(exports.FileType || (exports.FileType = {}));
|
|
36
|
+
|
|
37
|
+
const DEFUALT_ENCODING = 'utf-8';
|
|
38
|
+
class FilesService {
|
|
39
|
+
async move(oldPath, newPath) {
|
|
40
|
+
await fs__namespace.rename(oldPath, newPath);
|
|
41
|
+
}
|
|
42
|
+
async copy(sourcePath, destinationPath, options) {
|
|
43
|
+
const { recursive = false, overwrite = true } = options ?? {};
|
|
44
|
+
// Check if destination exists and handle overwrite
|
|
45
|
+
if (!overwrite && (await this.exists(destinationPath))) {
|
|
46
|
+
throw new Error(`Destination '${destinationPath}' already exists`);
|
|
47
|
+
}
|
|
48
|
+
const sourceStats = await fs__namespace.stat(sourcePath);
|
|
49
|
+
if (sourceStats.isFile()) {
|
|
50
|
+
const destinationDir = path__namespace.dirname(destinationPath);
|
|
51
|
+
await this.mkdirUnsafe(destinationDir);
|
|
52
|
+
await fs__namespace.copyFile(sourcePath, destinationPath);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (sourceStats.isDirectory()) {
|
|
56
|
+
if (!recursive) {
|
|
57
|
+
throw new Error(`'${sourcePath}' is a directory (use recursive option)`);
|
|
58
|
+
}
|
|
59
|
+
await this.copyRecursive(sourcePath, destinationPath);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async copyRecursive(sourcePath, destinationPath) {
|
|
63
|
+
const sourceStats = await fs__namespace.stat(sourcePath);
|
|
64
|
+
if (sourceStats.isFile()) {
|
|
65
|
+
const destinationDir = path__namespace.dirname(destinationPath);
|
|
66
|
+
await this.mkdirUnsafe(destinationDir);
|
|
67
|
+
await fs__namespace.copyFile(sourcePath, destinationPath);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (sourceStats.isDirectory()) {
|
|
71
|
+
await this.mkdirUnsafe(destinationPath);
|
|
72
|
+
const entries = await fs__namespace.readdir(sourcePath);
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
const sourceEntryPath = path__namespace.join(sourcePath, entry);
|
|
75
|
+
const destEntryPath = path__namespace.join(destinationPath, entry);
|
|
76
|
+
await this.copyRecursive(sourceEntryPath, destEntryPath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async mkdir(filepath) {
|
|
81
|
+
await this.mkdirUnsafe(filepath);
|
|
82
|
+
}
|
|
83
|
+
async mkdirUnsafe(filepath) {
|
|
84
|
+
await fs__namespace.mkdir(filepath, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
async write(filepath, content, options) {
|
|
87
|
+
const { encoding = DEFUALT_ENCODING } = options ?? {};
|
|
88
|
+
const parentDirs = path__namespace.dirname(filepath);
|
|
89
|
+
await this.mkdirUnsafe(parentDirs);
|
|
90
|
+
await fs__namespace.writeFile(filepath, content, encoding);
|
|
91
|
+
}
|
|
92
|
+
async touch(filepath) {
|
|
93
|
+
const exists = await this.exists(filepath);
|
|
94
|
+
if (!exists)
|
|
95
|
+
await this.write(filepath, '');
|
|
96
|
+
}
|
|
97
|
+
async read(filepath, options) {
|
|
98
|
+
const { encoding = DEFUALT_ENCODING, lines } = options ?? {};
|
|
99
|
+
if (lines === undefined) {
|
|
100
|
+
return await fs__namespace.readFile(filepath, encoding);
|
|
101
|
+
}
|
|
102
|
+
const stream = fsSync__namespace.createReadStream(filepath, { encoding });
|
|
103
|
+
const reader = readline__namespace.createInterface({
|
|
104
|
+
input: stream,
|
|
105
|
+
crlfDelay: Infinity,
|
|
106
|
+
});
|
|
107
|
+
let result = '';
|
|
108
|
+
let linesRead = 0;
|
|
109
|
+
for await (const line of reader) {
|
|
110
|
+
if (linesRead >= lines)
|
|
111
|
+
break;
|
|
112
|
+
result += line + '\n';
|
|
113
|
+
linesRead++;
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
async delete(filepath, options) {
|
|
118
|
+
const { force = true, recursive = true } = options ?? {};
|
|
119
|
+
await fs__namespace.rm(filepath, { force, recursive });
|
|
120
|
+
}
|
|
121
|
+
async exists(filepath) {
|
|
122
|
+
try {
|
|
123
|
+
await fs__namespace.access(filepath);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async isDir(filepath) {
|
|
131
|
+
try {
|
|
132
|
+
const stats = await fs__namespace.stat(filepath);
|
|
133
|
+
return stats.isDirectory();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async isFile(filepath) {
|
|
140
|
+
try {
|
|
141
|
+
const stats = await fs__namespace.stat(filepath);
|
|
142
|
+
return stats.isFile();
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async isSymlink(filepath) {
|
|
149
|
+
try {
|
|
150
|
+
const stats = await fs__namespace.stat(filepath);
|
|
151
|
+
return stats.isSymbolicLink();
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async getMeta(filepath, options) {
|
|
158
|
+
const { depth = 0, stripBasepath } = options ?? {};
|
|
159
|
+
const stats = await fs__namespace.stat(filepath);
|
|
160
|
+
const isDir = stats.isDirectory();
|
|
161
|
+
const isFile = stats.isFile();
|
|
162
|
+
const { size, ctime, mtime, atime } = stats;
|
|
163
|
+
const commonMeta = {
|
|
164
|
+
path: this.stripBasepath(filepath, stripBasepath),
|
|
165
|
+
size,
|
|
166
|
+
created: ctime,
|
|
167
|
+
modified: mtime,
|
|
168
|
+
accessed: atime,
|
|
169
|
+
};
|
|
170
|
+
if (isDir) {
|
|
171
|
+
const children = [];
|
|
172
|
+
if (depth > 0) {
|
|
173
|
+
const childNames = await this.list(filepath);
|
|
174
|
+
for (const child of childNames) {
|
|
175
|
+
const childDepth = Math.max(0, depth - 1);
|
|
176
|
+
const childMeta = await this.getMeta(path__namespace.join(filepath, child), {
|
|
177
|
+
depth: childDepth,
|
|
178
|
+
stripBasepath,
|
|
179
|
+
});
|
|
180
|
+
children.push(childMeta);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
...commonMeta,
|
|
185
|
+
type: exports.FileType.Directory,
|
|
186
|
+
children,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (isFile)
|
|
190
|
+
return {
|
|
191
|
+
...commonMeta,
|
|
192
|
+
type: exports.FileType.File,
|
|
193
|
+
};
|
|
194
|
+
throw new Error(`File at ${filepath} is not normal file or directory`);
|
|
195
|
+
}
|
|
196
|
+
async list(dirpath, options) {
|
|
197
|
+
const { depth = 0, stripBasepath } = options ?? {};
|
|
198
|
+
if (depth > 0) {
|
|
199
|
+
return await this.listRecursive(dirpath, depth, 0, stripBasepath);
|
|
200
|
+
}
|
|
201
|
+
return await fs__namespace.readdir(dirpath);
|
|
202
|
+
}
|
|
203
|
+
async *listRead(dirpath, options) {
|
|
204
|
+
const { depth = 0 } = options ?? {};
|
|
205
|
+
const files = await this.list(dirpath, { depth });
|
|
206
|
+
for (const filepath of files) {
|
|
207
|
+
const isFile = await this.isFile(filepath);
|
|
208
|
+
if (!isFile)
|
|
209
|
+
continue;
|
|
210
|
+
try {
|
|
211
|
+
const content = await this.read(filepath);
|
|
212
|
+
yield {
|
|
213
|
+
filepath,
|
|
214
|
+
content,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// Skip files that can't be read
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async listRecursive(dirpath, maxDepth, currentDepth, stripBasepath) {
|
|
224
|
+
const results = [];
|
|
225
|
+
const entries = await fs__namespace.readdir(dirpath, { withFileTypes: true });
|
|
226
|
+
for (const entry of entries) {
|
|
227
|
+
const fullPath = path__namespace.join(dirpath, entry.name);
|
|
228
|
+
const strippedPath = this.stripBasepath(fullPath, stripBasepath);
|
|
229
|
+
results.push(strippedPath);
|
|
230
|
+
if (entry.isDirectory() && currentDepth < maxDepth) {
|
|
231
|
+
const subResults = await this.listRecursive(fullPath, maxDepth, currentDepth + 1, stripBasepath);
|
|
232
|
+
results.push(...subResults);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return results;
|
|
236
|
+
}
|
|
237
|
+
stripBasepath(original, pathToStrip) {
|
|
238
|
+
if (!pathToStrip)
|
|
239
|
+
return original;
|
|
240
|
+
const base = pathToStrip.replace(/^\/+/, '/').replace(/\/+$/, '/');
|
|
241
|
+
const stripped = original.replace(base, '');
|
|
242
|
+
return `/${stripped}`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
class MultiEntryFileDb {
|
|
247
|
+
constructor(dirpath, parser) {
|
|
248
|
+
this.dirpath = dirpath;
|
|
249
|
+
this.parser = parser;
|
|
250
|
+
this.files = new FilesService();
|
|
251
|
+
}
|
|
252
|
+
async create(entry) {
|
|
253
|
+
await this.writeEntry(entry);
|
|
254
|
+
return entry;
|
|
255
|
+
}
|
|
256
|
+
async getById(id) {
|
|
257
|
+
return await this.readEntry(id);
|
|
258
|
+
}
|
|
259
|
+
async getByIdOrThrow(id) {
|
|
260
|
+
const entry = await this.readEntry(id);
|
|
261
|
+
if (!entry) {
|
|
262
|
+
throw new Error('Entry with id ' + id + ' does not exist');
|
|
263
|
+
}
|
|
264
|
+
return entry;
|
|
265
|
+
}
|
|
266
|
+
async getWhere(predicate, max) {
|
|
267
|
+
const entries = await this.getAll();
|
|
268
|
+
return entries.filter(predicate).slice(0, max);
|
|
269
|
+
}
|
|
270
|
+
async getAll(whereIds) {
|
|
271
|
+
const ids = whereIds === undefined ? await this.getAllIds() : whereIds;
|
|
272
|
+
const entries = [];
|
|
273
|
+
for (const id of ids) {
|
|
274
|
+
const entry = await this.readEntry(id);
|
|
275
|
+
if (entry) {
|
|
276
|
+
entries.push(entry);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return entries;
|
|
280
|
+
}
|
|
281
|
+
async getAllIds() {
|
|
282
|
+
try {
|
|
283
|
+
const entries = await this.files.list(this.dirpath);
|
|
284
|
+
return entries.filter((name) => name.endsWith('.json')).map((name) => name.slice(0, -5)); // Remove .json extension
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Directory might not exist
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async update(id, updater) {
|
|
292
|
+
const entry = await this.readEntry(id);
|
|
293
|
+
if (!entry) {
|
|
294
|
+
throw new Error('Entry with id ' + id + ' does not exist');
|
|
295
|
+
}
|
|
296
|
+
const updatedEntryFields = await updater(entry);
|
|
297
|
+
const updatedEntry = { ...entry, ...updatedEntryFields };
|
|
298
|
+
await this.writeEntry(updatedEntry);
|
|
299
|
+
if (updatedEntry.id !== id) {
|
|
300
|
+
await this.delete(id);
|
|
301
|
+
}
|
|
302
|
+
return updatedEntry;
|
|
303
|
+
}
|
|
304
|
+
async delete(id) {
|
|
305
|
+
try {
|
|
306
|
+
const filepath = this.getFilePath(id);
|
|
307
|
+
await this.files.delete(filepath, { force: false });
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// File might not exist, ignore error
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
async deleteByIds(ids) {
|
|
316
|
+
return this.deleteWhere((entry) => ids.includes(entry.id));
|
|
317
|
+
}
|
|
318
|
+
async deleteWhere(predicate) {
|
|
319
|
+
const deletedIds = [];
|
|
320
|
+
const ignoredIds = [];
|
|
321
|
+
for await (const entry of this.iterEntries()) {
|
|
322
|
+
if (!predicate(entry))
|
|
323
|
+
continue;
|
|
324
|
+
const didDelete = await this.delete(entry.id);
|
|
325
|
+
if (didDelete) {
|
|
326
|
+
deletedIds.push(entry.id);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
ignoredIds.push(entry.id);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return { deletedIds, ignoredIds };
|
|
333
|
+
}
|
|
334
|
+
async destroy() {
|
|
335
|
+
await this.files.delete(this.dirpath);
|
|
336
|
+
}
|
|
337
|
+
async exists(id) {
|
|
338
|
+
const entry = await this.readEntry(id);
|
|
339
|
+
return entry !== null;
|
|
340
|
+
}
|
|
341
|
+
async countAll() {
|
|
342
|
+
const ids = await this.getAllIds();
|
|
343
|
+
return ids.length;
|
|
344
|
+
}
|
|
345
|
+
async countWhere(predicate) {
|
|
346
|
+
return (await this.getWhere(predicate)).length;
|
|
347
|
+
}
|
|
348
|
+
getFilePath(id) {
|
|
349
|
+
return path__namespace.join(this.dirpath, `${id}.json`);
|
|
350
|
+
}
|
|
351
|
+
async readEntry(id) {
|
|
352
|
+
try {
|
|
353
|
+
const filepath = this.getFilePath(id);
|
|
354
|
+
const text = await this.files.read(filepath);
|
|
355
|
+
const entry = this.parser.parse(text);
|
|
356
|
+
return entry;
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
// File doesn't exist or invalid JSON
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async writeEntry(entry) {
|
|
364
|
+
const filepath = this.getFilePath(entry.id);
|
|
365
|
+
await this.files.write(filepath, JSON.stringify(entry, null, 2));
|
|
366
|
+
}
|
|
367
|
+
async *iterEntries() {
|
|
368
|
+
const ids = await this.getAllIds();
|
|
369
|
+
for (const id of ids) {
|
|
370
|
+
const entry = await this.readEntry(id);
|
|
371
|
+
if (entry)
|
|
372
|
+
yield entry;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
class SingleEntryFileDb {
|
|
378
|
+
constructor(filepath, parser) {
|
|
379
|
+
this.filepath = filepath;
|
|
380
|
+
this.parser = parser;
|
|
381
|
+
this.files = new FilesService();
|
|
382
|
+
}
|
|
383
|
+
path() {
|
|
384
|
+
return this.filepath;
|
|
385
|
+
}
|
|
386
|
+
async isInited() {
|
|
387
|
+
const exists = await this.files.exists(this.filepath);
|
|
388
|
+
return exists;
|
|
389
|
+
}
|
|
390
|
+
async read() {
|
|
391
|
+
const text = await this.files.read(this.filepath);
|
|
392
|
+
const entry = this.parser.parse(text);
|
|
393
|
+
return entry;
|
|
394
|
+
}
|
|
395
|
+
async write(updaterOrEntry) {
|
|
396
|
+
let entry;
|
|
397
|
+
if (typeof updaterOrEntry === 'function') {
|
|
398
|
+
const updater = updaterOrEntry;
|
|
399
|
+
const existing = await this.read();
|
|
400
|
+
const updatedFields = await updater(existing);
|
|
401
|
+
entry = { ...existing, ...updatedFields };
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
entry = updaterOrEntry;
|
|
405
|
+
}
|
|
406
|
+
await this.files.write(this.filepath, JSON.stringify(entry, null, 2));
|
|
407
|
+
return entry;
|
|
408
|
+
}
|
|
409
|
+
async delete() {
|
|
410
|
+
await this.files.delete(this.filepath);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
exports.MultiEntryFileDb = MultiEntryFileDb;
|
|
415
|
+
exports.SingleEntryFileDb = SingleEntryFileDb;
|
|
416
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/types.ts","../../src/files.ts","../../src/multiEntryFileDb.ts","../../src/singleEntryFileDb.ts"],"sourcesContent":["export type Identifiable = {\n id: Id\n}\n\nexport type Id = string\n\nexport type Promisable<T> = T | Promise<T>\n\nexport type DeleteManyOutput = {\n deletedIds: Id[]\n ignoredIds: Id[]\n}\n\nexport type PredicateFn<T extends Identifiable> = (entry: T) => boolean\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 './types'\nimport { FileType } from './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 FilesService {\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 type { Identifiable, DeleteManyOutput, Promisable, PredicateFn } from './types'\nimport { FilesService } from './files'\nimport { JsonParser } from '@jsonkit/tools'\nimport * as path from 'path'\n\nexport class MultiEntryFileDb<T extends Identifiable> {\n protected readonly files: FilesService = new FilesService()\n\n constructor(\n protected readonly dirpath: string,\n protected readonly parser: JsonParser,\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 return await this.readEntry(id)\n }\n\n async getByIdOrThrow(id: T['id']): Promise<T> {\n const entry = await this.readEntry(id)\n if (!entry) {\n throw new Error('Entry with id ' + id + ' does not exist')\n }\n return entry\n }\n\n async getWhere(predicate: PredicateFn<T>, max?: number): Promise<T[]> {\n const entries = await this.getAll()\n return entries.filter(predicate).slice(0, max)\n }\n\n async getAll(whereIds?: T['id'][]): Promise<T[]> {\n const ids = whereIds === undefined ? await this.getAllIds() : whereIds\n const entries: T[] = []\n\n for (const id of ids) {\n const entry = await this.readEntry(id)\n if (entry) {\n entries.push(entry)\n }\n }\n\n return entries\n }\n\n async getAllIds(): Promise<T['id'][]> {\n try {\n const entries = await this.files.list(this.dirpath)\n return entries.filter((name) => name.endsWith('.json')).map((name) => name.slice(0, -5)) // Remove .json extension\n } catch {\n // Directory might not exist\n return []\n }\n }\n\n async update(id: T['id'], updater: (entry: T) => Promisable<Partial<T>>): Promise<T> {\n const entry = await this.readEntry(id)\n if (!entry) {\n throw new Error('Entry with id ' + id + ' does not exist')\n }\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.delete(id)\n }\n\n return updatedEntry\n }\n\n async delete(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 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.delete(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 destroy() {\n await this.files.delete(this.dirpath)\n }\n\n async exists(id: T['id']): Promise<boolean> {\n const entry = await this.readEntry(id)\n return entry !== null\n }\n\n async countAll(): Promise<number> {\n const ids = await this.getAllIds()\n return ids.length\n }\n\n async countWhere(predicate: PredicateFn<T>): Promise<number> {\n return (await this.getWhere(predicate)).length\n }\n\n protected getFilePath(id: T['id']) {\n return path.join(this.dirpath, `${id}.json`)\n }\n\n protected async readEntry(id: T['id']) {\n try {\n const filepath = this.getFilePath(id)\n const text = await this.files.read(filepath)\n const entry = this.parser.parse<T>(text)\n return entry\n } catch {\n // File doesn't exist or invalid JSON\n return null\n }\n }\n\n protected async writeEntry(entry: T) {\n const filepath = this.getFilePath(entry.id)\n await this.files.write(filepath, JSON.stringify(entry, null, 2))\n }\n\n protected async *iterEntries() {\n const ids = await this.getAllIds()\n for (const id of ids) {\n const entry = await this.readEntry(id)\n if (entry) yield entry\n }\n }\n}\n","import type { Identifiable, Promisable } from './types'\nimport { FilesService } from './files'\nimport { JsonParser } from '@jsonkit/tools'\n\nexport class SingleEntryFileDb<T> {\n protected readonly files: FilesService = new FilesService()\n\n constructor(\n protected readonly filepath: string,\n protected readonly parser: JsonParser,\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<T>(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"],"names":["FileType","fs","path","fsSync","readline"],"mappings":"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"}
|