inibase 1.0.0-rc.31 → 1.0.0-rc.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/file.d.ts +4 -0
- package/dist/file.js +27 -2
- package/dist/index.js +118 -140
- package/package.json +1 -1
package/dist/file.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { ComparisonOperator, FieldType } from "./index.js";
|
|
3
|
+
export declare const lock: (folderPath: string) => Promise<void>;
|
|
4
|
+
export declare const unlock: (folderPath: string) => Promise<void>;
|
|
3
5
|
export declare const write: (filePath: string, data: any, disableCompression?: boolean) => Promise<void>;
|
|
4
6
|
export declare const read: (filePath: string, disableCompression?: boolean) => Promise<string>;
|
|
5
7
|
/**
|
|
@@ -168,4 +170,6 @@ export default class File {
|
|
|
168
170
|
static count: (filePath: string) => Promise<number>;
|
|
169
171
|
static write: (filePath: string, data: any, disableCompression?: boolean) => Promise<void>;
|
|
170
172
|
static read: (filePath: string, disableCompression?: boolean) => Promise<string>;
|
|
173
|
+
static lock: (folderPath: string) => Promise<void>;
|
|
174
|
+
static unlock: (folderPath: string) => Promise<void>;
|
|
171
175
|
}
|
package/dist/file.js
CHANGED
|
@@ -1,16 +1,39 @@
|
|
|
1
|
-
import { open, access, writeFile, readFile, constants as fsConstants, } from "node:fs/promises";
|
|
1
|
+
import { open, access, writeFile, readFile, constants as fsConstants, unlink, } from "node:fs/promises";
|
|
2
2
|
import { createInterface } from "node:readline";
|
|
3
3
|
import { Transform } from "node:stream";
|
|
4
4
|
import { pipeline } from "node:stream/promises";
|
|
5
5
|
import { createGzip, createGunzip, gzip as gzipAsync, gunzip as gunzipAsync, } from "node:zlib";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
|
+
import { join } from "node:path";
|
|
7
8
|
import { detectFieldType, isArrayOfArrays, isNumber, isObject, } from "./utils.js";
|
|
8
9
|
import { encodeID, comparePassword } from "./utils.server.js";
|
|
9
10
|
import Config from "./config.js";
|
|
10
11
|
const gzip = promisify(gzipAsync);
|
|
11
12
|
const gunzip = promisify(gunzipAsync);
|
|
13
|
+
export const lock = async (folderPath) => {
|
|
14
|
+
let lockFile, lockFilePath = join(folderPath, "locked.inib");
|
|
15
|
+
try {
|
|
16
|
+
lockFile = await open(lockFilePath, "wx");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
catch ({ message }) {
|
|
20
|
+
if (message.split(":")[0] === "EEXIST")
|
|
21
|
+
return await new Promise((resolve, reject) => setTimeout(() => resolve(lock(folderPath)), 13));
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
await lockFile?.close();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export const unlock = async (folderPath) => {
|
|
28
|
+
try {
|
|
29
|
+
await unlink(join(folderPath, "locked.inib"));
|
|
30
|
+
}
|
|
31
|
+
catch { }
|
|
32
|
+
};
|
|
12
33
|
export const write = async (filePath, data, disableCompression = false) => {
|
|
13
|
-
await writeFile(filePath, Config.isCompressionEnabled && !disableCompression
|
|
34
|
+
await writeFile(filePath, Config.isCompressionEnabled && !disableCompression
|
|
35
|
+
? await gzip(String(data))
|
|
36
|
+
: String(data));
|
|
14
37
|
};
|
|
15
38
|
export const read = async (filePath, disableCompression = false) => {
|
|
16
39
|
return Config.isCompressionEnabled && !disableCompression
|
|
@@ -765,4 +788,6 @@ export default class File {
|
|
|
765
788
|
static count = count;
|
|
766
789
|
static write = write;
|
|
767
790
|
static read = read;
|
|
791
|
+
static lock = lock;
|
|
792
|
+
static unlock = unlock;
|
|
768
793
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { unlink, rename, mkdir, readdir
|
|
1
|
+
import { unlink, rename, mkdir, readdir } from "node:fs/promises";
|
|
2
2
|
import { existsSync, appendFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { cpus } from "node:os";
|
|
@@ -66,12 +66,12 @@ export default class Inibase {
|
|
|
66
66
|
// remove id from schema
|
|
67
67
|
schema = schema.filter(({ key }) => !["id", "createdAt", "updatedAt"].includes(key));
|
|
68
68
|
schema = UtilsServer.addIdToSchema(schema, UtilsServer.findLastIdNumber(schema, this.salt), this.salt);
|
|
69
|
-
const
|
|
70
|
-
if (!(await File.isExists(
|
|
71
|
-
await mkdir(
|
|
72
|
-
if (!(await File.isExists(join(
|
|
73
|
-
await mkdir(join(
|
|
74
|
-
if (await File.isExists(
|
|
69
|
+
const tablePath = join(this.folder, this.database, tableName), tableSchemaPath = join(tablePath, "schema.json");
|
|
70
|
+
if (!(await File.isExists(tablePath)))
|
|
71
|
+
await mkdir(tablePath, { recursive: true });
|
|
72
|
+
if (!(await File.isExists(join(tablePath, ".tmp"))))
|
|
73
|
+
await mkdir(join(tablePath, ".tmp"));
|
|
74
|
+
if (await File.isExists(tableSchemaPath)) {
|
|
75
75
|
// update columns files names based on field id
|
|
76
76
|
const schemaToIdsPath = (schema, prefix = "") => {
|
|
77
77
|
let RETURN = {};
|
|
@@ -88,17 +88,17 @@ export default class Inibase {
|
|
|
88
88
|
}, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath((await this.getTableSchema(tableName)) ?? []), schemaToIdsPath(schema));
|
|
89
89
|
if (replaceOldPathes)
|
|
90
90
|
await Promise.all(Object.entries(replaceOldPathes).map(async ([oldPath, newPath]) => {
|
|
91
|
-
if (await File.isExists(join(
|
|
92
|
-
await rename(join(
|
|
91
|
+
if (await File.isExists(join(tablePath, oldPath)))
|
|
92
|
+
await rename(join(tablePath, oldPath), join(tablePath, newPath));
|
|
93
93
|
}));
|
|
94
94
|
}
|
|
95
|
-
await File.write(join(
|
|
95
|
+
await File.write(join(tablePath, "schema.json"), JSON.stringify(decodeIdFromSchema(schema), null, 2), true);
|
|
96
96
|
}
|
|
97
97
|
async getTableSchema(tableName) {
|
|
98
|
-
const
|
|
99
|
-
if (!(await File.isExists(
|
|
98
|
+
const tableSchemaPath = join(this.folder, this.database, tableName, "schema.json");
|
|
99
|
+
if (!(await File.isExists(tableSchemaPath)))
|
|
100
100
|
return undefined;
|
|
101
|
-
const schemaFile = await File.read(
|
|
101
|
+
const schemaFile = await File.read(tableSchemaPath, true);
|
|
102
102
|
if (!schemaFile)
|
|
103
103
|
return undefined;
|
|
104
104
|
const schema = JSON.parse(schemaFile), lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
@@ -301,7 +301,7 @@ export default class Inibase {
|
|
|
301
301
|
]));
|
|
302
302
|
}
|
|
303
303
|
async getItemsFromSchema(tableName, schema, linesNumber, options, prefix) {
|
|
304
|
-
const
|
|
304
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
305
305
|
let RETURN = {};
|
|
306
306
|
await Promise.all(schema.map(async (field) => {
|
|
307
307
|
if ((field.type === "array" ||
|
|
@@ -392,7 +392,7 @@ export default class Inibase {
|
|
|
392
392
|
options.columns = options.columns
|
|
393
393
|
.filter((column) => column.includes(`${field.key}.`))
|
|
394
394
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
395
|
-
const items = await File.get(join(
|
|
395
|
+
const items = await File.get(join(tablePath, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field.children, this.salt);
|
|
396
396
|
if (items)
|
|
397
397
|
await Promise.all(Object.entries(items).map(async ([index, item]) => {
|
|
398
398
|
if (!RETURN[index])
|
|
@@ -402,8 +402,8 @@ export default class Inibase {
|
|
|
402
402
|
: this.getDefaultValue(field);
|
|
403
403
|
}));
|
|
404
404
|
}
|
|
405
|
-
else if (await File.isExists(join(
|
|
406
|
-
const items = await File.get(join(
|
|
405
|
+
else if (await File.isExists(join(tablePath, (prefix ?? "") + field.key + ".inib"))) {
|
|
406
|
+
const items = await File.get(join(tablePath, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field?.children, this.salt);
|
|
407
407
|
if (items)
|
|
408
408
|
for (const [index, item] of Object.entries(items)) {
|
|
409
409
|
if (!RETURN[index])
|
|
@@ -428,13 +428,13 @@ export default class Inibase {
|
|
|
428
428
|
}
|
|
429
429
|
else if (field.type === "table") {
|
|
430
430
|
if ((await File.isExists(join(this.folder, this.database, field.key))) &&
|
|
431
|
-
(await File.isExists(join(
|
|
431
|
+
(await File.isExists(join(tablePath, (prefix ?? "") + field.key + ".inib")))) {
|
|
432
432
|
if (options.columns)
|
|
433
433
|
options.columns = options.columns
|
|
434
434
|
.filter((column) => column.includes(`${field.key}.`) &&
|
|
435
435
|
!column.includes(`${field.key}.`))
|
|
436
436
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
437
|
-
const items = await File.get(join(
|
|
437
|
+
const items = await File.get(join(tablePath, (prefix ?? "") + field.key + ".inib"), linesNumber, "number", undefined, this.salt);
|
|
438
438
|
if (items)
|
|
439
439
|
for await (const [index, item] of Object.entries(items)) {
|
|
440
440
|
if (!RETURN[index])
|
|
@@ -445,8 +445,8 @@ export default class Inibase {
|
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
|
-
else if (await File.isExists(join(
|
|
449
|
-
const items = await File.get(join(
|
|
448
|
+
else if (await File.isExists(join(tablePath, (prefix ?? "") + field.key + ".inib"))) {
|
|
449
|
+
const items = await File.get(join(tablePath, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field?.children, this.salt);
|
|
450
450
|
if (items)
|
|
451
451
|
for (const [index, item] of Object.entries(items)) {
|
|
452
452
|
if (!RETURN[index])
|
|
@@ -463,6 +463,7 @@ export default class Inibase {
|
|
|
463
463
|
return RETURN;
|
|
464
464
|
}
|
|
465
465
|
async applyCriteria(tableName, schema, options, criteria, allTrue) {
|
|
466
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
466
467
|
let RETURN = {}, RETURN_LineNumbers = null;
|
|
467
468
|
if (!criteria)
|
|
468
469
|
return [null, null];
|
|
@@ -545,7 +546,7 @@ export default class Inibase {
|
|
|
545
546
|
searchOperator = "=";
|
|
546
547
|
searchComparedAtValue = value;
|
|
547
548
|
}
|
|
548
|
-
const [searchResult, totalLines, linesNumbers] = await File.search(join(
|
|
549
|
+
const [searchResult, totalLines, linesNumbers] = await File.search(join(tablePath, key + ".inib"), searchOperator ?? "=", searchComparedAtValue ?? null, searchLogicalOperator, field?.type, field?.children, options.perPage, options.page - 1 * options.perPage + 1, true, this.salt);
|
|
549
550
|
if (searchResult) {
|
|
550
551
|
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).map(([id, value]) => [
|
|
551
552
|
id,
|
|
@@ -592,6 +593,7 @@ export default class Inibase {
|
|
|
592
593
|
page: 1,
|
|
593
594
|
perPage: 15,
|
|
594
595
|
}, onlyOne, onlyLinesNumbers, tableSchema) {
|
|
596
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
595
597
|
// Ensure options.columns is an array
|
|
596
598
|
if (options.columns) {
|
|
597
599
|
options.columns = Array.isArray(options.columns)
|
|
@@ -607,8 +609,7 @@ export default class Inibase {
|
|
|
607
609
|
let schema = tableSchema ?? (await this.getTableSchema(tableName));
|
|
608
610
|
if (!schema)
|
|
609
611
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
610
|
-
|
|
611
|
-
if (!(await File.isExists(idFilePath)))
|
|
612
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
612
613
|
return null;
|
|
613
614
|
if (options.columns && options.columns.length)
|
|
614
615
|
schema = this._filterSchemaByColumns(schema, options.columns);
|
|
@@ -618,12 +619,15 @@ export default class Inibase {
|
|
|
618
619
|
index +
|
|
619
620
|
1), options));
|
|
620
621
|
if (Config.isCacheEnabled &&
|
|
621
|
-
(await File.isExists(join(
|
|
622
|
-
this.totalItems[tableName + "-*"] = Number(await File.read(join(
|
|
622
|
+
(await File.isExists(join(tablePath, ".tmp", "pagination.inib"))))
|
|
623
|
+
this.totalItems[tableName + "-*"] = Number((await File.read(join(tablePath, ".tmp", "pagination.inib"), true)).split(",")[1]);
|
|
623
624
|
else {
|
|
624
|
-
|
|
625
|
+
let [lastId, totalItems] = await File.get(join(tablePath, "id.inib"), -1, "number", undefined, this.salt, true);
|
|
626
|
+
if (lastId)
|
|
627
|
+
lastId = Number(Object.keys(lastId)[0] ?? 0);
|
|
628
|
+
this.totalItems[tableName + "-*"] = totalItems;
|
|
625
629
|
if (Config.isCacheEnabled)
|
|
626
|
-
await File.write(join(
|
|
630
|
+
await File.write(join(tablePath, ".tmp", "pagination.inib"), `${lastId},${totalItems}`, true);
|
|
627
631
|
}
|
|
628
632
|
}
|
|
629
633
|
else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
@@ -644,7 +648,7 @@ export default class Inibase {
|
|
|
644
648
|
let Ids = where;
|
|
645
649
|
if (!Array.isArray(Ids))
|
|
646
650
|
Ids = [Ids];
|
|
647
|
-
const [lineNumbers, countItems] = await File.search(
|
|
651
|
+
const [lineNumbers, countItems] = await File.search(join(tablePath, "id.inib"), "[]", Ids.map((id) => Utils.isNumber(id) ? Number(id) : UtilsServer.decodeID(id, this.salt)), undefined, "number", undefined, Ids.length, 0, !this.totalItems[tableName + "-*"], this.salt);
|
|
648
652
|
if (!lineNumbers)
|
|
649
653
|
throw this.throwError("INVALID_ID", where);
|
|
650
654
|
if (onlyLinesNumbers)
|
|
@@ -652,16 +656,8 @@ export default class Inibase {
|
|
|
652
656
|
? Object.keys(lineNumbers).map(Number)
|
|
653
657
|
: null;
|
|
654
658
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
|
|
655
|
-
if (!this.totalItems[tableName + "-*"])
|
|
656
|
-
|
|
657
|
-
(await File.isExists(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"))))
|
|
658
|
-
this.totalItems[tableName + "-*"] = Number(await File.read(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), true));
|
|
659
|
-
else {
|
|
660
|
-
this.totalItems[tableName + "-*"] = await File.count(idFilePath);
|
|
661
|
-
if (Config.isCacheEnabled)
|
|
662
|
-
await File.write(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), String(this.totalItems[tableName + "-*"]), true);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
659
|
+
if (!this.totalItems[tableName + "-*"])
|
|
660
|
+
this.totalItems[tableName + "-*"] = countItems;
|
|
665
661
|
if (RETURN && RETURN.length && !Array.isArray(where))
|
|
666
662
|
RETURN = RETURN[0];
|
|
667
663
|
}
|
|
@@ -669,7 +665,7 @@ export default class Inibase {
|
|
|
669
665
|
let cachedFilePath = "";
|
|
670
666
|
// Criteria
|
|
671
667
|
if (Config.isCacheEnabled)
|
|
672
|
-
cachedFilePath = join(
|
|
668
|
+
cachedFilePath = join(tablePath, ".tmp", `${UtilsServer.hashObject(where)}.inib`);
|
|
673
669
|
if (Config.isCacheEnabled && (await File.isExists(cachedFilePath))) {
|
|
674
670
|
const cachedItems = (await File.read(cachedFilePath, true)).split(",");
|
|
675
671
|
this.totalItems[tableName + "-*"] = cachedItems.length;
|
|
@@ -714,38 +710,26 @@ export default class Inibase {
|
|
|
714
710
|
page: 1,
|
|
715
711
|
perPage: 15,
|
|
716
712
|
};
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
try {
|
|
720
|
-
testFileHandle = await open(join(cashFolderPath, "id.inib"), "wx");
|
|
721
|
-
renameList = [[join(cashFolderPath, "id.inib"), ""]];
|
|
722
|
-
}
|
|
723
|
-
catch ({ message }) {
|
|
724
|
-
if (message.split(":")[0] === "EEXIST")
|
|
725
|
-
return await new Promise((resolve, reject) => setTimeout(() => resolve(this.post(tableName, data, options, returnPostedData)), 13));
|
|
726
|
-
}
|
|
727
|
-
finally {
|
|
728
|
-
await testFileHandle?.close();
|
|
729
|
-
}
|
|
713
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
714
|
+
await File.lock(join(tablePath, ".tmp"));
|
|
730
715
|
if (!returnPostedData)
|
|
731
716
|
returnPostedData = false;
|
|
732
717
|
const schema = await this.getTableSchema(tableName);
|
|
733
718
|
let RETURN;
|
|
734
719
|
if (!schema)
|
|
735
720
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
736
|
-
let lastId = 0, totalItems = 0,
|
|
737
|
-
if (await File.isExists(
|
|
738
|
-
if (
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
totalItems = await File.count(join(this.folder, this.database, tableName, "id.inib"));
|
|
744
|
-
}
|
|
721
|
+
let lastId = 0, totalItems = 0, renameList = [];
|
|
722
|
+
if (await File.isExists(join(tablePath, "id.inib"))) {
|
|
723
|
+
if (Config.isCacheEnabled &&
|
|
724
|
+
(await File.isExists(join(tablePath, ".tmp", "pagination.inib"))))
|
|
725
|
+
[lastId, totalItems] = (await File.read(join(tablePath, ".tmp", "pagination.inib"), true))
|
|
726
|
+
.split(",")
|
|
727
|
+
.map(Number);
|
|
745
728
|
else {
|
|
746
|
-
|
|
729
|
+
let lastIdObj;
|
|
730
|
+
[lastIdObj, totalItems] = await File.get(join(tablePath, "id.inib"), -1, "number", undefined, this.salt, true);
|
|
747
731
|
if (lastIdObj)
|
|
748
|
-
lastId = Number(Object.
|
|
732
|
+
lastId = Number(Object.keys(lastIdObj)[0] ?? 0);
|
|
749
733
|
}
|
|
750
734
|
}
|
|
751
735
|
if (Utils.isArrayOfObjects(data))
|
|
@@ -764,12 +748,12 @@ export default class Inibase {
|
|
|
764
748
|
throw this.throwError("NO_DATA");
|
|
765
749
|
try {
|
|
766
750
|
RETURN = this.formatData(RETURN, schema);
|
|
767
|
-
const pathesContents = this.joinPathesContents(join(
|
|
768
|
-
|
|
751
|
+
const pathesContents = this.joinPathesContents(join(tablePath), Array.isArray(RETURN) ? RETURN.toReversed() : RETURN);
|
|
752
|
+
await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(await File.append(path, content))));
|
|
769
753
|
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
770
754
|
renameList = [];
|
|
771
|
-
|
|
772
|
-
|
|
755
|
+
if (Config.isCacheEnabled)
|
|
756
|
+
await File.write(join(tablePath, ".tmp", "pagination.inib"), `${lastId},${totalItems + (Array.isArray(RETURN) ? RETURN.length : 1)}`, true);
|
|
773
757
|
if (returnPostedData)
|
|
774
758
|
return this.get(tableName, Utils.isArrayOfObjects(RETURN)
|
|
775
759
|
? RETURN.map((data) => Number(data.id))
|
|
@@ -777,6 +761,7 @@ export default class Inibase {
|
|
|
777
761
|
undefined, schema);
|
|
778
762
|
}
|
|
779
763
|
finally {
|
|
764
|
+
await File.unlock(join(tablePath, ".tmp"));
|
|
780
765
|
if (renameList.length)
|
|
781
766
|
await Promise.all(renameList.map(async ([tempPath, _]) => (await File.isExists(tempPath)) ? unlink(tempPath) : undefined));
|
|
782
767
|
}
|
|
@@ -785,13 +770,15 @@ export default class Inibase {
|
|
|
785
770
|
page: 1,
|
|
786
771
|
perPage: 15,
|
|
787
772
|
}, returnPostedData) {
|
|
773
|
+
let renameList = [];
|
|
774
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
788
775
|
const schema = await this.getTableSchema(tableName);
|
|
789
776
|
if (!schema)
|
|
790
777
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
791
|
-
|
|
792
|
-
if (!(await File.isExists(idFilePath)))
|
|
778
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
793
779
|
throw this.throwError("NO_ITEMS", tableName);
|
|
794
780
|
data = this.formatData(data, schema, true);
|
|
781
|
+
await File.lock(join(tablePath, ".tmp"));
|
|
795
782
|
if (!where) {
|
|
796
783
|
if (Utils.isArrayOfObjects(data)) {
|
|
797
784
|
if (!data.every((item) => item.hasOwnProperty("id") && Utils.isValidID(item.id)))
|
|
@@ -806,7 +793,7 @@ export default class Inibase {
|
|
|
806
793
|
return this.put(tableName, data, UtilsServer.decodeID(data.id, this.salt));
|
|
807
794
|
}
|
|
808
795
|
else {
|
|
809
|
-
const pathesContents = this.joinPathesContents(join(
|
|
796
|
+
const pathesContents = this.joinPathesContents(join(tablePath), Utils.isArrayOfObjects(data)
|
|
810
797
|
? data.map((item) => ({
|
|
811
798
|
...(({ id, ...restOfData }) => restOfData)(item),
|
|
812
799
|
updatedAt: Date.now(),
|
|
@@ -815,26 +802,21 @@ export default class Inibase {
|
|
|
815
802
|
...(({ id, ...restOfData }) => restOfData)(data),
|
|
816
803
|
updatedAt: Date.now(),
|
|
817
804
|
});
|
|
818
|
-
let testFileHandle;
|
|
819
805
|
try {
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
806
|
+
await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(await File.replace(path, content))));
|
|
807
|
+
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
808
|
+
if (Config.isCacheEnabled)
|
|
809
|
+
await Promise.all((await readdir(join(tablePath, ".tmp")))
|
|
810
|
+
?.filter((fileName) => !["pagination.inib", "locked.inib"].includes(fileName))
|
|
811
|
+
.map(async (file) => unlink(join(tablePath, ".tmp", file))));
|
|
812
|
+
if (returnPostedData)
|
|
813
|
+
return this.get(tableName, where, options, undefined, undefined, schema);
|
|
825
814
|
}
|
|
826
815
|
finally {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
831
|
-
if (Config.isCacheEnabled) {
|
|
832
|
-
const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
|
|
833
|
-
if (cacheFiles.length)
|
|
834
|
-
await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
|
|
816
|
+
if (renameList.length)
|
|
817
|
+
await Promise.all(renameList.map(async ([tempPath, _]) => (await File.isExists(tempPath)) ? unlink(tempPath) : undefined));
|
|
818
|
+
await File.unlock(join(tablePath, ".tmp"));
|
|
835
819
|
}
|
|
836
|
-
if (returnPostedData)
|
|
837
|
-
return this.get(tableName, where, options, undefined, undefined, schema);
|
|
838
820
|
}
|
|
839
821
|
}
|
|
840
822
|
else if ((Array.isArray(where) &&
|
|
@@ -849,7 +831,7 @@ export default class Inibase {
|
|
|
849
831
|
else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
850
832
|
Utils.isNumber(where)) {
|
|
851
833
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
852
|
-
const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(join(
|
|
834
|
+
const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(join(tablePath), Utils.isArrayOfObjects(data)
|
|
853
835
|
? data.map((item) => ({
|
|
854
836
|
...item,
|
|
855
837
|
updatedAt: Date.now(),
|
|
@@ -861,26 +843,22 @@ export default class Inibase {
|
|
|
861
843
|
[lineNum]: Array.isArray(content) ? content[index] : content,
|
|
862
844
|
}), {}),
|
|
863
845
|
]));
|
|
864
|
-
let testFileHandle;
|
|
865
846
|
try {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
if (
|
|
870
|
-
|
|
847
|
+
await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(await File.replace(path, content))));
|
|
848
|
+
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
849
|
+
renameList = [];
|
|
850
|
+
if (Config.isCacheEnabled)
|
|
851
|
+
await Promise.all((await readdir(join(tablePath, ".tmp")))
|
|
852
|
+
?.filter((fileName) => !["pagination.inib", "locked.inib"].includes(fileName))
|
|
853
|
+
.map(async (file) => unlink(join(tablePath, ".tmp", file))));
|
|
854
|
+
if (returnPostedData)
|
|
855
|
+
return this.get(tableName, where, options, !Array.isArray(where), undefined, schema);
|
|
871
856
|
}
|
|
872
857
|
finally {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
877
|
-
if (Config.isCacheEnabled) {
|
|
878
|
-
const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
|
|
879
|
-
if (cacheFiles.length)
|
|
880
|
-
await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
|
|
858
|
+
if (renameList.length)
|
|
859
|
+
await Promise.all(renameList.map(async ([tempPath, _]) => (await File.isExists(tempPath)) ? unlink(tempPath) : undefined));
|
|
860
|
+
await File.unlock(join(tablePath, ".tmp"));
|
|
881
861
|
}
|
|
882
|
-
if (returnPostedData)
|
|
883
|
-
return this.get(tableName, where, options, !Array.isArray(where), undefined, schema);
|
|
884
862
|
}
|
|
885
863
|
}
|
|
886
864
|
else if (Utils.isObject(where)) {
|
|
@@ -893,21 +871,22 @@ export default class Inibase {
|
|
|
893
871
|
throw this.throwError("INVALID_PARAMETERS", tableName);
|
|
894
872
|
}
|
|
895
873
|
async delete(tableName, where, _id) {
|
|
874
|
+
let renameList = [];
|
|
875
|
+
const tablePath = join(this.folder, this.database, tableName);
|
|
876
|
+
await File.lock(join(tablePath, ".tmp"));
|
|
896
877
|
const schema = await this.getTableSchema(tableName);
|
|
897
878
|
if (!schema)
|
|
898
879
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
899
|
-
|
|
900
|
-
if (!(await File.isExists(idFilePath)))
|
|
880
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
901
881
|
throw this.throwError("NO_ITEMS", tableName);
|
|
902
882
|
if (!where) {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
if (Config.isCacheEnabled)
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}
|
|
883
|
+
await Promise.all((await readdir(join(tablePath)))
|
|
884
|
+
?.filter((fileName) => fileName.endsWith(".inib"))
|
|
885
|
+
.map(async (file) => unlink(join(tablePath, file))));
|
|
886
|
+
if (Config.isCacheEnabled)
|
|
887
|
+
await Promise.all((await readdir(join(tablePath, ".tmp")))
|
|
888
|
+
?.filter((fileName) => !["pagination.inib", "locked.inib"].includes(fileName))
|
|
889
|
+
.map(async (file) => unlink(join(tablePath, ".tmp", file))));
|
|
911
890
|
return "*";
|
|
912
891
|
}
|
|
913
892
|
else if ((Array.isArray(where) &&
|
|
@@ -924,34 +903,33 @@ export default class Inibase {
|
|
|
924
903
|
else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
925
904
|
Utils.isNumber(where)) {
|
|
926
905
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
927
|
-
const files = (await readdir(join(
|
|
906
|
+
const files = (await readdir(join(tablePath)))?.filter((fileName) => fileName.endsWith(".inib"));
|
|
928
907
|
if (files.length) {
|
|
929
908
|
if (!_id)
|
|
930
|
-
_id = Object.entries((await File.get(join(
|
|
909
|
+
_id = Object.entries((await File.get(join(tablePath, "id.inib"), where, "number", undefined, this.salt)) ?? {}).map(([_key, id]) => UtilsServer.encodeID(Number(id), this.salt));
|
|
931
910
|
if (!_id.length)
|
|
932
911
|
throw this.throwError("NO_ITEMS", tableName);
|
|
933
|
-
let testFileHandle;
|
|
934
912
|
try {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
913
|
+
await Promise.all(files.map(async (file) => renameList.push(await File.remove(join(tablePath, file), where))));
|
|
914
|
+
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
915
|
+
if (Config.isCacheEnabled) {
|
|
916
|
+
await Promise.all((await readdir(join(tablePath, ".tmp")))
|
|
917
|
+
?.filter((fileName) => !["pagination.inib", "locked.inib"].includes(fileName))
|
|
918
|
+
.map(async (file) => unlink(join(tablePath, ".tmp", file))));
|
|
919
|
+
if (await File.isExists(join(tablePath, ".tmp", "pagination.inib"))) {
|
|
920
|
+
let [lastId, totalItems] = (await File.read(join(tablePath, ".tmp", "pagination.inib"), true))
|
|
921
|
+
.split(",")
|
|
922
|
+
.map(Number);
|
|
923
|
+
await File.write(join(tablePath, ".tmp", "pagination.inib"), `${lastId},${totalItems - (Array.isArray(where) ? where.length : 1)}`, true);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|
|
940
927
|
}
|
|
941
928
|
finally {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
946
|
-
if (Config.isCacheEnabled) {
|
|
947
|
-
const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
|
|
948
|
-
if (cacheFiles.length)
|
|
949
|
-
await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
|
|
950
|
-
await File.write(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), String(((await File.isExists(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib")))
|
|
951
|
-
? Number(await File.read(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), true))
|
|
952
|
-
: await File.count(join(this.folder, this.database, tableName, "id.inib"))) - (Array.isArray(where) ? where.length : 1)), true);
|
|
929
|
+
if (renameList.length)
|
|
930
|
+
await Promise.all(renameList.map(async ([tempPath, _]) => (await File.isExists(tempPath)) ? unlink(tempPath) : undefined));
|
|
931
|
+
await File.unlock(join(tablePath, ".tmp"));
|
|
953
932
|
}
|
|
954
|
-
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|
|
955
933
|
}
|
|
956
934
|
}
|
|
957
935
|
}
|
|
@@ -967,10 +945,10 @@ export default class Inibase {
|
|
|
967
945
|
}
|
|
968
946
|
async sum(tableName, columns, where) {
|
|
969
947
|
let RETURN = {};
|
|
970
|
-
const schema = await this.getTableSchema(tableName);
|
|
948
|
+
const tablePath = join(this.folder, this.database, tableName), schema = await this.getTableSchema(tableName);
|
|
971
949
|
if (!schema)
|
|
972
950
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
973
|
-
if (!(await File.isExists(join(
|
|
951
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
974
952
|
throw this.throwError("NO_ITEMS", tableName);
|
|
975
953
|
if (!Array.isArray(columns))
|
|
976
954
|
columns = [columns];
|
|
@@ -991,10 +969,10 @@ export default class Inibase {
|
|
|
991
969
|
}
|
|
992
970
|
async max(tableName, columns, where) {
|
|
993
971
|
let RETURN = {};
|
|
994
|
-
const schema = await this.getTableSchema(tableName);
|
|
972
|
+
const tablePath = join(this.folder, this.database, tableName), schema = await this.getTableSchema(tableName);
|
|
995
973
|
if (!schema)
|
|
996
974
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
997
|
-
if (!(await File.isExists(join(
|
|
975
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
998
976
|
throw this.throwError("NO_ITEMS", tableName);
|
|
999
977
|
if (!Array.isArray(columns))
|
|
1000
978
|
columns = [columns];
|
|
@@ -1015,10 +993,10 @@ export default class Inibase {
|
|
|
1015
993
|
}
|
|
1016
994
|
async min(tableName, columns, where) {
|
|
1017
995
|
let RETURN = {};
|
|
1018
|
-
const schema = await this.getTableSchema(tableName);
|
|
996
|
+
const tablePath = join(this.folder, this.database, tableName), schema = await this.getTableSchema(tableName);
|
|
1019
997
|
if (!schema)
|
|
1020
998
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
1021
|
-
if (!(await File.isExists(join(
|
|
999
|
+
if (!(await File.isExists(join(tablePath, "id.inib"))))
|
|
1022
1000
|
throw this.throwError("NO_ITEMS", tableName);
|
|
1023
1001
|
if (!Array.isArray(columns))
|
|
1024
1002
|
columns = [columns];
|