inibase 1.0.0-rc.50 → 1.0.0-rc.51
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/config.d.ts +3 -5
- package/dist/config.js +3 -5
- package/dist/file.d.ts +1 -32
- package/dist/file.js +65 -79
- package/dist/file.thread.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +149 -157
- package/dist/utils.d.ts +0 -25
- package/dist/utils.js +23 -51
- package/dist/utils.server.d.ts +1 -16
- package/dist/utils.server.js +4 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import { existsSync, appendFileSync } from "node:fs";
|
|
|
3
3
|
import { join, parse } from "node:path";
|
|
4
4
|
import { scryptSync, randomBytes } from "node:crypto";
|
|
5
5
|
import { Worker } from "node:worker_threads";
|
|
6
|
-
import File from "./file.js";
|
|
7
|
-
import Utils from "./utils.js";
|
|
8
|
-
import UtilsServer from "./utils.server.js";
|
|
9
|
-
import Config from "./config.js";
|
|
6
|
+
import * as File from "./file.js";
|
|
7
|
+
import * as Utils from "./utils.js";
|
|
8
|
+
import * as UtilsServer from "./utils.server.js";
|
|
9
|
+
import * as Config from "./config.js";
|
|
10
10
|
import { inspect } from "node:util";
|
|
11
11
|
import Inison from "inison";
|
|
12
12
|
export default class Inibase {
|
|
@@ -47,14 +47,14 @@ export default class Inibase {
|
|
|
47
47
|
},
|
|
48
48
|
// Add more languages and error messages as needed
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
const errorMessage = errorMessages[language][code];
|
|
51
51
|
if (!errorMessage)
|
|
52
52
|
return new Error("ERR");
|
|
53
53
|
return new Error(variable
|
|
54
54
|
? Array.isArray(variable)
|
|
55
55
|
? errorMessage.replace(/\{variable\}/g, () => variable.shift()?.toString() ?? "")
|
|
56
|
-
: errorMessage.replaceAll(
|
|
57
|
-
: errorMessage.replaceAll(
|
|
56
|
+
: errorMessage.replaceAll("{variable}", `'${variable.toString()}'`)
|
|
57
|
+
: errorMessage.replaceAll("{variable}", ""));
|
|
58
58
|
}
|
|
59
59
|
async createWorker(functionName, arg) {
|
|
60
60
|
return new Promise((resolve, reject) => {
|
|
@@ -77,15 +77,15 @@ export default class Inibase {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
_schemaToIdsPath = (schema, prefix = "") => {
|
|
80
|
-
|
|
80
|
+
const RETURN = {};
|
|
81
81
|
for (const field of schema)
|
|
82
82
|
if ((field.type === "array" || field.type === "object") &&
|
|
83
83
|
field.children &&
|
|
84
84
|
Utils.isArrayOfObjects(field.children)) {
|
|
85
|
-
Utils.deepMerge(RETURN, this._schemaToIdsPath(field.children, (prefix ?? "") + field.key
|
|
85
|
+
Utils.deepMerge(RETURN, this._schemaToIdsPath(field.children, `${(prefix ?? "") + field.key}.`));
|
|
86
86
|
}
|
|
87
87
|
else if (field.id)
|
|
88
|
-
RETURN[field.id] = (prefix ?? "") + field.key
|
|
88
|
+
RETURN[field.id] = `${(prefix ?? "") + field.key}.inib`;
|
|
89
89
|
return RETURN;
|
|
90
90
|
};
|
|
91
91
|
async setTableSchema(tableName, schema) {
|
|
@@ -101,10 +101,10 @@ export default class Inibase {
|
|
|
101
101
|
if (await File.isExists(tableSchemaPath)) {
|
|
102
102
|
// update columns files names based on field id
|
|
103
103
|
const currentSchema = await this.getTableSchema(tableName, false);
|
|
104
|
-
schema = UtilsServer.addIdToSchema(schema, currentSchema
|
|
104
|
+
schema = UtilsServer.addIdToSchema(schema, currentSchema?.length
|
|
105
105
|
? UtilsServer.findLastIdNumber(currentSchema, this.salt)
|
|
106
|
-
:
|
|
107
|
-
if (currentSchema
|
|
106
|
+
: 0, this.salt, false);
|
|
107
|
+
if (currentSchema?.length) {
|
|
108
108
|
const replaceOldPathes = Utils.findChangedProperties(this._schemaToIdsPath(currentSchema), this._schemaToIdsPath(schema));
|
|
109
109
|
if (replaceOldPathes)
|
|
110
110
|
await Promise.all(Object.entries(replaceOldPathes).map(async ([oldPath, newPath]) => {
|
|
@@ -114,7 +114,7 @@ export default class Inibase {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
else
|
|
117
|
-
schema = UtilsServer.addIdToSchema(schema,
|
|
117
|
+
schema = UtilsServer.addIdToSchema(schema, 0, this.salt, false);
|
|
118
118
|
await File.write(join(tablePath, "schema.json"), JSON.stringify(schema, null, 2), true);
|
|
119
119
|
}
|
|
120
120
|
async getTableSchema(tableName, encodeIDs = true) {
|
|
@@ -127,28 +127,27 @@ export default class Inibase {
|
|
|
127
127
|
const schema = JSON.parse(schemaFile), lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
128
128
|
if (!encodeIDs)
|
|
129
129
|
return schema;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
];
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
id: UtilsServer.encodeID(0, this.salt),
|
|
133
|
+
key: "id",
|
|
134
|
+
type: "id",
|
|
135
|
+
required: true,
|
|
136
|
+
},
|
|
137
|
+
...UtilsServer.encodeSchemaID(schema, this.salt),
|
|
138
|
+
{
|
|
139
|
+
id: UtilsServer.encodeID(lastIdNumber + 1, this.salt),
|
|
140
|
+
key: "createdAt",
|
|
141
|
+
type: "date",
|
|
142
|
+
required: true,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: UtilsServer.encodeID(lastIdNumber + 2, this.salt),
|
|
146
|
+
key: "updatedAt",
|
|
147
|
+
type: "date",
|
|
148
|
+
required: false,
|
|
149
|
+
},
|
|
150
|
+
];
|
|
152
151
|
}
|
|
153
152
|
async getSchemaWhenTableNotEmpty(tableName, schema) {
|
|
154
153
|
const tablePath = join(this.folder, this.database, tableName);
|
|
@@ -171,8 +170,7 @@ export default class Inibase {
|
|
|
171
170
|
data[field.key] === undefined) {
|
|
172
171
|
if (field.required && !skipRequiredField)
|
|
173
172
|
throw this.throwError("FIELD_REQUIRED", field.key);
|
|
174
|
-
|
|
175
|
-
return;
|
|
173
|
+
return;
|
|
176
174
|
}
|
|
177
175
|
if (Object.hasOwn(data, field.key) &&
|
|
178
176
|
!Utils.validateFieldType(data[field.key], field.type, (field.type === "array" || field.type === "object") &&
|
|
@@ -285,7 +283,7 @@ export default class Inibase {
|
|
|
285
283
|
const field = Utils.getField(key, schema);
|
|
286
284
|
if (!field)
|
|
287
285
|
continue;
|
|
288
|
-
const [searchResult, totalLines] = await File.search(join(tablePath, key
|
|
286
|
+
const [searchResult, totalLines] = await File.search(join(tablePath, `${key}.inib`), Array.isArray(values) ? "=" : "[]", values, undefined, field.type, field.children, 1, undefined, false, this.salt);
|
|
289
287
|
if (searchResult && totalLines > 0)
|
|
290
288
|
throw this.throwError("FIELD_UNIQUE", [
|
|
291
289
|
field.key,
|
|
@@ -297,8 +295,8 @@ export default class Inibase {
|
|
|
297
295
|
formatData(data, schema, formatOnlyAvailiableKeys) {
|
|
298
296
|
if (Utils.isArrayOfObjects(data))
|
|
299
297
|
return data.map((single_data) => this.formatData(single_data, schema, formatOnlyAvailiableKeys));
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
if (Utils.isObject(data)) {
|
|
299
|
+
const RETURN = {};
|
|
302
300
|
for (const field of schema) {
|
|
303
301
|
if (!Object.hasOwn(data, field.key)) {
|
|
304
302
|
if (formatOnlyAvailiableKeys || !field.required)
|
|
@@ -310,8 +308,7 @@ export default class Inibase {
|
|
|
310
308
|
}
|
|
311
309
|
return RETURN;
|
|
312
310
|
}
|
|
313
|
-
|
|
314
|
-
return [];
|
|
311
|
+
return [];
|
|
315
312
|
}
|
|
316
313
|
getDefaultValue(field) {
|
|
317
314
|
if (Array.isArray(field.type))
|
|
@@ -361,11 +358,11 @@ export default class Inibase {
|
|
|
361
358
|
if (Utils.isObject(value))
|
|
362
359
|
Object.assign(RETURN, this._CombineData(value, `${key}.`));
|
|
363
360
|
else if (Utils.isArrayOfObjects(value)) {
|
|
364
|
-
Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value), (prefix ?? "") + key
|
|
361
|
+
Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value), `${(prefix ?? "") + key}.`));
|
|
365
362
|
}
|
|
366
363
|
else if (Utils.isArrayOfArrays(value) &&
|
|
367
364
|
value.every(Utils.isArrayOfObjects))
|
|
368
|
-
Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value.map(this._combineObjectsToArray)), (prefix ?? "") + key
|
|
365
|
+
Object.assign(RETURN, this._CombineData(this._combineObjectsToArray(value.map(this._combineObjectsToArray)), `${(prefix ?? "") + key}.`));
|
|
369
366
|
else
|
|
370
367
|
RETURN[(prefix ?? "") + key] = File.encode(value);
|
|
371
368
|
}
|
|
@@ -374,7 +371,7 @@ export default class Inibase {
|
|
|
374
371
|
_addPathToKeys = (obj, path) => {
|
|
375
372
|
const newObject = {};
|
|
376
373
|
for (const key in obj)
|
|
377
|
-
newObject[join(path, key
|
|
374
|
+
newObject[join(path, `${key}.inib`)] = obj[key];
|
|
378
375
|
return newObject;
|
|
379
376
|
};
|
|
380
377
|
joinPathesContents(mainPath, data) {
|
|
@@ -386,9 +383,10 @@ export default class Inibase {
|
|
|
386
383
|
RETURN[index] = {};
|
|
387
384
|
if (!RETURN[index][field.key])
|
|
388
385
|
RETURN[index][field.key] = [];
|
|
389
|
-
for (const child_field of field.children.filter((children) => children.type === "array" &&
|
|
386
|
+
for (const child_field of field.children.filter((children) => children.type === "array" &&
|
|
387
|
+
Utils.isArrayOfObjects(children.children))) {
|
|
390
388
|
if (Utils.isObject(item[child_field.key])) {
|
|
391
|
-
Object.entries(item[child_field.key])
|
|
389
|
+
for (const [key, value] of Object.entries(item[child_field.key])) {
|
|
392
390
|
for (let _i = 0; _i < value.length; _i++) {
|
|
393
391
|
if ((Array.isArray(value[_i]) && Utils.isArrayOfNulls(value[_i])) ||
|
|
394
392
|
value[_i] === null)
|
|
@@ -415,7 +413,7 @@ export default class Inibase {
|
|
|
415
413
|
});
|
|
416
414
|
}
|
|
417
415
|
}
|
|
418
|
-
}
|
|
416
|
+
}
|
|
419
417
|
}
|
|
420
418
|
}
|
|
421
419
|
}
|
|
@@ -431,14 +429,14 @@ export default class Inibase {
|
|
|
431
429
|
if (field.children.filter((children) => children.type === "array" &&
|
|
432
430
|
Utils.isArrayOfObjects(children.children)).length) {
|
|
433
431
|
// one of children has array field type and has children array of object = Schema
|
|
434
|
-
Object.entries((await this.getItemsFromSchema(tableName, field.children.filter((children) => children.type === "array" &&
|
|
435
|
-
Utils.isArrayOfObjects(children.children)), linesNumber, options, (prefix ?? "") + field.key
|
|
432
|
+
for (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children.filter((children) => children.type === "array" &&
|
|
433
|
+
Utils.isArrayOfObjects(children.children)), linesNumber, options, `${(prefix ?? "") + field.key}.`)) ?? {})) {
|
|
436
434
|
this._getItemsFromSchemaHelper(RETURN, item, index, field);
|
|
437
|
-
}
|
|
435
|
+
}
|
|
438
436
|
field.children = field.children.filter((children) => children.type !== "array" ||
|
|
439
437
|
!Utils.isArrayOfObjects(children.children));
|
|
440
438
|
}
|
|
441
|
-
Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, (prefix ?? "") + field.key
|
|
439
|
+
for (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, `${(prefix ?? "") + field.key}.`)) ?? {})) {
|
|
442
440
|
if (!RETURN[index])
|
|
443
441
|
RETURN[index] = {};
|
|
444
442
|
if (Utils.isObject(item)) {
|
|
@@ -483,19 +481,19 @@ export default class Inibase {
|
|
|
483
481
|
}
|
|
484
482
|
else
|
|
485
483
|
RETURN[index][field.key] = item;
|
|
486
|
-
}
|
|
484
|
+
}
|
|
487
485
|
}
|
|
488
486
|
else if (field.children === "table" ||
|
|
489
487
|
(Array.isArray(field.type) && field.type.includes("table")) ||
|
|
490
488
|
(Array.isArray(field.children) && field.children.includes("table"))) {
|
|
491
489
|
if (field.table &&
|
|
492
490
|
(await File.isExists(join(this.folder, this.database, field.table))) &&
|
|
493
|
-
(await File.isExists(join(tablePath, (prefix ?? "") + field.key
|
|
491
|
+
(await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}.inib`)))) {
|
|
494
492
|
if (options.columns)
|
|
495
493
|
options.columns = options.columns
|
|
496
494
|
.filter((column) => column.includes(`${field.key}.`))
|
|
497
495
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
498
|
-
const items = await File.get(join(tablePath, (prefix ?? "") + field.key
|
|
496
|
+
const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}.inib`), linesNumber, field.type, field.children, this.salt);
|
|
499
497
|
if (items)
|
|
500
498
|
await Promise.allSettled(Object.entries(items).map(async ([index, item]) => {
|
|
501
499
|
if (!RETURN[index])
|
|
@@ -506,8 +504,8 @@ export default class Inibase {
|
|
|
506
504
|
}));
|
|
507
505
|
}
|
|
508
506
|
}
|
|
509
|
-
else if (await File.isExists(join(tablePath, (prefix ?? "") + field.key
|
|
510
|
-
const items = await File.get(join(tablePath, (prefix ?? "") + field.key
|
|
507
|
+
else if (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}.inib`))) {
|
|
508
|
+
const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}.inib`), linesNumber, field.type, field.children, this.salt);
|
|
511
509
|
if (items)
|
|
512
510
|
for (const [index, item] of Object.entries(items)) {
|
|
513
511
|
if (!RETURN[index])
|
|
@@ -517,7 +515,7 @@ export default class Inibase {
|
|
|
517
515
|
}
|
|
518
516
|
}
|
|
519
517
|
else if (field.type === "object") {
|
|
520
|
-
for await (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, (prefix ?? "") + field.key
|
|
518
|
+
for await (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, `${(prefix ?? "") + field.key}.`)) ?? {})) {
|
|
521
519
|
if (!RETURN[index])
|
|
522
520
|
RETURN[index] = {};
|
|
523
521
|
if (Utils.isObject(item)) {
|
|
@@ -532,12 +530,12 @@ export default class Inibase {
|
|
|
532
530
|
}
|
|
533
531
|
else if (field.type === "table") {
|
|
534
532
|
if ((await File.isExists(join(this.folder, this.database, field.key))) &&
|
|
535
|
-
(await File.isExists(join(tablePath, (prefix ?? "") + field.key
|
|
533
|
+
(await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}.inib`)))) {
|
|
536
534
|
if (options.columns)
|
|
537
535
|
options.columns = options.columns
|
|
538
536
|
.filter((column) => column.includes(`${field.key}.`))
|
|
539
537
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
540
|
-
const items = await File.get(join(tablePath, (prefix ?? "") + field.key
|
|
538
|
+
const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}.inib`), linesNumber, "number", undefined, this.salt);
|
|
541
539
|
if (items)
|
|
542
540
|
await Promise.allSettled(Object.entries(items).map(async ([index, item]) => {
|
|
543
541
|
if (!RETURN[index])
|
|
@@ -548,8 +546,8 @@ export default class Inibase {
|
|
|
548
546
|
}));
|
|
549
547
|
}
|
|
550
548
|
}
|
|
551
|
-
else if (await File.isExists(join(tablePath, (prefix ?? "") + field.key
|
|
552
|
-
const items = await File.get(join(tablePath, (prefix ?? "") + field.key
|
|
549
|
+
else if (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}.inib`))) {
|
|
550
|
+
const items = await File.get(join(tablePath, `${(prefix ?? "") + field.key}.inib`), linesNumber, field.type, field.children, this.salt);
|
|
553
551
|
if (items)
|
|
554
552
|
for (const [index, item] of Object.entries(items)) {
|
|
555
553
|
if (!RETURN[index])
|
|
@@ -573,8 +571,9 @@ export default class Inibase {
|
|
|
573
571
|
if (criteria.and && Utils.isObject(criteria.and)) {
|
|
574
572
|
const [searchResult, lineNumbers] = await this.applyCriteria(tableName, schema, options, criteria.and, true);
|
|
575
573
|
if (searchResult) {
|
|
576
|
-
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).filter(([_k, v], _i) => Object.keys(v).length ===
|
|
577
|
-
|
|
574
|
+
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).filter(([_k, v], _i) => Object.keys(v).length ===
|
|
575
|
+
Object.keys(criteria.and ?? {}).length)));
|
|
576
|
+
criteria.and = undefined;
|
|
578
577
|
RETURN_LineNumbers = lineNumbers;
|
|
579
578
|
}
|
|
580
579
|
else
|
|
@@ -582,7 +581,7 @@ export default class Inibase {
|
|
|
582
581
|
}
|
|
583
582
|
if (criteria.or && Utils.isObject(criteria.or)) {
|
|
584
583
|
const [searchResult, lineNumbers] = await this.applyCriteria(tableName, schema, options, criteria.or, false);
|
|
585
|
-
|
|
584
|
+
criteria.or = undefined;
|
|
586
585
|
if (searchResult) {
|
|
587
586
|
RETURN = Utils.deepMerge(RETURN, searchResult);
|
|
588
587
|
RETURN_LineNumbers = lineNumbers;
|
|
@@ -609,7 +608,7 @@ export default class Inibase {
|
|
|
609
608
|
searchComparedAtValue = searchCriteria.map((single_or) => single_or[1]);
|
|
610
609
|
searchLogicalOperator = "or";
|
|
611
610
|
}
|
|
612
|
-
|
|
611
|
+
value.or = undefined;
|
|
613
612
|
}
|
|
614
613
|
if (value?.and &&
|
|
615
614
|
Array.isArray(value?.and)) {
|
|
@@ -623,7 +622,7 @@ export default class Inibase {
|
|
|
623
622
|
searchComparedAtValue = searchCriteria.map((single_and) => single_and[1]);
|
|
624
623
|
searchLogicalOperator = "and";
|
|
625
624
|
}
|
|
626
|
-
|
|
625
|
+
value.and = undefined;
|
|
627
626
|
}
|
|
628
627
|
}
|
|
629
628
|
else if (Array.isArray(value)) {
|
|
@@ -649,7 +648,7 @@ export default class Inibase {
|
|
|
649
648
|
searchOperator = "=";
|
|
650
649
|
searchComparedAtValue = value;
|
|
651
650
|
}
|
|
652
|
-
const [searchResult, totalLines, linesNumbers] = await File.search(join(tablePath, key
|
|
651
|
+
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);
|
|
653
652
|
if (searchResult) {
|
|
654
653
|
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).map(([id, value]) => [
|
|
655
654
|
id,
|
|
@@ -657,7 +656,7 @@ export default class Inibase {
|
|
|
657
656
|
[key]: value,
|
|
658
657
|
},
|
|
659
658
|
])));
|
|
660
|
-
this.totalItems[tableName
|
|
659
|
+
this.totalItems[`${tableName}-${key}`] = totalLines;
|
|
661
660
|
RETURN_LineNumbers = linesNumbers;
|
|
662
661
|
}
|
|
663
662
|
if (allTrue && index > 0) {
|
|
@@ -675,17 +674,17 @@ export default class Inibase {
|
|
|
675
674
|
return schema
|
|
676
675
|
.map((field) => {
|
|
677
676
|
if (columns.some((column) => column.startsWith("!")))
|
|
678
|
-
return columns.includes(
|
|
677
|
+
return columns.includes(`!${field.key}`) ? null : field;
|
|
679
678
|
if (columns.includes(field.key) || columns.includes("*"))
|
|
680
679
|
return field;
|
|
681
680
|
if ((field.type === "array" || field.type === "object") &&
|
|
682
681
|
Utils.isArrayOfObjects(field.children) &&
|
|
683
|
-
columns.filter((column) => column.startsWith(field.key
|
|
684
|
-
column.startsWith(
|
|
682
|
+
columns.filter((column) => column.startsWith(`${field.key}.`) ||
|
|
683
|
+
column.startsWith(`!${field.key}.`)).length) {
|
|
685
684
|
field.children = this._filterSchemaByColumns(field.children, columns
|
|
686
|
-
.filter((column) => column.startsWith(field.key
|
|
687
|
-
column.startsWith(
|
|
688
|
-
.map((column) => column.replace(field.key
|
|
685
|
+
.filter((column) => column.startsWith(`${field.key}.`) ||
|
|
686
|
+
column.startsWith(`!${field.key}.`))
|
|
687
|
+
.map((column) => column.replace(`${field.key}.`, "")));
|
|
689
688
|
return field;
|
|
690
689
|
}
|
|
691
690
|
return null;
|
|
@@ -717,7 +716,7 @@ export default class Inibase {
|
|
|
717
716
|
options.perPage = options.perPage || 15;
|
|
718
717
|
let RETURN;
|
|
719
718
|
let schema = await this.getSchemaWhenTableNotEmpty(tableName, tableSchema);
|
|
720
|
-
if (options.columns
|
|
719
|
+
if (options.columns?.length)
|
|
721
720
|
schema = this._filterSchemaByColumns(schema, options.columns);
|
|
722
721
|
if (where &&
|
|
723
722
|
((Array.isArray(where) && !where.length) ||
|
|
@@ -730,12 +729,12 @@ export default class Inibase {
|
|
|
730
729
|
1), options));
|
|
731
730
|
if (Config.isCacheEnabled &&
|
|
732
731
|
(await File.isExists(join(tablePath, ".cache", "pagination.inib"))))
|
|
733
|
-
this.totalItems[tableName
|
|
732
|
+
this.totalItems[`${tableName}-*`] = Number((await File.read(join(tablePath, ".cache", "pagination.inib"), true)).split(",")[1]);
|
|
734
733
|
else {
|
|
735
734
|
let [lastId, totalItems] = await File.get(join(tablePath, "id.inib"), -1, "number", undefined, this.salt, true);
|
|
736
735
|
if (lastId)
|
|
737
|
-
lastId = Number(Object.keys(lastId)[0] ?? 0);
|
|
738
|
-
this.totalItems[tableName
|
|
736
|
+
lastId = Number(Object.keys(lastId)?.[0] ?? 0);
|
|
737
|
+
this.totalItems[`${tableName}-*`] = totalItems;
|
|
739
738
|
if (Config.isCacheEnabled)
|
|
740
739
|
await File.write(join(tablePath, ".cache", "pagination.inib"), `${lastId},${totalItems}`, true);
|
|
741
740
|
}
|
|
@@ -750,9 +749,9 @@ export default class Inibase {
|
|
|
750
749
|
if (onlyLinesNumbers)
|
|
751
750
|
return lineNumbers;
|
|
752
751
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, lineNumbers, options)) ?? {});
|
|
753
|
-
if (!this.totalItems[tableName
|
|
754
|
-
this.totalItems[tableName
|
|
755
|
-
if (RETURN
|
|
752
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
753
|
+
this.totalItems[`${tableName}-*`] = lineNumbers.length;
|
|
754
|
+
if (RETURN?.length && !Array.isArray(where))
|
|
756
755
|
RETURN = RETURN[0];
|
|
757
756
|
}
|
|
758
757
|
else if ((Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
@@ -760,7 +759,7 @@ export default class Inibase {
|
|
|
760
759
|
let Ids = where;
|
|
761
760
|
if (!Array.isArray(Ids))
|
|
762
761
|
Ids = [Ids];
|
|
763
|
-
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
|
|
762
|
+
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);
|
|
764
763
|
if (!lineNumbers)
|
|
765
764
|
throw this.throwError("NO_RESULTS", tableName);
|
|
766
765
|
if (onlyLinesNumbers)
|
|
@@ -768,9 +767,9 @@ export default class Inibase {
|
|
|
768
767
|
? Object.keys(lineNumbers).map(Number)
|
|
769
768
|
: null;
|
|
770
769
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
|
|
771
|
-
if (!this.totalItems[tableName
|
|
772
|
-
this.totalItems[tableName
|
|
773
|
-
if (RETURN
|
|
770
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
771
|
+
this.totalItems[`${tableName}-*`] = countItems;
|
|
772
|
+
if (RETURN?.length && !Array.isArray(where))
|
|
774
773
|
RETURN = RETURN[0];
|
|
775
774
|
}
|
|
776
775
|
else if (Utils.isObject(where)) {
|
|
@@ -780,33 +779,31 @@ export default class Inibase {
|
|
|
780
779
|
cachedFilePath = join(tablePath, ".cache", `${UtilsServer.hashString(inspect(where, { sorted: true }))}.inib`);
|
|
781
780
|
if (Config.isCacheEnabled && (await File.isExists(cachedFilePath))) {
|
|
782
781
|
const cachedItems = (await File.read(cachedFilePath, true)).split(",");
|
|
783
|
-
this.totalItems[tableName
|
|
782
|
+
this.totalItems[`${tableName}-*`] = cachedItems.length;
|
|
784
783
|
if (onlyLinesNumbers)
|
|
785
784
|
return cachedItems.map(Number);
|
|
786
785
|
return this.get(tableName, cachedItems
|
|
787
786
|
.slice((options.page - 1) * options.perPage, options.page * options.perPage)
|
|
788
787
|
.map(Number), options, undefined, undefined, schema);
|
|
789
788
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
if (
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
await File.write(cachedFilePath, Array.from(linesNumbers).join(","), true);
|
|
800
|
-
}
|
|
789
|
+
let linesNumbers = null;
|
|
790
|
+
[RETURN, linesNumbers] = await this.applyCriteria(tableName, schema, options, where);
|
|
791
|
+
if (RETURN && linesNumbers) {
|
|
792
|
+
if (onlyLinesNumbers)
|
|
793
|
+
return Object.keys(RETURN).map(Number);
|
|
794
|
+
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]);
|
|
795
|
+
RETURN = Object.values(Utils.deepMerge(RETURN, await this.getItemsFromSchema(tableName, schema.filter(({ key }) => !alreadyExistsColumns.includes(key)), Object.keys(RETURN).map(Number), options)));
|
|
796
|
+
if (Config.isCacheEnabled)
|
|
797
|
+
await File.write(cachedFilePath, Array.from(linesNumbers).join(","), true);
|
|
801
798
|
}
|
|
802
799
|
}
|
|
803
800
|
if (!RETURN ||
|
|
804
801
|
(Utils.isObject(RETURN) && !Object.keys(RETURN).length) ||
|
|
805
802
|
(Array.isArray(RETURN) && !RETURN.length))
|
|
806
803
|
return null;
|
|
807
|
-
const greatestTotalItems = this.totalItems[tableName
|
|
804
|
+
const greatestTotalItems = this.totalItems[`${tableName}-*`] ??
|
|
808
805
|
Math.max(...Object.entries(this.totalItems)
|
|
809
|
-
.filter(([k]) => k.startsWith(tableName
|
|
806
|
+
.filter(([k]) => k.startsWith(`${tableName}-`))
|
|
810
807
|
.map(([, v]) => v));
|
|
811
808
|
this.pageInfo[tableName] = {
|
|
812
809
|
...(({ columns, ...restOfOptions }) => restOfOptions)(options),
|
|
@@ -839,10 +836,10 @@ export default class Inibase {
|
|
|
839
836
|
.split(",")
|
|
840
837
|
.map(Number);
|
|
841
838
|
else {
|
|
842
|
-
let lastIdObj;
|
|
839
|
+
let lastIdObj = null;
|
|
843
840
|
[lastIdObj, totalItems] = await File.get(join(tablePath, "id.inib"), -1, "number", undefined, this.salt, true);
|
|
844
841
|
if (lastIdObj)
|
|
845
|
-
lastId = Number(Object.keys(lastIdObj)[0] ?? 0);
|
|
842
|
+
lastId = Number(Object.keys(lastIdObj)?.[0] ?? 0);
|
|
846
843
|
}
|
|
847
844
|
}
|
|
848
845
|
if (Utils.isArrayOfObjects(data))
|
|
@@ -908,47 +905,45 @@ export default class Inibase {
|
|
|
908
905
|
.filter(({ id }) => id !== undefined)
|
|
909
906
|
.map(({ id }) => id));
|
|
910
907
|
}
|
|
911
|
-
|
|
908
|
+
if (Object.hasOwn(data, "id")) {
|
|
912
909
|
if (!Utils.isValidID(data.id))
|
|
913
910
|
throw this.throwError("INVALID_ID", data.id);
|
|
914
911
|
return this.put(tableName, data, data.id);
|
|
915
912
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
await
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
Utils.combineObjects([...Array(totalItems)].map((_, i) => ({
|
|
935
|
-
[`${i + 1}`]: content,
|
|
936
|
-
}))),
|
|
937
|
-
])
|
|
938
|
-
: await File.replace(path, Utils.combineObjects([...Array(totalItems)].map((_, i) => ({
|
|
913
|
+
let totalItems;
|
|
914
|
+
if (Config.isCacheEnabled &&
|
|
915
|
+
(await File.isExists(join(tablePath, ".cache", "pagination.inib"))))
|
|
916
|
+
totalItems = (await File.read(join(tablePath, ".cache", "pagination.inib"), true))
|
|
917
|
+
.split(",")
|
|
918
|
+
.map(Number)[1];
|
|
919
|
+
else
|
|
920
|
+
totalItems = await File.count(join(tablePath, "id.inib"));
|
|
921
|
+
const pathesContents = this.joinPathesContents(tablePath, {
|
|
922
|
+
...(({ id, ...restOfData }) => restOfData)(data),
|
|
923
|
+
updatedAt: Date.now(),
|
|
924
|
+
});
|
|
925
|
+
try {
|
|
926
|
+
await File.lock(join(tablePath, ".tmp"));
|
|
927
|
+
await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(this.isThreadEnabled
|
|
928
|
+
? await File.createWorker("replace", [
|
|
929
|
+
path,
|
|
930
|
+
Utils.combineObjects([...Array(totalItems)].map((_, i) => ({
|
|
939
931
|
[`${i + 1}`]: content,
|
|
940
|
-
})))
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
932
|
+
}))),
|
|
933
|
+
])
|
|
934
|
+
: await File.replace(path, Utils.combineObjects([...Array(totalItems)].map((_, i) => ({
|
|
935
|
+
[`${i + 1}`]: content,
|
|
936
|
+
})))))));
|
|
937
|
+
await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
938
|
+
if (Config.isCacheEnabled)
|
|
939
|
+
await this.clearCache(join(tablePath, ".cache"));
|
|
940
|
+
if (returnUpdatedData)
|
|
941
|
+
return await this.get(tableName, where, options, undefined, undefined, schema);
|
|
942
|
+
}
|
|
943
|
+
finally {
|
|
944
|
+
if (renameList.length)
|
|
945
|
+
await Promise.allSettled(renameList.map(async ([tempPath, _]) => unlink(tempPath)));
|
|
946
|
+
await File.unlock(join(tablePath, ".tmp"));
|
|
952
947
|
}
|
|
953
948
|
}
|
|
954
949
|
else if ((Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
@@ -966,8 +961,7 @@ export default class Inibase {
|
|
|
966
961
|
}))
|
|
967
962
|
: { ...data, updatedAt: Date.now() })).map(([path, content]) => [
|
|
968
963
|
path,
|
|
969
|
-
[...(Array.isArray(where) ? where : [where])].reduce((obj, lineNum, index) => ({
|
|
970
|
-
...obj,
|
|
964
|
+
[...(Array.isArray(where) ? where : [where])].reduce((obj, lineNum, index) => Object.assign(obj, {
|
|
971
965
|
[lineNum]: Array.isArray(content) ? content[index] : content,
|
|
972
966
|
}), {}),
|
|
973
967
|
]));
|
|
@@ -996,14 +990,13 @@ export default class Inibase {
|
|
|
996
990
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
997
991
|
if (returnUpdatedData)
|
|
998
992
|
return this.put(tableName, data, lineNumbers, options, returnUpdatedData);
|
|
999
|
-
|
|
1000
|
-
await this.put(tableName, data, lineNumbers, options, returnUpdatedData);
|
|
993
|
+
await this.put(tableName, data, lineNumbers, options, returnUpdatedData);
|
|
1001
994
|
}
|
|
1002
995
|
else
|
|
1003
996
|
throw this.throwError("INVALID_PARAMETERS");
|
|
1004
997
|
}
|
|
1005
998
|
async delete(tableName, where, _id) {
|
|
1006
|
-
|
|
999
|
+
const renameList = [];
|
|
1007
1000
|
const tablePath = join(this.folder, this.database, tableName), schema = await this.getSchemaWhenTableNotEmpty(tableName);
|
|
1008
1001
|
if (!where) {
|
|
1009
1002
|
try {
|
|
@@ -1019,12 +1012,12 @@ export default class Inibase {
|
|
|
1019
1012
|
}
|
|
1020
1013
|
return "*";
|
|
1021
1014
|
}
|
|
1022
|
-
|
|
1015
|
+
if ((Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
1023
1016
|
Utils.isValidID(where)) {
|
|
1024
1017
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
1025
1018
|
return this.delete(tableName, lineNumbers, where);
|
|
1026
1019
|
}
|
|
1027
|
-
|
|
1020
|
+
if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1028
1021
|
Utils.isNumber(where)) {
|
|
1029
1022
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
1030
1023
|
const files = (await readdir(tablePath))?.filter((fileName) => fileName.endsWith(".inib"));
|
|
@@ -1045,7 +1038,7 @@ export default class Inibase {
|
|
|
1045
1038
|
if (Config.isCacheEnabled) {
|
|
1046
1039
|
await this.clearCache(tablePath);
|
|
1047
1040
|
if (await File.isExists(join(tablePath, ".cache", "pagination.inib"))) {
|
|
1048
|
-
|
|
1041
|
+
const [lastId, totalItems] = (await File.read(join(tablePath, ".cache", "pagination.inib"), true))
|
|
1049
1042
|
.split(",")
|
|
1050
1043
|
.map(Number);
|
|
1051
1044
|
await File.write(join(tablePath, ".cache", "pagination.inib"), `${lastId},${totalItems - (Array.isArray(where) ? where.length : 1)}`, true);
|
|
@@ -1069,12 +1062,12 @@ export default class Inibase {
|
|
|
1069
1062
|
return null;
|
|
1070
1063
|
}
|
|
1071
1064
|
async sum(tableName, columns, where) {
|
|
1072
|
-
|
|
1065
|
+
const RETURN = {};
|
|
1073
1066
|
const tablePath = join(this.folder, this.database, tableName), schema = await this.getSchemaWhenTableNotEmpty(tableName);
|
|
1074
1067
|
if (!Array.isArray(columns))
|
|
1075
1068
|
columns = [columns];
|
|
1076
1069
|
for await (const column of columns) {
|
|
1077
|
-
const columnPath = join(tablePath, column
|
|
1070
|
+
const columnPath = join(tablePath, `${column}.inib`);
|
|
1078
1071
|
if (await File.isExists(columnPath)) {
|
|
1079
1072
|
if (where) {
|
|
1080
1073
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
@@ -1089,12 +1082,12 @@ export default class Inibase {
|
|
|
1089
1082
|
return Array.isArray(columns) ? RETURN : Object.values(RETURN)[0];
|
|
1090
1083
|
}
|
|
1091
1084
|
async max(tableName, columns, where) {
|
|
1092
|
-
|
|
1085
|
+
const RETURN = {};
|
|
1093
1086
|
const tablePath = join(this.folder, this.database, tableName), schema = await this.getSchemaWhenTableNotEmpty(tableName);
|
|
1094
1087
|
if (!Array.isArray(columns))
|
|
1095
1088
|
columns = [columns];
|
|
1096
1089
|
for await (const column of columns) {
|
|
1097
|
-
const columnPath = join(tablePath, column
|
|
1090
|
+
const columnPath = join(tablePath, `${column}.inib`);
|
|
1098
1091
|
if (await File.isExists(columnPath)) {
|
|
1099
1092
|
if (where) {
|
|
1100
1093
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
@@ -1109,12 +1102,12 @@ export default class Inibase {
|
|
|
1109
1102
|
return RETURN;
|
|
1110
1103
|
}
|
|
1111
1104
|
async min(tableName, columns, where) {
|
|
1112
|
-
|
|
1105
|
+
const RETURN = {};
|
|
1113
1106
|
const tablePath = join(this.folder, this.database, tableName), schema = await this.getSchemaWhenTableNotEmpty(tableName);
|
|
1114
1107
|
if (!Array.isArray(columns))
|
|
1115
1108
|
columns = [columns];
|
|
1116
1109
|
for await (const column of columns) {
|
|
1117
|
-
const columnPath = join(tablePath, column
|
|
1110
|
+
const columnPath = join(tablePath, `${column}.inib`);
|
|
1118
1111
|
if (await File.isExists(columnPath)) {
|
|
1119
1112
|
if (where) {
|
|
1120
1113
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
@@ -1155,7 +1148,7 @@ export default class Inibase {
|
|
|
1155
1148
|
if (Config.isCacheEnabled)
|
|
1156
1149
|
cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
|
|
1157
1150
|
if (where) {
|
|
1158
|
-
|
|
1151
|
+
const lineNumbers = await this.get(tableName, where, undefined, undefined, true, schema);
|
|
1159
1152
|
keepItems = Object.values((await File.get(join(tablePath, "id.inib"), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
|
|
1160
1153
|
isLineNumbers = false;
|
|
1161
1154
|
if (!keepItems.length)
|
|
@@ -1170,14 +1163,13 @@ export default class Inibase {
|
|
|
1170
1163
|
// Construct the paste command to merge files and filter lines by IDs
|
|
1171
1164
|
const pasteCommand = `paste ${filesPathes.join(" ")}`;
|
|
1172
1165
|
// Construct the sort command dynamically based on the number of files for sorting
|
|
1173
|
-
|
|
1166
|
+
const index = 2;
|
|
1174
1167
|
const sortColumns = sortArray
|
|
1175
1168
|
.map(([key, ascending], i) => {
|
|
1176
1169
|
const field = Utils.getField(key, schema);
|
|
1177
1170
|
if (field)
|
|
1178
1171
|
return `-k${i + index},${i + index}${field.type === "number" ? "n" : ""}${!ascending ? "r" : ""}`;
|
|
1179
|
-
|
|
1180
|
-
return "";
|
|
1172
|
+
return "";
|
|
1181
1173
|
})
|
|
1182
1174
|
.join(" ");
|
|
1183
1175
|
const sortCommand = `sort ${sortColumns}`;
|