inibase 1.2.8 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/file.d.ts CHANGED
@@ -111,34 +111,7 @@ export declare const remove: (filePath: string, linesToDelete: number | number[]
111
111
  export declare const search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | null | (string | number | boolean | null)[], logicalOperator?: "and" | "or", searchIn?: Set<number>, field?: Field & {
112
112
  databasePath?: string;
113
113
  }, limit?: number, offset?: number, readWholeFile?: boolean) => Promise<[Record<number, string | number | boolean | null | (string | number | boolean | null)[]> | null, number, Set<number> | null]>;
114
- /**
115
- * Asynchronously calculates the sum of numerical values from specified lines in a file.
116
- *
117
- * @param filePath - Path of the file to read.
118
- * @param lineNumbers - Optional specific line number(s) to include in the sum. If not provided, sums all lines.
119
- * @returns Promise<number>. The sum of numerical values from the specified lines.
120
- *
121
- * Note: Decodes each line as a number using the 'decode' function. Non-numeric lines contribute 0 to the sum.
122
- */
123
- export declare const sum: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
124
- /**
125
- * Asynchronously finds the maximum numerical value from specified lines in a file.
126
- *
127
- * @param filePath - Path of the file to read.
128
- * @param lineNumbers - Optional specific line number(s) to consider for finding the maximum value. If not provided, considers all lines.
129
- * @returns Promise<number>. The maximum numerical value found in the specified lines.
130
- *
131
- * Note: Decodes each line as a number using the 'decode' function. Considers only numerical values for determining the maximum.
132
- */
133
- export declare const max: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
134
- /**
135
- * Asynchronously finds the minimum numerical value from specified lines in a file.
136
- *
137
- * @param filePath - Path of the file to read.
138
- * @param lineNumbers - Optional specific line number(s) to consider for finding the minimum value. If not provided, considers all lines.
139
- * @returns Promise<number>. The minimum numerical value found in the specified lines.
140
- *
141
- * Note: Decodes each line as a number using the 'decode' function. Considers only numerical values for determining the minimum.
142
- */
143
- export declare const min: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
114
+ export declare const sum: (fp: string, ln?: number | number[]) => Promise<number>;
115
+ export declare const min: (fp: string, ln?: number | number[]) => Promise<number>;
116
+ export declare const max: (fp: string, ln?: number | number[]) => Promise<number>;
144
117
  export declare const getFileDate: (path: string) => Promise<Date>;
package/dist/file.js CHANGED
@@ -581,127 +581,66 @@ export const search = async (filePath, operator, comparedAtValue, logicalOperato
581
581
  }
582
582
  };
583
583
  /**
584
- * Asynchronously calculates the sum of numerical values from specified lines in a file.
584
+ * Reads the file once and returns either the sum, min or max of the
585
+ * (optionally-selected) numeric lines.
585
586
  *
586
- * @param filePath - Path of the file to read.
587
- * @param lineNumbers - Optional specific line number(s) to include in the sum. If not provided, sums all lines.
588
- * @returns Promise<number>. The sum of numerical values from the specified lines.
587
+ * @param filePath Absolute path of the column file (may be .gz-compressed).
588
+ * @param wanted Metric to compute: "sum" (default), "min" or "max".
589
+ * @param lineNumbers Specific line-number(s) to restrict the scan to.
589
590
  *
590
- * Note: Decodes each line as a number using the 'decode' function. Non-numeric lines contribute 0 to the sum.
591
+ * @returns Promise<number> The requested metric, or 0 if no numeric value found.
591
592
  */
592
- export const sum = async (filePath, lineNumbers) => {
593
+ async function reduceNumbers(filePath, wanted = "sum", lineNumbers) {
594
+ /* optional subset */
595
+ const filter = lineNumbers
596
+ ? new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers])
597
+ : null;
598
+ /* running aggregators */
593
599
  let sum = 0;
594
- let fileHandle = null;
600
+ let min = Infinity;
601
+ let max = -Infinity;
602
+ let processed = 0; // count of numeric lines we actually used
603
+ let seen = 0; // count of filtered lines we have visited
604
+ let line = 0;
605
+ const fh = await open(filePath, "r");
606
+ const rl = createReadLineInternface(filePath, fh);
595
607
  try {
596
- fileHandle = await open(filePath, "r");
597
- const rl = createReadLineInternface(filePath, fileHandle);
598
- if (lineNumbers) {
599
- let linesCount = 0;
600
- const lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
601
- for await (const line of rl) {
602
- linesCount++;
603
- if (!lineNumbersArray.has(linesCount))
604
- continue;
605
- sum += +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
606
- lineNumbersArray.delete(linesCount);
607
- if (!lineNumbersArray.size)
608
- break;
609
- }
610
- }
611
- else
612
- for await (const line of rl)
613
- sum += +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
614
- return sum;
615
- }
616
- finally {
617
- await fileHandle?.close();
618
- }
619
- };
620
- /**
621
- * Asynchronously finds the maximum numerical value from specified lines in a file.
622
- *
623
- * @param filePath - Path of the file to read.
624
- * @param lineNumbers - Optional specific line number(s) to consider for finding the maximum value. If not provided, considers all lines.
625
- * @returns Promise<number>. The maximum numerical value found in the specified lines.
626
- *
627
- * Note: Decodes each line as a number using the 'decode' function. Considers only numerical values for determining the maximum.
628
- */
629
- export const max = async (filePath, lineNumbers) => {
630
- let max = 0;
631
- let fileHandle = null;
632
- let rl = null;
633
- try {
634
- fileHandle = await open(filePath, "r");
635
- rl = createReadLineInternface(filePath, fileHandle);
636
- if (lineNumbers) {
637
- let linesCount = 0;
638
- const lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
639
- for await (const line of rl) {
640
- linesCount++;
641
- if (!lineNumbersArray.has(linesCount))
642
- continue;
643
- const lineContentNum = +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
644
- if (lineContentNum > max)
645
- max = lineContentNum;
646
- lineNumbersArray.delete(linesCount);
647
- if (!lineNumbersArray.size)
648
- break;
608
+ for await (const txt of rl) {
609
+ line++;
610
+ /* skip unwanted lines */
611
+ if (filter && !filter.has(line))
612
+ continue;
613
+ const num = Number(decode(txt, { key: "BLABLA", type: "number" })); // ← your existing decode()
614
+ if (isNaN(num))
615
+ continue;
616
+ processed++;
617
+ if (wanted === "sum") {
618
+ sum += num;
649
619
  }
650
- }
651
- else
652
- for await (const line of rl) {
653
- const lineContentNum = +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
654
- if (lineContentNum > max)
655
- max = lineContentNum;
620
+ else if (wanted === "min") {
621
+ if (num < min)
622
+ min = num;
656
623
  }
657
- return max;
658
- }
659
- finally {
660
- await fileHandle?.close();
661
- }
662
- };
663
- /**
664
- * Asynchronously finds the minimum numerical value from specified lines in a file.
665
- *
666
- * @param filePath - Path of the file to read.
667
- * @param lineNumbers - Optional specific line number(s) to consider for finding the minimum value. If not provided, considers all lines.
668
- * @returns Promise<number>. The minimum numerical value found in the specified lines.
669
- *
670
- * Note: Decodes each line as a number using the 'decode' function. Considers only numerical values for determining the minimum.
671
- */
672
- export const min = async (filePath, lineNumbers) => {
673
- let min = 0;
674
- let fileHandle = null;
675
- try {
676
- fileHandle = await open(filePath, "r");
677
- const rl = createReadLineInternface(filePath, fileHandle);
678
- if (lineNumbers) {
679
- let linesCount = 0;
680
- const lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
681
- for await (const line of rl) {
682
- linesCount++;
683
- if (!lineNumbersArray.has(linesCount))
684
- continue;
685
- const lineContentNum = +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
686
- if (lineContentNum < min)
687
- min = lineContentNum;
688
- lineNumbersArray.delete(linesCount);
689
- if (!lineNumbersArray.size)
690
- break;
624
+ else if (wanted === "max") {
625
+ if (num > max)
626
+ max = num;
691
627
  }
628
+ /* early break when we have consumed all requested lines */
629
+ if (filter && ++seen === filter.size)
630
+ break;
692
631
  }
693
- else
694
- for await (const line of rl) {
695
- const lineContentNum = +(decode(line, { key: "BLABLA", type: "number" }) ?? 0);
696
- if (lineContentNum < min)
697
- min = lineContentNum;
698
- }
699
- return min;
700
632
  }
701
633
  finally {
702
- await fileHandle?.close();
634
+ await fh.close();
703
635
  }
704
- };
636
+ if (processed === 0)
637
+ return 0; // nothing numeric found
638
+ return wanted === "sum" ? sum : wanted === "min" ? min : max;
639
+ }
640
+ /* Optional convenience wrappers (signatures unchanged) */
641
+ export const sum = (fp, ln) => reduceNumbers(fp, "sum", ln);
642
+ export const min = (fp, ln) => reduceNumbers(fp, "min", ln);
643
+ export const max = (fp, ln) => reduceNumbers(fp, "max", ln);
705
644
  export const getFileDate = (path) => stat(path)
706
645
  .then((s) => s.mtime || s.birthtime)
707
646
  .catch(() => new Date());
package/dist/index.d.ts CHANGED
@@ -122,7 +122,6 @@ export default class Inibase {
122
122
  private processObjectField;
123
123
  private isTableField;
124
124
  private processTableField;
125
- private _setNestedKey;
126
125
  private applyCriteria;
127
126
  private _filterSchemaByColumns;
128
127
  /**
package/dist/index.js CHANGED
@@ -927,141 +927,124 @@ export default class Inibase {
927
927
  }
928
928
  }
929
929
  }
930
- _setNestedKey(obj, path, value) {
931
- const keys = path.split(".");
932
- let current = obj;
933
- keys.forEach((key, index) => {
934
- if (index === keys.length - 1) {
935
- current[key] = value; // Set the value at the last key
936
- }
937
- else {
938
- current[key] = current[key] || {}; // Ensure the object structure exists
939
- current = current[key];
940
- }
941
- });
942
- }
943
930
  async applyCriteria(tableName, options, criteria, allTrue, searchIn) {
944
931
  const tablePath = join(this.databasePath, tableName);
945
- let RETURN = {};
946
- if (!criteria)
947
- return [null, null];
932
+ /** result container – we mutate rows in-place instead of deep-merging */
933
+ const RETURN = {};
934
+ /* ---------- fast exit ---------- */
935
+ if (!criteria || Object.keys(criteria).length === 0)
936
+ return null;
937
+ /* ---------- split top-level logical groups ---------- */
948
938
  const criteriaAND = criteria.and;
939
+ const criteriaOR = criteria.or;
949
940
  if (criteriaAND)
950
941
  delete criteria.and;
951
- const criteriaOR = criteria.or;
952
942
  if (criteriaOR)
953
943
  delete criteria.or;
954
- if (Object.keys(criteria).length > 0) {
944
+ /** cache table schema once – Utils.getField() is cheap but we call it a lot */
945
+ const schema = globalConfig[this.databasePath].tables.get(tableName).schema;
946
+ /* ---------- MAIN LOOP (top-level criteria only) ---------- */
947
+ if (Object.keys(criteria).length) {
955
948
  if (allTrue === undefined)
956
949
  allTrue = true;
957
- criteria = Utils.toDotNotation(criteria, ["or", "and"]);
958
- let index = -1;
959
- for await (const [key, value] of Object.entries(criteria)) {
960
- const field = Utils.getField(key, globalConfig[this.databasePath].tables.get(tableName).schema);
950
+ for (const [key, rawValue] of Object.entries(criteria)) {
951
+ /* bail early if no candidates left for an “AND” chain */
952
+ if (allTrue && searchIn && searchIn.size === 0)
953
+ return null;
954
+ const field = Utils.getField(key, schema);
961
955
  if (!field)
962
956
  continue;
963
- index++;
964
- let searchOperator = undefined;
965
- let searchComparedAtValue = undefined;
966
- let searchLogicalOperator = undefined;
957
+ let value = rawValue;
958
+ /* ----- resolve relational sub-queries ----- */
959
+ if (field.table && Utils.isObject(value)) {
960
+ const rel = await this.get(field.table, value, {
961
+ columns: "id",
962
+ });
963
+ value = rel?.length ? `[]${rel.map(({ id }) => id)}` : undefined; // ⟵ no match → abort whole AND-chain
964
+ if (value === undefined && allTrue)
965
+ return null;
966
+ }
967
+ /* ----- determine operator / compare value ----- */
968
+ let searchOperator;
969
+ let searchComparedAtValue;
970
+ let searchLogicalOperator;
967
971
  if (Utils.isObject(value)) {
968
- if (value?.or &&
969
- Array.isArray(value?.or)) {
970
- const searchCriteria = (value?.or)
971
- .map((single_or) => typeof single_or === "string"
972
- ? Utils.FormatObjectCriteriaValue(single_or)
973
- : ["=", single_or])
974
- .filter((a) => a);
975
- if (searchCriteria.length > 0) {
976
- searchOperator = searchCriteria.map((single_or) => single_or[0]);
977
- searchComparedAtValue = searchCriteria.map((single_or) => single_or[1]);
978
- searchLogicalOperator = "or";
979
- }
980
- delete value.or;
981
- }
982
- if (value?.and &&
983
- Array.isArray(value?.and)) {
984
- const searchCriteria = (value?.and)
985
- .map((single_and) => typeof single_and === "string"
986
- ? Utils.FormatObjectCriteriaValue(single_and)
987
- : ["=", single_and])
988
- .filter((a) => a);
989
- if (searchCriteria.length > 0) {
990
- searchOperator = searchCriteria.map((single_and) => single_and[0]);
991
- searchComparedAtValue = searchCriteria.map((single_and) => single_and[1]);
992
- searchLogicalOperator = "and";
972
+ /* nested object with .and / .or inside */
973
+ const nestedAnd = value.and;
974
+ const nestedOr = value.or;
975
+ if (nestedAnd || nestedOr) {
976
+ const logicalChild = nestedAnd ?? nestedOr;
977
+ const logic = nestedAnd ? "and" : "or";
978
+ const crit = Object.entries(logicalChild)
979
+ .map((item) => typeof item[1] === "string"
980
+ ? Utils.FormatObjectCriteriaValue(item[1])
981
+ : ["=", item[1]])
982
+ .filter(Boolean);
983
+ if (crit.length) {
984
+ searchOperator = crit.map((c) => c[0]);
985
+ searchComparedAtValue = crit.map((c) => c[1]);
986
+ searchLogicalOperator = logic;
993
987
  }
994
- delete value.and;
995
988
  }
996
989
  }
997
990
  else if (Array.isArray(value)) {
998
- const searchCriteria = value
999
- .map((single) => typeof single === "string"
1000
- ? Utils.FormatObjectCriteriaValue(single)
1001
- : ["=", single])
1002
- .filter((a) => a);
1003
- if (searchCriteria.length > 0) {
1004
- searchOperator = searchCriteria.map((single) => single[0]);
1005
- searchComparedAtValue = searchCriteria.map((single) => single[1]);
1006
- searchLogicalOperator = "and";
1007
- }
991
+ const crit = value
992
+ .map((v) => typeof v === "string"
993
+ ? Utils.FormatObjectCriteriaValue(v)
994
+ : ["=", v])
995
+ .filter(Boolean);
996
+ searchOperator = crit.map((c) => c[0]);
997
+ searchComparedAtValue = crit.map((c) => c[1]);
998
+ searchLogicalOperator = "or";
1008
999
  }
1009
1000
  else if (typeof value === "string") {
1010
- const ComparisonOperatorValue = Utils.FormatObjectCriteriaValue(value);
1011
- if (ComparisonOperatorValue) {
1012
- searchOperator = ComparisonOperatorValue[0];
1013
- searchComparedAtValue = ComparisonOperatorValue[1];
1014
- }
1001
+ const [op, val] = Utils.FormatObjectCriteriaValue(value);
1002
+ searchOperator = op;
1003
+ searchComparedAtValue = val;
1015
1004
  }
1016
1005
  else {
1017
1006
  searchOperator = "=";
1018
1007
  searchComparedAtValue = value;
1019
1008
  }
1020
- const [searchResult, totalLines, linesNumbers] = await File.search(join(tablePath, `${key}${this.getFileExtension(tableName)}`), searchOperator ?? "=", searchComparedAtValue ?? null, searchLogicalOperator, searchIn, {
1009
+ /* ---------- disk search ---------- */
1010
+ const [hitRows, totalLines, lineSet] = await File.search(join(tablePath, `${key}${this.getFileExtension(tableName)}`), searchOperator ?? "=", searchComparedAtValue ?? null, searchLogicalOperator, searchIn, {
1021
1011
  ...field,
1022
1012
  databasePath: this.databasePath,
1023
1013
  table: field.table ?? tableName,
1024
1014
  }, options.perPage, (options.page - 1) * options.perPage +
1025
1015
  (options.page > 1 ? 1 : 0), true);
1026
- if (searchResult) {
1027
- const formatedSearchResult = Object.fromEntries(Object.entries(searchResult).map(([id, value]) => {
1028
- const nestedObj = {};
1029
- this._setNestedKey(nestedObj, key, value);
1030
- return [id, nestedObj];
1031
- }));
1032
- RETURN = allTrue
1033
- ? formatedSearchResult
1034
- : Utils.deepMerge(RETURN, formatedSearchResult);
1035
- this.totalItems.set(`${tableName}-${key}`, totalLines);
1036
- if (linesNumbers?.size && allTrue)
1037
- searchIn = linesNumbers;
1016
+ if (!hitRows) {
1017
+ if (allTrue)
1018
+ return null; // AND-chain broken
1019
+ continue; // OR-chain: just skip
1038
1020
  }
1039
- else if (allTrue)
1040
- return null;
1021
+ /* ---------- map rows into RETURN without deep-merge ---------- */
1022
+ for (const [lnStr, val] of Object.entries(hitRows)) {
1023
+ const ln = +lnStr;
1024
+ const row = (RETURN[ln] ??= {});
1025
+ row[key] = val;
1026
+ }
1027
+ this.totalItems.set(`${tableName}-${key}`, totalLines);
1028
+ /* shrink search domain for next AND condition */
1029
+ if (lineSet?.size && allTrue)
1030
+ searchIn = lineSet;
1041
1031
  }
1042
1032
  }
1033
+ /* ---------- process nested .and / .or recursively (unchanged) ---------- */
1043
1034
  if (criteriaAND && Utils.isObject(criteriaAND)) {
1044
- const searchResult = await this.applyCriteria(tableName, options, criteriaAND, true, searchIn);
1045
- if (searchResult) {
1046
- RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).filter(([_k, v], _i) => Object.keys(v).filter((key) => Object.keys(criteriaAND).includes(key)).length)));
1047
- }
1048
- else
1035
+ const res = await this.applyCriteria(tableName, options, criteriaAND, true, searchIn);
1036
+ if (!res)
1049
1037
  return null;
1038
+ for (const [lnStr, data] of Object.entries(res))
1039
+ (RETURN[+lnStr] ??= {}), Object.assign(RETURN[+lnStr], data);
1050
1040
  }
1051
1041
  if (criteriaOR && Utils.isObject(criteriaOR)) {
1052
- const searchResult = await this.applyCriteria(tableName, options, criteriaOR, false, searchIn);
1053
- if (searchResult) {
1054
- RETURN = Utils.deepMerge(RETURN, searchResult);
1055
- if (!Object.keys(RETURN).length)
1056
- RETURN = {};
1057
- RETURN = Object.fromEntries(Object.entries(RETURN).filter(([_index, item]) => Object.keys(item).filter((key) => Object.keys(criteriaOR).includes(key) ||
1058
- Object.keys(criteriaOR).some((criteriaKey) => criteriaKey.startsWith(`${key}.`))).length));
1059
- if (!Object.keys(RETURN).length)
1060
- RETURN = {};
1061
- }
1062
- else
1063
- RETURN = {};
1042
+ const res = await this.applyCriteria(tableName, options, criteriaOR, false, undefined);
1043
+ if (res)
1044
+ for (const [lnStr, data] of Object.entries(res))
1045
+ (RETURN[+lnStr] ??= {}), Object.assign(RETURN[+lnStr], data);
1064
1046
  }
1047
+ /* ---------- final answer ---------- */
1065
1048
  return Object.keys(RETURN).length ? RETURN : null;
1066
1049
  }
1067
1050
  _filterSchemaByColumns(schema, columns) {
package/dist/utils.js CHANGED
@@ -427,8 +427,11 @@ export const FormatObjectCriteriaValue = (value) => {
427
427
  case "[":
428
428
  return value[1] === "]"
429
429
  ? [
430
- value.slice(0, 2),
431
- value.slice(2).toString().split(","),
430
+ "[]",
431
+ value.slice(2)
432
+ .toString()
433
+ .split(",")
434
+ .map((v) => (isNumber(v) ? Number(v) : v)),
432
435
  ]
433
436
  : ["[]", value.slice(1)];
434
437
  case "!":
@@ -439,23 +442,20 @@ export const FormatObjectCriteriaValue = (value) => {
439
442
  ]
440
443
  : value[1] === "["
441
444
  ? [
442
- value.slice(0, 3),
443
- value.slice(3),
445
+ "![]",
446
+ value.slice(3)
447
+ .toString()
448
+ .split(",")
449
+ .map((v) => (isNumber(v) ? Number(v) : v)),
444
450
  ]
445
451
  : [
446
452
  `${value.slice(0, 1)}=`,
447
453
  value.slice(1),
448
454
  ];
449
455
  case "=":
450
- return [
451
- value.slice(0, 1),
452
- value.slice(1),
453
- ];
456
+ return ["=", value.slice(1)];
454
457
  case "*":
455
- return [
456
- value.slice(0, 1),
457
- value.slice(1),
458
- ];
458
+ return ["*", value.slice(1)];
459
459
  default:
460
460
  return ["=", value];
461
461
  }
@@ -95,10 +95,10 @@ export const addIdToSchema = (schema, startWithID) => {
95
95
  function _addIdToField(field) {
96
96
  if (!field.id) {
97
97
  startWithID.value++;
98
- field.id = encodeID(startWithID.value);
98
+ field.id = startWithID.value;
99
99
  }
100
- else
101
- field.id = isValidID(field.id) ? decodeID(field.id) : encodeID(field.id);
100
+ else if (isValidID(field.id))
101
+ field.id = decodeID(field.id);
102
102
  if ((field.type === "array" || field.type === "object") &&
103
103
  isArrayOfObjects(field.children))
104
104
  field.children = _addIdToSchema(field.children);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Karim Amahtil",
@@ -69,22 +69,24 @@
69
69
  },
70
70
  "devDependencies": {
71
71
  "@biomejs/biome": "1.9.4",
72
- "@types/bun": "^1.1.10",
73
- "@types/node": "^22.7.4",
74
- "lefthook": "^1.10.1",
75
- "tinybench": "^3.0.7",
76
- "typescript": "^5.7.2"
72
+ "@types/bun": "^1.2.10",
73
+ "@types/node": "^22.15.2",
74
+ "lefthook": "^1.11.11",
75
+ "tinybench": "^4.0.1",
76
+ "tsx": "^4.19.3",
77
+ "typescript": "^5.8.3"
77
78
  },
78
79
  "dependencies": {
79
- "dotenv": "^16.4.5",
80
+ "dotenv": "^16.5.0",
80
81
  "inison": "^2.0.1",
81
82
  "re2": "^1.21.4"
82
83
  },
83
84
  "scripts": {
84
- "prepublish": "npx -q tsc",
85
- "build": "npx -q tsc",
85
+ "prepublish": "tsc",
86
+ "prebuild": "biome check --write src",
87
+ "build": "tsc",
86
88
  "benchmark": "./benchmark/run.js",
87
- "test": "npx -q tsx ./tests/inibase.test.ts",
88
- "test:utils": "npx -q tsx ./tests/utils.test.ts"
89
+ "test": "tsx ./tests/inibase.test.ts",
90
+ "test:utils": "tsx ./tests/utils.test.ts"
89
91
  }
90
92
  }