inibase 1.0.0-rc.77 → 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 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 { basename, join } from "node:path";
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(basename(path))))
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(basename(path));
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
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import "dotenv/config";
3
2
  export interface Data {
4
3
  id?: number | string;
package/dist/index.js CHANGED
@@ -822,7 +822,7 @@ export default class Inibase {
822
822
  (Utils.isObject(where) && !Object.keys(where).length)))
823
823
  where = undefined;
824
824
  if (options.sort) {
825
- let sortArray, isLineNumbers = true, keepItems = [];
825
+ let sortArray, awkCommand = "";
826
826
  if (Utils.isObject(options.sort) && !Array.isArray(options.sort)) {
827
827
  // {name: "ASC", age: "DESC"}
828
828
  sortArray = Object.entries(options.sort).map(([key, value]) => [
@@ -840,16 +840,17 @@ export default class Inibase {
840
840
  cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
841
841
  if (where) {
842
842
  const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
843
- keepItems = Object.values((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
844
- isLineNumbers = false;
845
- if (!keepItems.length)
843
+ if (!lineNumbers.length)
846
844
  throw this.throwError("NO_RESULTS", tableName);
847
- keepItems = keepItems.slice((options.page - 1) * options.perPage, options.page * options.perPage);
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(" || ")}'`;
848
847
  }
849
- if (!keepItems.length)
850
- keepItems = Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
848
+ else
849
+ awkCommand = `awk '${Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
851
850
  index +
852
- 1);
851
+ 1)
852
+ .map((lineNumber) => `NR==${lineNumber}`)
853
+ .join(" || ")}'`;
853
854
  const filesPathes = [["id", true], ...sortArray].map((column) => join(tablePath, `${column[0]}${this.getFileExtension(tableName)}`));
854
855
  for await (const path of filesPathes.slice(1))
855
856
  if (!(await File.isExists(path)))
@@ -869,15 +870,11 @@ export default class Inibase {
869
870
  })
870
871
  .join(" ");
871
872
  const sortCommand = `sort ${sortColumns} -T=${join(tablePath, ".tmp")}`;
872
- // Construct the awk command to keep only the specified lines after sorting
873
- const awkCommand = isLineNumbers
874
- ? `awk '${keepItems.map((lineNumber) => `NR==${lineNumber}`).join(" || ")}'`
875
- : `awk '${keepItems.map((id) => `$1 ~ /^${id} */`).join(" || ")}'`;
876
873
  try {
877
874
  if (cacheKey)
878
875
  await File.lock(join(tablePath, ".tmp"), cacheKey);
879
876
  // Combine && Execute the commands synchronously
880
- const lines = (await UtilsServer.exec(this.tables[tableName].config.cache
877
+ let lines = (await UtilsServer.exec(this.tables[tableName].config.cache
881
878
  ? (await File.isExists(join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)))
882
879
  ? `${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
883
880
  : `${pasteCommand} | ${sortCommand} -o ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)} && ${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
@@ -886,6 +883,12 @@ export default class Inibase {
886
883
  })).stdout
887
884
  .trim()
888
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;
889
892
  // Parse the result and extract the specified lines
890
893
  const outputArray = lines.map((line) => {
891
894
  const splitedFileColumns = line.split("\t"); // Assuming tab-separated columns
@@ -916,11 +919,14 @@ export default class Inibase {
916
919
  RETURN = Object.values(await this.getItemsFromSchema(tableName, schema, Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
917
920
  index +
918
921
  1), options));
919
- if (await File.isExists(join(tablePath, ".cache", ".pagination")))
920
- this.totalItems[`${tableName}-*`] = Number((await readFile(join(tablePath, ".cache", ".pagination"), "utf8")).split(",")[1]);
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
+ }
921
926
  else {
922
927
  const lastId = Number(Object.keys((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), -1, "number", undefined, this.salt, true))?.[0] ?? 0));
923
- this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
928
+ if (!this.totalItems[`${tableName}-*`])
929
+ this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
924
930
  await writeFile(join(tablePath, ".cache", ".pagination"), `${lastId},${this.totalItems[`${tableName}-*`]}`);
925
931
  }
926
932
  }
@@ -930,12 +936,12 @@ export default class Inibase {
930
936
  let lineNumbers = where;
931
937
  if (!Array.isArray(lineNumbers))
932
938
  lineNumbers = [lineNumbers];
939
+ if (!this.totalItems[`${tableName}-*`])
940
+ this.totalItems[`${tableName}-*`] = lineNumbers.length;
933
941
  // useless
934
942
  if (onlyLinesNumbers)
935
943
  return lineNumbers;
936
944
  RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, lineNumbers, options)) ?? {});
937
- if (!this.totalItems[`${tableName}-*`])
938
- this.totalItems[`${tableName}-*`] = lineNumbers.length;
939
945
  if (RETURN?.length && !Array.isArray(where))
940
946
  RETURN = RETURN[0];
941
947
  }
@@ -947,6 +953,8 @@ export default class Inibase {
947
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);
948
954
  if (!lineNumbers)
949
955
  throw this.throwError("NO_RESULTS", tableName);
956
+ if (!this.totalItems[`${tableName}-*`])
957
+ this.totalItems[`${tableName}-*`] = countItems;
950
958
  if (onlyLinesNumbers)
951
959
  return Object.keys(lineNumbers).length
952
960
  ? Object.keys(lineNumbers).map(Number)
@@ -957,8 +965,6 @@ export default class Inibase {
957
965
  options.columns = undefined;
958
966
  }
959
967
  RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
960
- if (!this.totalItems[`${tableName}-*`])
961
- this.totalItems[`${tableName}-*`] = countItems;
962
968
  if (RETURN?.length && !Array.isArray(where))
963
969
  RETURN = RETURN[0];
964
970
  }
@@ -970,7 +976,8 @@ export default class Inibase {
970
976
  if (this.tables[tableName].config.cache &&
971
977
  (await File.isExists(cachedFilePath))) {
972
978
  const cachedItems = (await readFile(cachedFilePath, "utf8")).split(",");
973
- this.totalItems[`${tableName}-*`] = cachedItems.length;
979
+ if (!this.totalItems[`${tableName}-*`])
980
+ this.totalItems[`${tableName}-*`] = cachedItems.length;
974
981
  if (onlyLinesNumbers)
975
982
  return cachedItems.map(Number);
976
983
  return this.get(tableName, cachedItems
@@ -980,8 +987,10 @@ export default class Inibase {
980
987
  let linesNumbers = null;
981
988
  [RETURN, linesNumbers] = await this.applyCriteria(tableName, schema, options, where);
982
989
  if (RETURN && linesNumbers) {
990
+ if (!this.totalItems[`${tableName}-*`])
991
+ this.totalItems[`${tableName}-*`] = linesNumbers.size;
983
992
  if (onlyLinesNumbers)
984
- return Object.keys(RETURN).map(Number);
993
+ return Array.from(linesNumbers);
985
994
  const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]), alreadyExistsColumnsIDs = Utils.flattenSchema(schema)
986
995
  .filter(({ key }) => alreadyExistsColumns.includes(key))
987
996
  .map(({ id }) => id);
@@ -1030,7 +1039,8 @@ export default class Inibase {
1030
1039
  .map(Number);
1031
1040
  else {
1032
1041
  lastId = Number(Object.keys((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), -1, "number", undefined, this.salt, true))?.[0] ?? 0));
1033
- this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
1042
+ if (!this.totalItems[`${tableName}-*`])
1043
+ this.totalItems[`${tableName}-*`] = await File.count(join(tablePath, `id${this.getFileExtension(tableName)}`));
1034
1044
  }
1035
1045
  }
1036
1046
  else
@@ -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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.77",
3
+ "version": "1.0.0-rc.78",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Karim Amahtil",