inibase 1.5.6 → 1.5.8
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.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +108 -85
- package/package.json +1 -1
package/dist/file.js
CHANGED
|
@@ -227,7 +227,7 @@ export async function get(filePath, lineNumbers, field, readWholeFile = false) {
|
|
|
227
227
|
else if (lineNumbers === -1) {
|
|
228
228
|
const escapedFilePath = escapeShellPath(filePath);
|
|
229
229
|
const command = filePath.endsWith(".gz")
|
|
230
|
-
? `
|
|
230
|
+
? `gunzip -c ${escapedFilePath} | sed -n '$p'`
|
|
231
231
|
: `sed -n '$p' ${escapedFilePath}`;
|
|
232
232
|
const foundedLine = (await exec(command)).stdout.trimEnd();
|
|
233
233
|
if (foundedLine)
|
|
@@ -250,7 +250,7 @@ export async function get(filePath, lineNumbers, field, readWholeFile = false) {
|
|
|
250
250
|
}
|
|
251
251
|
const escapedFilePath = escapeShellPath(filePath);
|
|
252
252
|
const command = filePath.endsWith(".gz")
|
|
253
|
-
? `
|
|
253
|
+
? `gunzip -c ${escapedFilePath} | sed -n '${_groupIntoRanges(lineNumbers)}'`
|
|
254
254
|
: `sed -n '${_groupIntoRanges(lineNumbers)}' ${escapedFilePath}`;
|
|
255
255
|
const foundedLines = (await exec(command)).stdout.trimEnd().split("\n");
|
|
256
256
|
let index = 0;
|
|
@@ -336,7 +336,7 @@ export const replace = async (filePath, replacements, totalItems) => {
|
|
|
336
336
|
const escapedFileTempPath = escapeShellPath(fileTempPath);
|
|
337
337
|
const sedCommand = `sed -e s/.*/${replacements}/ -e /^$/s/^/${replacements}/ ${escapedFilePath}`;
|
|
338
338
|
const command = filePath.endsWith(".gz")
|
|
339
|
-
? `
|
|
339
|
+
? `gunzip -c ${escapedFilePath} | ${sedCommand} | gzip > ${escapedFileTempPath}`
|
|
340
340
|
: `${sedCommand} > ${escapedFileTempPath}`;
|
|
341
341
|
try {
|
|
342
342
|
await exec(command);
|
|
@@ -491,7 +491,7 @@ export const remove = async (filePath, linesToDelete) => {
|
|
|
491
491
|
const escapedFilePath = escapeShellPath(filePath);
|
|
492
492
|
const escapedFileTempPath = escapeShellPath(fileTempPath);
|
|
493
493
|
const command = filePath.endsWith(".gz")
|
|
494
|
-
? `
|
|
494
|
+
? `gunzip -c ${escapedFilePath} | sed '${_groupIntoRanges(linesToDelete, "d")}' | gzip > ${escapedFileTempPath}`
|
|
495
495
|
: `sed '${_groupIntoRanges(linesToDelete, "d")}' ${escapedFilePath} > ${escapedFileTempPath}`;
|
|
496
496
|
await exec(command);
|
|
497
497
|
return [fileTempPath, filePath];
|
package/dist/index.d.ts
CHANGED
|
@@ -104,9 +104,9 @@ export default class Inibase {
|
|
|
104
104
|
* Get table schema and config
|
|
105
105
|
*
|
|
106
106
|
* @param {string} tableName
|
|
107
|
-
* @return {*} {Promise<TableObject>}
|
|
107
|
+
* @return {*} {Promise<TableObject | undefined>}
|
|
108
108
|
*/
|
|
109
|
-
getTable(tableName: string): Promise<TableObject>;
|
|
109
|
+
getTable(tableName: string): Promise<TableObject | undefined>;
|
|
110
110
|
getTableSchema(tableName: string): Promise<Schema>;
|
|
111
111
|
private throwErrorIfTableEmpty;
|
|
112
112
|
validateData(data: Data | Data[], schema: Schema, skipRequiredField?: boolean): void;
|
package/dist/index.js
CHANGED
|
@@ -137,9 +137,9 @@ export default class Inibase {
|
|
|
137
137
|
getFileExtension(tableName) {
|
|
138
138
|
let mainExtension = this.fileExtension;
|
|
139
139
|
// TODO: ADD ENCRYPTION
|
|
140
|
-
// if(globalConfig[this.databasePath].tables
|
|
140
|
+
// if(globalConfig[this.databasePath].tables?.get(tableName)?.config.encryption)
|
|
141
141
|
// mainExtension += ".enc"
|
|
142
|
-
if (globalConfig[this.databasePath].tables
|
|
142
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.compression)
|
|
143
143
|
mainExtension += ".gz";
|
|
144
144
|
return mainExtension;
|
|
145
145
|
}
|
|
@@ -212,11 +212,13 @@ export default class Inibase {
|
|
|
212
212
|
*/
|
|
213
213
|
async updateTable(tableName, schema, config) {
|
|
214
214
|
const table = await this.getTable(tableName);
|
|
215
|
+
if (!table)
|
|
216
|
+
return;
|
|
215
217
|
const tablePath = join(this.databasePath, tableName);
|
|
216
218
|
if (schema) {
|
|
217
219
|
// remove id from schema
|
|
218
220
|
schema = schema.filter(({ key }) => !["id", "createdAt", "updatedAt"].includes(key));
|
|
219
|
-
let schemaIdFilePath;
|
|
221
|
+
let schemaIdFilePath = "";
|
|
220
222
|
for await (const fileName of glob("*.schema", { cwd: tablePath }))
|
|
221
223
|
schemaIdFilePath = join(tablePath, fileName);
|
|
222
224
|
const lastSchemaID = {
|
|
@@ -293,8 +295,8 @@ export default class Inibase {
|
|
|
293
295
|
"sh",
|
|
294
296
|
"-c",
|
|
295
297
|
`for file; do ${config.compression
|
|
296
|
-
?
|
|
297
|
-
:
|
|
298
|
+
? `zcat "$file" | ${process.platform === "darwin" ? "tail -r" : "tac"} | gzip > "$file.reversed" && mv "$file.reversed" "$file"`
|
|
299
|
+
: `${process.platform === "darwin" ? "tail -r" : "tac"} "$file" > "$file.reversed" && mv "$file.reversed" "$file"`}; done`,
|
|
298
300
|
"_",
|
|
299
301
|
"{}",
|
|
300
302
|
"+",
|
|
@@ -319,22 +321,22 @@ export default class Inibase {
|
|
|
319
321
|
: `table:${config.name}`);
|
|
320
322
|
}
|
|
321
323
|
}
|
|
322
|
-
globalConfig[this.databasePath].tables
|
|
324
|
+
globalConfig[this.databasePath].tables?.delete(tableName);
|
|
323
325
|
}
|
|
324
326
|
/**
|
|
325
327
|
* Get table schema and config
|
|
326
328
|
*
|
|
327
329
|
* @param {string} tableName
|
|
328
|
-
* @return {*} {Promise<TableObject>}
|
|
330
|
+
* @return {*} {Promise<TableObject | undefined>}
|
|
329
331
|
*/
|
|
330
332
|
async getTable(tableName) {
|
|
331
333
|
const tablePath = join(this.databasePath, tableName);
|
|
332
334
|
if (!(await File.isExists(tablePath)))
|
|
333
335
|
throw this.createError("TABLE_NOT_EXISTS", tableName);
|
|
334
|
-
if (!globalConfig[this.databasePath].tables
|
|
335
|
-
globalConfig[this.databasePath].tables
|
|
336
|
+
if (!globalConfig[this.databasePath].tables?.has(tableName) ||
|
|
337
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.timestamp !==
|
|
336
338
|
(await File.getFileDate(join(tablePath, `schema.${this.schemaFileExtension}`))))
|
|
337
|
-
globalConfig[this.databasePath].tables
|
|
339
|
+
globalConfig[this.databasePath].tables?.set(tableName, {
|
|
338
340
|
schema: await this.getTableSchema(tableName),
|
|
339
341
|
config: {
|
|
340
342
|
compression: await File.isExists(join(tablePath, ".compression.config")),
|
|
@@ -344,7 +346,7 @@ export default class Inibase {
|
|
|
344
346
|
},
|
|
345
347
|
timestamp: await File.getFileDate(join(tablePath, `schema.${this.schemaFileExtension}`)),
|
|
346
348
|
});
|
|
347
|
-
return globalConfig[this.databasePath].tables
|
|
349
|
+
return globalConfig[this.databasePath].tables?.get(tableName);
|
|
348
350
|
}
|
|
349
351
|
async getTableSchema(tableName) {
|
|
350
352
|
const tablePath = join(this.databasePath, tableName);
|
|
@@ -382,7 +384,7 @@ export default class Inibase {
|
|
|
382
384
|
type: "id",
|
|
383
385
|
required: true,
|
|
384
386
|
},
|
|
385
|
-
...schema,
|
|
387
|
+
...(schema || []),
|
|
386
388
|
{
|
|
387
389
|
id: -1,
|
|
388
390
|
key: "createdAt",
|
|
@@ -398,7 +400,7 @@ export default class Inibase {
|
|
|
398
400
|
}
|
|
399
401
|
async throwErrorIfTableEmpty(tableName) {
|
|
400
402
|
const table = await this.getTable(tableName);
|
|
401
|
-
if (!table
|
|
403
|
+
if (!table?.schema)
|
|
402
404
|
throw this.createError("NO_SCHEMA", tableName);
|
|
403
405
|
if (!(await File.isExists(join(this.databasePath, tableName, `id${this.getFileExtension(tableName)}`))))
|
|
404
406
|
throw this.createError("TABLE_EMPTY", tableName);
|
|
@@ -448,27 +450,24 @@ export default class Inibase {
|
|
|
448
450
|
!regex.test(String(data[field.key])))
|
|
449
451
|
throw this.createError("INVALID_REGEX_MATCH", [field.key]);
|
|
450
452
|
}
|
|
451
|
-
if (field.unique) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
uniqueKey = field.id;
|
|
455
|
-
else
|
|
456
|
-
uniqueKey = field.unique;
|
|
453
|
+
if (field.unique && field.id !== undefined) {
|
|
454
|
+
const fieldId = field.id;
|
|
455
|
+
const uniqueKey = typeof field.unique === "boolean" ? fieldId : field.unique;
|
|
457
456
|
if (!this.uniqueMap.has(uniqueKey))
|
|
458
457
|
this.uniqueMap.set(uniqueKey, {
|
|
459
458
|
exclude: new Set(),
|
|
460
459
|
columnsValues: new Map(),
|
|
461
460
|
});
|
|
462
|
-
if (!this.uniqueMap.get(uniqueKey)
|
|
461
|
+
if (!this.uniqueMap.get(uniqueKey)?.columnsValues.has(fieldId))
|
|
463
462
|
this.uniqueMap
|
|
464
|
-
|
|
465
|
-
|
|
463
|
+
?.get(uniqueKey)
|
|
464
|
+
?.columnsValues.set(fieldId, new Set());
|
|
466
465
|
if (data.id)
|
|
467
|
-
this.uniqueMap.get(uniqueKey)
|
|
466
|
+
this.uniqueMap.get(uniqueKey)?.exclude.add(-data.id);
|
|
468
467
|
this.uniqueMap
|
|
469
468
|
.get(uniqueKey)
|
|
470
|
-
|
|
471
|
-
|
|
469
|
+
?.columnsValues.get(fieldId)
|
|
470
|
+
?.add(data[field.key]);
|
|
472
471
|
}
|
|
473
472
|
}
|
|
474
473
|
}
|
|
@@ -477,7 +476,9 @@ export default class Inibase {
|
|
|
477
476
|
async validateTableData(tableName, data, skipRequiredField = false) {
|
|
478
477
|
const clonedData = structuredClone(data);
|
|
479
478
|
// Skip ID and (created|updated)At
|
|
480
|
-
this.validateData(clonedData, globalConfig[this.databasePath].tables
|
|
479
|
+
this.validateData(clonedData, globalConfig[this.databasePath].tables
|
|
480
|
+
?.get(tableName)
|
|
481
|
+
?.schema?.slice(1, -2) ?? [], skipRequiredField);
|
|
481
482
|
await this.checkUnique(tableName);
|
|
482
483
|
}
|
|
483
484
|
cleanObject(obj) {
|
|
@@ -491,6 +492,8 @@ export default class Inibase {
|
|
|
491
492
|
formatField(value, field, _formatOnlyAvailiableKeys) {
|
|
492
493
|
if (value === null || value === undefined || value === "")
|
|
493
494
|
return value;
|
|
495
|
+
if (!field)
|
|
496
|
+
return value;
|
|
494
497
|
let _fieldType = field.type;
|
|
495
498
|
if (Array.isArray(_fieldType))
|
|
496
499
|
_fieldType = Utils.detectFieldType(value, _fieldType) ?? _fieldType[0];
|
|
@@ -561,7 +564,7 @@ export default class Inibase {
|
|
|
561
564
|
}
|
|
562
565
|
async checkUnique(tableName) {
|
|
563
566
|
const tablePath = join(this.databasePath, tableName);
|
|
564
|
-
const flattenSchema = Utils.flattenSchema(globalConfig[this.databasePath].tables
|
|
567
|
+
const flattenSchema = Utils.flattenSchema(globalConfig[this.databasePath].tables?.get(tableName)?.schema ?? []);
|
|
565
568
|
function hasDuplicates(setA, setB) {
|
|
566
569
|
for (const value of setA)
|
|
567
570
|
if (setB.has(value))
|
|
@@ -576,12 +579,14 @@ export default class Inibase {
|
|
|
576
579
|
for await (const [columnID, values] of valueObject.columnsValues) {
|
|
577
580
|
index++;
|
|
578
581
|
const field = flattenSchema.find(({ id }) => id === columnID);
|
|
582
|
+
if (!field)
|
|
583
|
+
continue;
|
|
579
584
|
fieldsKeys.push(field.key);
|
|
580
585
|
const [_, totalLines, lineNumbers] = await File.search(join(tablePath, `${field.key}${this.getFileExtension(tableName)}`), "[]", Array.from(values), undefined, valueObject.exclude, { ...field, databasePath: this.databasePath }, 1, undefined, false);
|
|
581
586
|
if (totalLines > 0) {
|
|
582
587
|
if (valueObject.columnsValues.size === 1 ||
|
|
583
588
|
(valueObject.columnsValues.size === index &&
|
|
584
|
-
hasDuplicates(lineNumbers, mergedLineNumbers))) {
|
|
589
|
+
!!(lineNumbers && hasDuplicates(lineNumbers, mergedLineNumbers)))) {
|
|
585
590
|
this.uniqueMap = new Map();
|
|
586
591
|
if (valueObject.columnsValues.size > 1)
|
|
587
592
|
throw this.createError("GROUP_UNIQUE", [
|
|
@@ -593,7 +598,7 @@ export default class Inibase {
|
|
|
593
598
|
Array.from(values).join(", "),
|
|
594
599
|
]);
|
|
595
600
|
}
|
|
596
|
-
lineNumbers
|
|
601
|
+
lineNumbers?.forEach(mergedLineNumbers.add, mergedLineNumbers);
|
|
597
602
|
}
|
|
598
603
|
else {
|
|
599
604
|
shouldContinueParent = true; // Flag to skip the rest of this inner loop
|
|
@@ -778,7 +783,8 @@ export default class Inibase {
|
|
|
778
783
|
const items = await File.get(fieldPath, linesNumber, {
|
|
779
784
|
...field,
|
|
780
785
|
type: field.key === "id" &&
|
|
781
|
-
globalConfig[this.databasePath].tables
|
|
786
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
787
|
+
.decodeID
|
|
782
788
|
? "number"
|
|
783
789
|
: field.type,
|
|
784
790
|
databasePath: this.databasePath,
|
|
@@ -886,11 +892,11 @@ export default class Inibase {
|
|
|
886
892
|
}
|
|
887
893
|
}
|
|
888
894
|
}
|
|
889
|
-
else if (this.isSimpleField(field.children)) {
|
|
895
|
+
else if (field.children != null && this.isSimpleField(field.children)) {
|
|
890
896
|
// If `children` is FieldType, handle it as an array of simple types (no recursion needed here)
|
|
891
897
|
await this.processSimpleField(tableName, field, RETURN, linesNumber, prefix);
|
|
892
898
|
}
|
|
893
|
-
else if (this.isTableField(field.children)) {
|
|
899
|
+
else if (field.children != null && this.isTableField(field.children)) {
|
|
894
900
|
await this.processTableField(tableName, field, RETURN, linesNumber, options, prefix);
|
|
895
901
|
}
|
|
896
902
|
}
|
|
@@ -953,16 +959,18 @@ export default class Inibase {
|
|
|
953
959
|
.filter((item) => item), {
|
|
954
960
|
...options,
|
|
955
961
|
perPage: -1,
|
|
956
|
-
columns: options
|
|
962
|
+
columns: options?.columns
|
|
957
963
|
?.filter((column) => column.includes(`${field.key}.`))
|
|
958
964
|
.map((column) => column.replace(`${field.key}.`, "")),
|
|
959
965
|
});
|
|
960
966
|
const formatLineContent = (lineContent) => Array.isArray(lineContent)
|
|
961
|
-
? lineContent
|
|
967
|
+
? lineContent
|
|
968
|
+
.map((singleContent) => singleContent
|
|
962
969
|
? Array.isArray(singleContent)
|
|
963
970
|
? singleContent.map(formatLineContent)
|
|
964
971
|
: items?.find(({ id }) => singleContent === id)
|
|
965
972
|
: singleContent)
|
|
973
|
+
.filter((item) => item !== undefined)
|
|
966
974
|
: items?.find(({ id }) => lineContent === id);
|
|
967
975
|
for (const [lineNumber, lineContent] of searchableIDs.entries()) {
|
|
968
976
|
if (!lineContent)
|
|
@@ -987,7 +995,8 @@ export default class Inibase {
|
|
|
987
995
|
}
|
|
988
996
|
return acc[key];
|
|
989
997
|
}, obj);
|
|
990
|
-
|
|
998
|
+
if (lastKey !== undefined)
|
|
999
|
+
target[lastKey] = value;
|
|
991
1000
|
}
|
|
992
1001
|
async applyCriteria(tableName, options, criteria, allTrue, searchIn) {
|
|
993
1002
|
const tablePath = join(this.databasePath, tableName);
|
|
@@ -1000,7 +1009,7 @@ export default class Inibase {
|
|
|
1000
1009
|
const criteriaOR = criteria.or;
|
|
1001
1010
|
if (criteriaOR)
|
|
1002
1011
|
delete criteria.or;
|
|
1003
|
-
const schema = globalConfig[this.databasePath].tables
|
|
1012
|
+
const schema = globalConfig[this.databasePath].tables?.get(tableName)?.schema ?? [];
|
|
1004
1013
|
if (Object.keys(criteria).length) {
|
|
1005
1014
|
if (allTrue === undefined)
|
|
1006
1015
|
allTrue = true;
|
|
@@ -1028,15 +1037,17 @@ export default class Inibase {
|
|
|
1028
1037
|
if (nestedAnd || nestedOr) {
|
|
1029
1038
|
const logicalChild = nestedAnd ?? nestedOr;
|
|
1030
1039
|
const logic = nestedAnd ? "and" : "or";
|
|
1031
|
-
|
|
1032
|
-
.
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
+
if (logicalChild && !Array.isArray(logicalChild)) {
|
|
1041
|
+
const crit = Object.entries(logicalChild)
|
|
1042
|
+
.map((item) => typeof item[1] === "string"
|
|
1043
|
+
? Utils.FormatObjectCriteriaValue(item[1])
|
|
1044
|
+
: ["=", item[1]])
|
|
1045
|
+
.filter(Boolean);
|
|
1046
|
+
if (crit.length) {
|
|
1047
|
+
searchOperator = crit.map((c) => c[0]);
|
|
1048
|
+
searchComparedAtValue = crit.map((c) => c[1]);
|
|
1049
|
+
searchLogicalOperator = logic;
|
|
1050
|
+
}
|
|
1040
1051
|
}
|
|
1041
1052
|
delete value[logic];
|
|
1042
1053
|
}
|
|
@@ -1050,14 +1061,14 @@ export default class Inibase {
|
|
|
1050
1061
|
searchOperator = "=";
|
|
1051
1062
|
searchComparedAtValue = value;
|
|
1052
1063
|
}
|
|
1053
|
-
const [searchResult, totalLines, linesNumbers] = await File.search(join(tablePath, `${key}${this.getFileExtension(tableName)}`), searchOperator ?? "=", searchComparedAtValue, searchLogicalOperator, searchIn, {
|
|
1064
|
+
const [searchResult, totalLines, linesNumbers] = await File.search(join(tablePath, `${key}${this.getFileExtension(tableName)}`), searchOperator ?? "=", searchComparedAtValue ?? null, searchLogicalOperator, searchIn, {
|
|
1054
1065
|
...field,
|
|
1055
1066
|
databasePath: this.databasePath,
|
|
1056
1067
|
table: field.table ?? tableName,
|
|
1057
|
-
}, options.perPage < 0 ? undefined : options.perPage, options.perPage < 0
|
|
1068
|
+
}, (options.perPage ?? 0) < 0 ? undefined : options.perPage, (options.perPage ?? 0) < 0
|
|
1058
1069
|
? undefined
|
|
1059
1070
|
: (options.page - 1) * options.perPage +
|
|
1060
|
-
(options.page > 1 ? 1 : 0), true);
|
|
1071
|
+
((options.page ?? 1) > 1 ? 1 : 0), true);
|
|
1061
1072
|
if (!searchResult) {
|
|
1062
1073
|
if (allTrue)
|
|
1063
1074
|
return null;
|
|
@@ -1151,10 +1162,10 @@ export default class Inibase {
|
|
|
1151
1162
|
options.perPage = options.perPage || 15;
|
|
1152
1163
|
let total;
|
|
1153
1164
|
let RETURN;
|
|
1154
|
-
let schema = structuredClone((await this.getTable(tableName))
|
|
1165
|
+
let schema = structuredClone((await this.getTable(tableName))?.schema);
|
|
1155
1166
|
if (!schema)
|
|
1156
1167
|
throw this.createError("NO_SCHEMA", tableName);
|
|
1157
|
-
let pagination;
|
|
1168
|
+
let pagination = [0, 0];
|
|
1158
1169
|
for await (const paginationFileName of glob("*.pagination", {
|
|
1159
1170
|
cwd: tablePath,
|
|
1160
1171
|
}))
|
|
@@ -1183,7 +1194,7 @@ export default class Inibase {
|
|
|
1183
1194
|
.map((column) => [column, true]);
|
|
1184
1195
|
let cacheKey = "";
|
|
1185
1196
|
// Criteria
|
|
1186
|
-
if (globalConfig[this.databasePath].tables
|
|
1197
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1187
1198
|
cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
|
|
1188
1199
|
if (where) {
|
|
1189
1200
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
@@ -1221,7 +1232,7 @@ export default class Inibase {
|
|
|
1221
1232
|
if (cacheKey)
|
|
1222
1233
|
await File.lock(join(tablePath, ".tmp"), cacheKey);
|
|
1223
1234
|
// Combine && Execute the commands synchronously
|
|
1224
|
-
let lines = (await UtilsServer.exec(globalConfig[this.databasePath].tables
|
|
1235
|
+
let lines = (await UtilsServer.exec(globalConfig[this.databasePath].tables?.get(tableName)?.config.cache
|
|
1225
1236
|
? (await File.isExists(join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)))
|
|
1226
1237
|
? `${awkCommand} '${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}'`
|
|
1227
1238
|
: `${pasteCommand} | ${sortCommand} -o '${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}' && ${awkCommand} '${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}'`
|
|
@@ -1230,9 +1241,9 @@ export default class Inibase {
|
|
|
1230
1241
|
})).stdout
|
|
1231
1242
|
.trimEnd()
|
|
1232
1243
|
.split("\n");
|
|
1233
|
-
if (where)
|
|
1244
|
+
if (where && options.perPage >= 0)
|
|
1234
1245
|
lines = lines.slice((options.page - 1) * options.perPage, options.page * options.perPage);
|
|
1235
|
-
else if (!this.totalItems.has(`${tableName}-*`))
|
|
1246
|
+
else if (!where && !this.totalItems.has(`${tableName}-*`))
|
|
1236
1247
|
this.totalItems.set(`${tableName}-*`, pagination[1]);
|
|
1237
1248
|
if (!lines.length)
|
|
1238
1249
|
return null;
|
|
@@ -1245,7 +1256,7 @@ export default class Inibase {
|
|
|
1245
1256
|
const field = Utils.getField(parse(fileName).name, schema);
|
|
1246
1257
|
if (field) {
|
|
1247
1258
|
if (field.key === "id" &&
|
|
1248
|
-
globalConfig[this.databasePath].tables
|
|
1259
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1249
1260
|
.decodeID)
|
|
1250
1261
|
outputObject[field.key] = splitedFileColumns[index];
|
|
1251
1262
|
else
|
|
@@ -1254,7 +1265,9 @@ export default class Inibase {
|
|
|
1254
1265
|
});
|
|
1255
1266
|
return outputObject;
|
|
1256
1267
|
});
|
|
1257
|
-
const restOfColumns = await this.get(tableName, outputArray
|
|
1268
|
+
const restOfColumns = await this.get(tableName, outputArray
|
|
1269
|
+
.map(({ id }) => id)
|
|
1270
|
+
.filter((id) => id !== undefined), (({ sort, ...rest }) => rest)(options));
|
|
1258
1271
|
return restOfColumns
|
|
1259
1272
|
? outputArray.map((item) => ({
|
|
1260
1273
|
...item,
|
|
@@ -1279,7 +1292,8 @@ export default class Inibase {
|
|
|
1279
1292
|
else if (((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1280
1293
|
Utils.isNumber(where)) &&
|
|
1281
1294
|
(_whereIsLinesNumbers ||
|
|
1282
|
-
!globalConfig[this.databasePath].tables
|
|
1295
|
+
!globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1296
|
+
.decodeID)) {
|
|
1283
1297
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
1284
1298
|
let lineNumbers = where;
|
|
1285
1299
|
if (!Array.isArray(lineNumbers))
|
|
@@ -1293,7 +1307,8 @@ export default class Inibase {
|
|
|
1293
1307
|
RETURN = RETURN[0];
|
|
1294
1308
|
}
|
|
1295
1309
|
else if ((!_whereIsLinesNumbers &&
|
|
1296
|
-
globalConfig[this.databasePath].tables
|
|
1310
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1311
|
+
.decodeID &&
|
|
1297
1312
|
((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1298
1313
|
Utils.isNumber(where))) ||
|
|
1299
1314
|
(Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
@@ -1321,7 +1336,7 @@ export default class Inibase {
|
|
|
1321
1336
|
else if (Utils.isObject(where)) {
|
|
1322
1337
|
let cachedFilePath = "";
|
|
1323
1338
|
// Criteria
|
|
1324
|
-
if (globalConfig[this.databasePath].tables
|
|
1339
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache) {
|
|
1325
1340
|
cachedFilePath = join(tablePath, ".cache", `${UtilsServer.hashString(inspect(where, { sorted: true }))}${this.fileExtension}`);
|
|
1326
1341
|
if (await File.isExists(cachedFilePath)) {
|
|
1327
1342
|
const cachedItems = (await readFile(cachedFilePath, "utf8")).split(",");
|
|
@@ -1352,7 +1367,7 @@ export default class Inibase {
|
|
|
1352
1367
|
for (const [key] of this.totalItems)
|
|
1353
1368
|
if (key.startsWith(`${tableName}-`) && key !== `${tableName}-id`)
|
|
1354
1369
|
this.totalItems.delete(key);
|
|
1355
|
-
if (globalConfig[this.databasePath].tables
|
|
1370
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1356
1371
|
await writeFile(cachedFilePath, Object.keys(LineNumberDataObj).join(","));
|
|
1357
1372
|
}
|
|
1358
1373
|
}
|
|
@@ -1362,7 +1377,7 @@ export default class Inibase {
|
|
|
1362
1377
|
return null;
|
|
1363
1378
|
if (total === undefined)
|
|
1364
1379
|
total = this.totalItems.has(`${tableName}-*`)
|
|
1365
|
-
? this.totalItems.get(`${tableName}-*`)
|
|
1380
|
+
? (this.totalItems.get(`${tableName}-*`) ?? 0)
|
|
1366
1381
|
: Math.max(...[...this.totalItems.entries()]
|
|
1367
1382
|
.filter(([k]) => k.startsWith(`${tableName}-`))
|
|
1368
1383
|
.map(([, v]) => v));
|
|
@@ -1382,7 +1397,7 @@ export default class Inibase {
|
|
|
1382
1397
|
};
|
|
1383
1398
|
const tablePath = join(this.databasePath, tableName);
|
|
1384
1399
|
await this.getTable(tableName);
|
|
1385
|
-
if (!globalConfig[this.databasePath].tables
|
|
1400
|
+
if (!globalConfig[this.databasePath].tables?.get(tableName)?.schema)
|
|
1386
1401
|
throw this.createError("NO_SCHEMA", tableName);
|
|
1387
1402
|
if (!returnPostedData)
|
|
1388
1403
|
returnPostedData = false;
|
|
@@ -1392,7 +1407,7 @@ export default class Inibase {
|
|
|
1392
1407
|
const renameList = [];
|
|
1393
1408
|
try {
|
|
1394
1409
|
await File.lock(join(tablePath, ".tmp"), keys);
|
|
1395
|
-
let paginationFilePath;
|
|
1410
|
+
let paginationFilePath = "";
|
|
1396
1411
|
for await (const fileName of glob("*.pagination", { cwd: tablePath }))
|
|
1397
1412
|
paginationFilePath = join(tablePath, fileName);
|
|
1398
1413
|
let [lastId, _totalItems] = parse(paginationFilePath)
|
|
@@ -1411,36 +1426,38 @@ export default class Inibase {
|
|
|
1411
1426
|
clonedData.createdAt = Date.now();
|
|
1412
1427
|
clonedData.updatedAt = undefined;
|
|
1413
1428
|
}
|
|
1414
|
-
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables
|
|
1415
|
-
const pathesContents = this.joinPathesContents(tableName, globalConfig[this.databasePath].tables
|
|
1429
|
+
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables?.get(tableName)?.schema ?? [], false);
|
|
1430
|
+
const pathesContents = this.joinPathesContents(tableName, globalConfig[this.databasePath].tables?.get(tableName)?.config.prepend
|
|
1416
1431
|
? Array.isArray(clonedData)
|
|
1417
1432
|
? clonedData.toReversed()
|
|
1418
1433
|
: clonedData
|
|
1419
1434
|
: clonedData);
|
|
1420
|
-
await Promise.allSettled(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(globalConfig[this.databasePath].tables
|
|
1435
|
+
await Promise.allSettled(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1436
|
+
.prepend
|
|
1421
1437
|
? await File.prepend(path, content)
|
|
1422
1438
|
: await File.append(path, content))));
|
|
1423
1439
|
await Promise.allSettled(renameList
|
|
1424
1440
|
.filter(([_, filePath]) => filePath)
|
|
1425
1441
|
.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
1426
|
-
if (globalConfig[this.databasePath].tables
|
|
1442
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1427
1443
|
await this.clearCache(tableName);
|
|
1428
1444
|
const currentValue = this.totalItems.get(`${tableName}-*`) || 0;
|
|
1429
1445
|
this.totalItems.set(`${tableName}-*`, currentValue + (Array.isArray(data) ? data.length : 1));
|
|
1430
1446
|
await rename(paginationFilePath, join(tablePath, `${lastId}-${this.totalItems.get(`${tableName}-*`)}.pagination`));
|
|
1431
1447
|
if (returnPostedData)
|
|
1432
|
-
return this.get(tableName, globalConfig[this.databasePath].tables
|
|
1448
|
+
return this.get(tableName, globalConfig[this.databasePath].tables?.get(tableName)?.config.prepend
|
|
1433
1449
|
? Array.isArray(clonedData)
|
|
1434
1450
|
? clonedData.map((_, index) => index + 1).toReversed()
|
|
1435
1451
|
: 1
|
|
1436
1452
|
: Array.isArray(clonedData)
|
|
1437
1453
|
? clonedData
|
|
1438
|
-
.map((_, index) => this.totalItems.get(`${tableName}-*`) - index)
|
|
1454
|
+
.map((_, index) => (this.totalItems.get(`${tableName}-*`) ?? 0) - index)
|
|
1439
1455
|
.toReversed()
|
|
1440
1456
|
: this.totalItems.get(`${tableName}-*`), options, !Utils.isArrayOfObjects(clonedData), // return only one item if data is not array of objects
|
|
1441
1457
|
undefined, true);
|
|
1442
1458
|
return Array.isArray(clonedData)
|
|
1443
|
-
? (globalConfig[this.databasePath].tables
|
|
1459
|
+
? (globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1460
|
+
.prepend
|
|
1444
1461
|
? clonedData.toReversed()
|
|
1445
1462
|
: clonedData).map(({ id }) => UtilsServer.encodeID(id))
|
|
1446
1463
|
: UtilsServer.encodeID(clonedData.id);
|
|
@@ -1465,7 +1482,9 @@ export default class Inibase {
|
|
|
1465
1482
|
if (Utils.isArrayOfObjects(clonedData)) {
|
|
1466
1483
|
if (!clonedData.every((item) => Object.hasOwn(item, "id") && Utils.isValidID(item.id)))
|
|
1467
1484
|
throw this.createError("INVALID_ID");
|
|
1468
|
-
return this.put(tableName, clonedData, clonedData
|
|
1485
|
+
return this.put(tableName, clonedData, clonedData
|
|
1486
|
+
.map(({ id }) => id)
|
|
1487
|
+
.filter((id) => id !== undefined), options, returnUpdatedData);
|
|
1469
1488
|
}
|
|
1470
1489
|
if (Object.hasOwn(clonedData, "id")) {
|
|
1471
1490
|
if (!Utils.isValidID(clonedData.id))
|
|
@@ -1473,7 +1492,7 @@ export default class Inibase {
|
|
|
1473
1492
|
return this.put(tableName, clonedData, clonedData.id, options, returnUpdatedData);
|
|
1474
1493
|
}
|
|
1475
1494
|
await this.validateTableData(tableName, clonedData, true);
|
|
1476
|
-
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables
|
|
1495
|
+
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables?.get(tableName)?.schema ?? [], true);
|
|
1477
1496
|
const pathesContents = this.joinPathesContents(tableName, {
|
|
1478
1497
|
...(({ id, ...restOfData }) => restOfData)(clonedData),
|
|
1479
1498
|
updatedAt: Date.now(),
|
|
@@ -1488,7 +1507,7 @@ export default class Inibase {
|
|
|
1488
1507
|
await Promise.allSettled(renameList
|
|
1489
1508
|
.filter(([_, filePath]) => filePath)
|
|
1490
1509
|
.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
1491
|
-
if (globalConfig[this.databasePath].tables
|
|
1510
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1492
1511
|
await this.clearCache(join(tablePath, ".cache"));
|
|
1493
1512
|
if (returnUpdatedData)
|
|
1494
1513
|
return await this.get(tableName, undefined, options);
|
|
@@ -1504,10 +1523,11 @@ export default class Inibase {
|
|
|
1504
1523
|
else if (((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1505
1524
|
Utils.isNumber(where)) &&
|
|
1506
1525
|
(_whereIsLinesNumbers ||
|
|
1507
|
-
!globalConfig[this.databasePath].tables
|
|
1526
|
+
!globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1527
|
+
.decodeID)) {
|
|
1508
1528
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
1509
1529
|
await this.validateTableData(tableName, clonedData, true);
|
|
1510
|
-
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables
|
|
1530
|
+
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables?.get(tableName)?.schema ?? [], true);
|
|
1511
1531
|
const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(tableName, Array.isArray(clonedData)
|
|
1512
1532
|
? clonedData.map((item) => ({
|
|
1513
1533
|
...item,
|
|
@@ -1529,7 +1549,7 @@ export default class Inibase {
|
|
|
1529
1549
|
await Promise.allSettled(renameList
|
|
1530
1550
|
.filter(([_, filePath]) => filePath)
|
|
1531
1551
|
.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
|
|
1532
|
-
if (globalConfig[this.databasePath].tables
|
|
1552
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1533
1553
|
await this.clearCache(tableName);
|
|
1534
1554
|
if (returnUpdatedData)
|
|
1535
1555
|
return this.get(tableName, where, options, !Array.isArray(where), undefined, true);
|
|
@@ -1543,7 +1563,8 @@ export default class Inibase {
|
|
|
1543
1563
|
}
|
|
1544
1564
|
}
|
|
1545
1565
|
else if ((!_whereIsLinesNumbers &&
|
|
1546
|
-
globalConfig[this.databasePath].tables
|
|
1566
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1567
|
+
.decodeID &&
|
|
1547
1568
|
((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1548
1569
|
Utils.isNumber(where))) ||
|
|
1549
1570
|
(Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
@@ -1573,8 +1594,8 @@ export default class Inibase {
|
|
|
1573
1594
|
if (!where) {
|
|
1574
1595
|
try {
|
|
1575
1596
|
await File.lock(join(tablePath, ".tmp"));
|
|
1576
|
-
let paginationFilePath;
|
|
1577
|
-
let pagination;
|
|
1597
|
+
let paginationFilePath = "";
|
|
1598
|
+
let pagination = [0, 0];
|
|
1578
1599
|
for await (const paginationFileName of glob("*.pagination", {
|
|
1579
1600
|
cwd: tablePath,
|
|
1580
1601
|
})) {
|
|
@@ -1586,7 +1607,7 @@ export default class Inibase {
|
|
|
1586
1607
|
await Promise.allSettled((await readdir(tablePath))
|
|
1587
1608
|
?.filter((fileName) => fileName.endsWith(this.getFileExtension(tableName)))
|
|
1588
1609
|
.map(async (file) => unlink(join(tablePath, file))));
|
|
1589
|
-
if (globalConfig[this.databasePath].tables
|
|
1610
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1590
1611
|
await this.clearCache(tableName);
|
|
1591
1612
|
await rename(paginationFilePath, join(tablePath, `${pagination[0]}-0.pagination`));
|
|
1592
1613
|
return true;
|
|
@@ -1598,15 +1619,16 @@ export default class Inibase {
|
|
|
1598
1619
|
if (((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1599
1620
|
Utils.isNumber(where)) &&
|
|
1600
1621
|
(_whereIsLinesNumbers ||
|
|
1601
|
-
!globalConfig[this.databasePath].tables
|
|
1622
|
+
!globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1623
|
+
.decodeID)) {
|
|
1602
1624
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
1603
1625
|
const files = (await readdir(tablePath))?.filter((fileName) => fileName.endsWith(this.getFileExtension(tableName)));
|
|
1604
1626
|
if (files.length) {
|
|
1605
1627
|
const renameList = [];
|
|
1606
1628
|
try {
|
|
1607
1629
|
await File.lock(join(tablePath, ".tmp"));
|
|
1608
|
-
let paginationFilePath;
|
|
1609
|
-
let pagination;
|
|
1630
|
+
let paginationFilePath = "";
|
|
1631
|
+
let pagination = [0, 0];
|
|
1610
1632
|
for await (const paginationFileName of glob("*.pagination", {
|
|
1611
1633
|
cwd: tablePath,
|
|
1612
1634
|
})) {
|
|
@@ -1626,7 +1648,7 @@ export default class Inibase {
|
|
|
1626
1648
|
await Promise.allSettled((await readdir(tablePath))
|
|
1627
1649
|
?.filter((fileName) => fileName.endsWith(this.getFileExtension(tableName)))
|
|
1628
1650
|
.map(async (file) => unlink(join(tablePath, file))));
|
|
1629
|
-
if (globalConfig[this.databasePath].tables
|
|
1651
|
+
if (globalConfig[this.databasePath].tables?.get(tableName)?.config.cache)
|
|
1630
1652
|
await this.clearCache(tableName);
|
|
1631
1653
|
await rename(paginationFilePath, join(tablePath, `${pagination[0]}-${pagination[1] - (Array.isArray(where) ? where.length : 1)}.pagination`));
|
|
1632
1654
|
return true;
|
|
@@ -1641,7 +1663,8 @@ export default class Inibase {
|
|
|
1641
1663
|
}
|
|
1642
1664
|
}
|
|
1643
1665
|
if ((!_whereIsLinesNumbers &&
|
|
1644
|
-
globalConfig[this.databasePath].tables
|
|
1666
|
+
globalConfig[this.databasePath].tables?.get(tableName)?.config
|
|
1667
|
+
.decodeID &&
|
|
1645
1668
|
((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
1646
1669
|
Utils.isNumber(where))) ||
|
|
1647
1670
|
(Array.isArray(where) && where.every(Utils.isValidID)) ||
|