inibase 1.0.0-rc.76 → 1.0.0-rc.78
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/cli.js +6 -5
- package/dist/file.d.ts +1 -6
- package/dist/index.d.ts +0 -1
- package/dist/index.js +43 -31
- package/dist/utils.server.d.ts +0 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "dotenv/config";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
import Inison from "inison";
|
|
@@ -12,10 +12,11 @@ const textGreen = (input) => `\u001b[1;32m${input}\u001b[0m`;
|
|
|
12
12
|
const textRed = (input) => `\u001b[1;31m${input}\u001b[0m`;
|
|
13
13
|
const textBlue = (input) => `\u001b[1;34m${input}\u001b[0m`;
|
|
14
14
|
const textMagenta = (input) => `\u001b[1;35m${input}\u001b[0m`;
|
|
15
|
-
let { path, version } = parseArgs({
|
|
15
|
+
let { path, version, table } = parseArgs({
|
|
16
16
|
options: {
|
|
17
17
|
path: { type: "string", short: "p" },
|
|
18
18
|
version: { type: "boolean", short: "v" },
|
|
19
|
+
table: { type: "string", short: "t" },
|
|
19
20
|
},
|
|
20
21
|
}).values;
|
|
21
22
|
if (version) {
|
|
@@ -30,16 +31,15 @@ const rl = createInterface({
|
|
|
30
31
|
const setPath = async (firstTime) => {
|
|
31
32
|
if (!path)
|
|
32
33
|
path = await rl.question(firstTime ? "Database path: " : "Please type a valid database path: ");
|
|
33
|
-
if (!path || !(await isExists(
|
|
34
|
+
if (!path || !(await isExists(path)))
|
|
34
35
|
await setPath();
|
|
35
36
|
};
|
|
36
37
|
console.clear();
|
|
37
38
|
await setPath(true);
|
|
38
|
-
const db = new Inibase(
|
|
39
|
+
const db = new Inibase(path);
|
|
39
40
|
process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
|
|
40
41
|
console.clear();
|
|
41
42
|
rl.prompt();
|
|
42
|
-
let table;
|
|
43
43
|
rl.on("line", async (input) => {
|
|
44
44
|
const splitedInput = input
|
|
45
45
|
.trim()
|
|
@@ -70,6 +70,7 @@ rl.on("line", async (input) => {
|
|
|
70
70
|
${textMagenta("--page")} | ${textMagenta("-p")} number?
|
|
71
71
|
${textMagenta("--per-page")} | ${textMagenta("-l")} number?
|
|
72
72
|
${textMagenta("--columns")} | ${textMagenta("-c")} columnName[]?
|
|
73
|
+
${textMagenta("--sort")} | ${textMagenta("-s")} (string|string[]|Inison.stringify(sortObject))?
|
|
73
74
|
${textMagenta("--data")} | ${textMagenta("-d")} Inison.stringify(Data) ${textRed("* POST & PUT")}`);
|
|
74
75
|
break;
|
|
75
76
|
}
|
package/dist/file.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
1
|
import type { ComparisonOperator, FieldType, Schema } from "./index.js";
|
|
3
2
|
export declare const lock: (folderPath: string, prefix?: string) => Promise<void>;
|
|
4
3
|
export declare const unlock: (folderPath: string, prefix?: string) => Promise<void>;
|
|
@@ -107,11 +106,7 @@ export declare const remove: (filePath: string, linesToDelete: number | number[]
|
|
|
107
106
|
*
|
|
108
107
|
* Note: Decodes each line for comparison and can handle complex queries with multiple conditions.
|
|
109
108
|
*/
|
|
110
|
-
export declare const search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | null | (string | number | boolean | null)[], logicalOperator?: "and" | "or", fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[] | Schema, limit?: number, offset?: number, readWholeFile?: boolean, secretKey?: string | Buffer) => Promise<[
|
|
111
|
-
Record<number, string | number | boolean | null | (string | number | boolean | null)[]> | null,
|
|
112
|
-
number,
|
|
113
|
-
Set<number> | null
|
|
114
|
-
]>;
|
|
109
|
+
export declare const search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | null | (string | number | boolean | null)[], logicalOperator?: "and" | "or", fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[] | Schema, limit?: number, offset?: number, readWholeFile?: boolean, secretKey?: string | Buffer) => Promise<[Record<number, string | number | boolean | null | (string | number | boolean | null)[]> | null, number, Set<number> | null]>;
|
|
115
110
|
/**
|
|
116
111
|
* Asynchronously counts the number of lines in a file.
|
|
117
112
|
*
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -222,30 +222,32 @@ export default class Inibase {
|
|
|
222
222
|
const schemaFile = await readFile(tableSchemaPath, "utf8");
|
|
223
223
|
if (!schemaFile)
|
|
224
224
|
return undefined;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return [
|
|
225
|
+
let schema = JSON.parse(schemaFile);
|
|
226
|
+
const lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
227
|
+
schema = [
|
|
229
228
|
{
|
|
230
|
-
id:
|
|
229
|
+
id: 0,
|
|
231
230
|
key: "id",
|
|
232
231
|
type: "id",
|
|
233
232
|
required: true,
|
|
234
233
|
},
|
|
235
|
-
...
|
|
234
|
+
...schema,
|
|
236
235
|
{
|
|
237
|
-
id:
|
|
236
|
+
id: lastIdNumber + 1,
|
|
238
237
|
key: "createdAt",
|
|
239
238
|
type: "date",
|
|
240
239
|
required: true,
|
|
241
240
|
},
|
|
242
241
|
{
|
|
243
|
-
id:
|
|
242
|
+
id: lastIdNumber + 2,
|
|
244
243
|
key: "updatedAt",
|
|
245
244
|
type: "date",
|
|
246
245
|
required: false,
|
|
247
246
|
},
|
|
248
247
|
];
|
|
248
|
+
if (!encodeIDs)
|
|
249
|
+
return schema;
|
|
250
|
+
return UtilsServer.encodeSchemaID(schema, this.salt);
|
|
249
251
|
}
|
|
250
252
|
async throwErrorIfTableEmpty(tableName) {
|
|
251
253
|
const table = await this.getTable(tableName);
|
|
@@ -820,7 +822,7 @@ export default class Inibase {
|
|
|
820
822
|
(Utils.isObject(where) && !Object.keys(where).length)))
|
|
821
823
|
where = undefined;
|
|
822
824
|
if (options.sort) {
|
|
823
|
-
let sortArray,
|
|
825
|
+
let sortArray, awkCommand = "";
|
|
824
826
|
if (Utils.isObject(options.sort) && !Array.isArray(options.sort)) {
|
|
825
827
|
// {name: "ASC", age: "DESC"}
|
|
826
828
|
sortArray = Object.entries(options.sort).map(([key, value]) => [
|
|
@@ -838,16 +840,17 @@ export default class Inibase {
|
|
|
838
840
|
cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
|
|
839
841
|
if (where) {
|
|
840
842
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
841
|
-
|
|
842
|
-
isLineNumbers = false;
|
|
843
|
-
if (!keepItems.length)
|
|
843
|
+
if (!lineNumbers.length)
|
|
844
844
|
throw this.throwError("NO_RESULTS", tableName);
|
|
845
|
-
|
|
845
|
+
const itemsIDs = Object.values((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
|
|
846
|
+
awkCommand = `awk '${itemsIDs.map((id) => `$1 == ${id}`).join(" || ")}'`;
|
|
846
847
|
}
|
|
847
|
-
|
|
848
|
-
|
|
848
|
+
else
|
|
849
|
+
awkCommand = `awk '${Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
|
|
849
850
|
index +
|
|
850
|
-
1)
|
|
851
|
+
1)
|
|
852
|
+
.map((lineNumber) => `NR==${lineNumber}`)
|
|
853
|
+
.join(" || ")}'`;
|
|
851
854
|
const filesPathes = [["id", true], ...sortArray].map((column) => join(tablePath, `${column[0]}${this.getFileExtension(tableName)}`));
|
|
852
855
|
for await (const path of filesPathes.slice(1))
|
|
853
856
|
if (!(await File.isExists(path)))
|
|
@@ -867,15 +870,11 @@ export default class Inibase {
|
|
|
867
870
|
})
|
|
868
871
|
.join(" ");
|
|
869
872
|
const sortCommand = `sort ${sortColumns} -T=${join(tablePath, ".tmp")}`;
|
|
870
|
-
// Construct the awk command to keep only the specified lines after sorting
|
|
871
|
-
const awkCommand = isLineNumbers
|
|
872
|
-
? `awk '${keepItems.map((lineNumber) => `NR==${lineNumber}`).join(" || ")}'`
|
|
873
|
-
: `awk '${keepItems.map((id) => `$1 ~ /^${id} */`).join(" || ")}'`;
|
|
874
873
|
try {
|
|
875
874
|
if (cacheKey)
|
|
876
875
|
await File.lock(join(tablePath, ".tmp"), cacheKey);
|
|
877
876
|
// Combine && Execute the commands synchronously
|
|
878
|
-
|
|
877
|
+
let lines = (await UtilsServer.exec(this.tables[tableName].config.cache
|
|
879
878
|
? (await File.isExists(join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)))
|
|
880
879
|
? `${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
881
880
|
: `${pasteCommand} | ${sortCommand} -o ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)} && ${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
@@ -884,6 +883,12 @@ export default class Inibase {
|
|
|
884
883
|
})).stdout
|
|
885
884
|
.trim()
|
|
886
885
|
.split("\n");
|
|
886
|
+
if (where)
|
|
887
|
+
lines = lines.slice((options.page - 1) * options.perPage, options.page * options.perPage);
|
|
888
|
+
else if (!this.totalItems[`${tableName}-*`])
|
|
889
|
+
this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
|
|
890
|
+
if (!lines.length)
|
|
891
|
+
return null;
|
|
887
892
|
// Parse the result and extract the specified lines
|
|
888
893
|
const outputArray = lines.map((line) => {
|
|
889
894
|
const splitedFileColumns = line.split("\t"); // Assuming tab-separated columns
|
|
@@ -914,11 +919,14 @@ export default class Inibase {
|
|
|
914
919
|
RETURN = Object.values(await this.getItemsFromSchema(tableName, schema, Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
|
|
915
920
|
index +
|
|
916
921
|
1), options));
|
|
917
|
-
if (await File.isExists(join(tablePath, ".cache", ".pagination")))
|
|
918
|
-
this.totalItems[`${tableName}-*`]
|
|
922
|
+
if (await File.isExists(join(tablePath, ".cache", ".pagination"))) {
|
|
923
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
924
|
+
this.totalItems[`${tableName}-*`] = Number((await readFile(join(tablePath, ".cache", ".pagination"), "utf8")).split(",")[1]);
|
|
925
|
+
}
|
|
919
926
|
else {
|
|
920
927
|
const lastId = Number(Object.keys((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), -1, "number", undefined, this.salt, true))?.[0] ?? 0));
|
|
921
|
-
this.totalItems[`${tableName}-*`]
|
|
928
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
929
|
+
this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
|
|
922
930
|
await writeFile(join(tablePath, ".cache", ".pagination"), `${lastId},${this.totalItems[`${tableName}-*`]}`);
|
|
923
931
|
}
|
|
924
932
|
}
|
|
@@ -928,12 +936,12 @@ export default class Inibase {
|
|
|
928
936
|
let lineNumbers = where;
|
|
929
937
|
if (!Array.isArray(lineNumbers))
|
|
930
938
|
lineNumbers = [lineNumbers];
|
|
939
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
940
|
+
this.totalItems[`${tableName}-*`] = lineNumbers.length;
|
|
931
941
|
// useless
|
|
932
942
|
if (onlyLinesNumbers)
|
|
933
943
|
return lineNumbers;
|
|
934
944
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, lineNumbers, options)) ?? {});
|
|
935
|
-
if (!this.totalItems[`${tableName}-*`])
|
|
936
|
-
this.totalItems[`${tableName}-*`] = lineNumbers.length;
|
|
937
945
|
if (RETURN?.length && !Array.isArray(where))
|
|
938
946
|
RETURN = RETURN[0];
|
|
939
947
|
}
|
|
@@ -945,6 +953,8 @@ export default class Inibase {
|
|
|
945
953
|
const [lineNumbers, countItems] = await File.search(join(tablePath, `id${this.getFileExtension(tableName)}`), "[]", Ids.map((id) => Utils.isNumber(id) ? Number(id) : UtilsServer.decodeID(id, this.salt)), undefined, "number", undefined, Ids.length, 0, !this.totalItems[`${tableName}-*`], this.salt);
|
|
946
954
|
if (!lineNumbers)
|
|
947
955
|
throw this.throwError("NO_RESULTS", tableName);
|
|
956
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
957
|
+
this.totalItems[`${tableName}-*`] = countItems;
|
|
948
958
|
if (onlyLinesNumbers)
|
|
949
959
|
return Object.keys(lineNumbers).length
|
|
950
960
|
? Object.keys(lineNumbers).map(Number)
|
|
@@ -955,8 +965,6 @@ export default class Inibase {
|
|
|
955
965
|
options.columns = undefined;
|
|
956
966
|
}
|
|
957
967
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
|
|
958
|
-
if (!this.totalItems[`${tableName}-*`])
|
|
959
|
-
this.totalItems[`${tableName}-*`] = countItems;
|
|
960
968
|
if (RETURN?.length && !Array.isArray(where))
|
|
961
969
|
RETURN = RETURN[0];
|
|
962
970
|
}
|
|
@@ -968,7 +976,8 @@ export default class Inibase {
|
|
|
968
976
|
if (this.tables[tableName].config.cache &&
|
|
969
977
|
(await File.isExists(cachedFilePath))) {
|
|
970
978
|
const cachedItems = (await readFile(cachedFilePath, "utf8")).split(",");
|
|
971
|
-
this.totalItems[`${tableName}-*`]
|
|
979
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
980
|
+
this.totalItems[`${tableName}-*`] = cachedItems.length;
|
|
972
981
|
if (onlyLinesNumbers)
|
|
973
982
|
return cachedItems.map(Number);
|
|
974
983
|
return this.get(tableName, cachedItems
|
|
@@ -978,8 +987,10 @@ export default class Inibase {
|
|
|
978
987
|
let linesNumbers = null;
|
|
979
988
|
[RETURN, linesNumbers] = await this.applyCriteria(tableName, schema, options, where);
|
|
980
989
|
if (RETURN && linesNumbers) {
|
|
990
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
991
|
+
this.totalItems[`${tableName}-*`] = linesNumbers.size;
|
|
981
992
|
if (onlyLinesNumbers)
|
|
982
|
-
return
|
|
993
|
+
return Array.from(linesNumbers);
|
|
983
994
|
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]), alreadyExistsColumnsIDs = Utils.flattenSchema(schema)
|
|
984
995
|
.filter(({ key }) => alreadyExistsColumns.includes(key))
|
|
985
996
|
.map(({ id }) => id);
|
|
@@ -1028,7 +1039,8 @@ export default class Inibase {
|
|
|
1028
1039
|
.map(Number);
|
|
1029
1040
|
else {
|
|
1030
1041
|
lastId = Number(Object.keys((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), -1, "number", undefined, this.salt, true))?.[0] ?? 0));
|
|
1031
|
-
this.totalItems[`${tableName}-*`]
|
|
1042
|
+
if (!this.totalItems[`${tableName}-*`])
|
|
1043
|
+
this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
|
|
1032
1044
|
}
|
|
1033
1045
|
}
|
|
1034
1046
|
else
|
package/dist/utils.server.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
4
1
|
import { exec as execAsync, execFile as execFileAsync } from "node:child_process";
|
|
5
2
|
import { gunzip as gunzipAsync, gzip as gzipAsync } from "node:zlib";
|
|
6
3
|
import type { ComparisonOperator, Field, FieldType, Schema } from "./index.js";
|