inibase 1.0.0-rc.28 → 1.0.0-rc.29

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![npmjs](https://img.shields.io/npm/dm/inibase.svg?style=flat)](https://www.npmjs.org/package/inibase) [![License](https://img.shields.io/github/license/inicontent/inibase.svg?style=flat&colorA=18181B&colorB=28CF8D)](./LICENSE) [![Activity](https://img.shields.io/github/commit-activity/m/inicontent/inibase)](https://github.com/inicontent/inibase/pulse) [![GitHub stars](https://img.shields.io/github/stars/inicontent/inibase?style=social)](https://github.com/inicontent/inibase)
6
6
 
7
- > A file-based & memory-efficient, serverless relational database management system :fire:
7
+ > A file-based & memory-efficient, serverless, ACID compliant, relational database management system :fire:
8
8
 
9
9
  ## Features
10
10
 
@@ -74,6 +74,8 @@ To simplify the idea, each database has tables, each table has columns, each col
74
74
  | PUT | 33 ms (10.29 mb) | 312 ms (11.06 mb) | 3539 ms (14.87 mb) |
75
75
  | DELETE | 134 ms (13.50 mb) | 1224 ms (16.57 mb) | 7339 ms (11.46 mb) |
76
76
 
77
+ Ps: Testing by default with `user` table, with username, email, password fields _so results include password encryption process_
78
+
77
79
 
78
80
  ## Roadmap
79
81
 
package/dist/file.js CHANGED
@@ -286,7 +286,7 @@ export async function get(filePath, lineNumbers, fieldType, fieldChildrenType, s
286
286
  * Note: If the file doesn't exist and replacements is an object, it creates a new file with the specified replacements.
287
287
  */
288
288
  export const replace = async (filePath, replacements) => {
289
- const fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/${Date.now()}-$1`);
289
+ const fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/$1`);
290
290
  if (await isExists(filePath)) {
291
291
  let fileHandle, fileTempHandle, rl;
292
292
  try {
@@ -339,7 +339,7 @@ export const replace = async (filePath, replacements) => {
339
339
  *
340
340
  */
341
341
  export const append = async (filePath, data) => {
342
- const fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/${Date.now()}-$1`);
342
+ const fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/$1`);
343
343
  if (await isExists(filePath)) {
344
344
  let fileHandle, fileTempHandle, rl;
345
345
  try {
@@ -366,7 +366,7 @@ export const append = async (filePath, data) => {
366
366
  }
367
367
  }
368
368
  else
369
- await write(fileTempPath, `${Array.isArray(data) ? data.join("\n") : data}\n`);
369
+ await write(fileTempPath, `${Array.isArray(data) ? data.join("\n") : data}\n`, undefined);
370
370
  return [fileTempPath, filePath];
371
371
  };
372
372
  /**
@@ -379,16 +379,24 @@ export const append = async (filePath, data) => {
379
379
  * Note: Creates a temporary file during the process and replaces the original file with it after removing lines.
380
380
  */
381
381
  export const remove = async (filePath, linesToDelete) => {
382
- let linesCount = 0;
383
- const fileHandle = await open(filePath, "r"), fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/${Date.now()}-$1`), fileTempHandle = await open(fileTempPath, "w"), linesToDeleteArray = new Set(Array.isArray(linesToDelete)
382
+ let linesCount = 0, deletedCount = 0;
383
+ const fileHandle = await open(filePath, "r"), fileTempPath = filePath.replace(/([^/]+)\/?$/, `.tmp/$1`), fileTempHandle = await open(fileTempPath, "w"), linesToDeleteArray = new Set(Array.isArray(linesToDelete)
384
384
  ? linesToDelete.map(Number)
385
385
  : [Number(linesToDelete)]), rl = readLineInternface(fileHandle);
386
386
  await _pipeline(rl, fileTempHandle.createWriteStream(), new Transform({
387
387
  transform(line, encoding, callback) {
388
388
  linesCount++;
389
- return !linesToDeleteArray.has(linesCount)
390
- ? callback(null, `${line}\n`)
391
- : callback();
389
+ if (linesToDeleteArray.has(linesCount)) {
390
+ deletedCount++;
391
+ return callback();
392
+ }
393
+ else
394
+ return callback(null, `${line}\n`);
395
+ },
396
+ final(callback) {
397
+ if (deletedCount === linesCount)
398
+ this.push("\n");
399
+ return callback();
392
400
  },
393
401
  }));
394
402
  await fileTempHandle.close();
package/dist/index.d.ts CHANGED
@@ -75,12 +75,11 @@ export default class Inibase {
75
75
  private getDefaultValue;
76
76
  private joinPathesContents;
77
77
  private getItemsFromSchema;
78
- private FormatObjectCriteriaValue;
79
78
  private applyCriteria;
80
79
  private _filterSchemaByColumns;
81
80
  get(tableName: string, where?: string | number | (string | number)[] | Criteria | undefined, options?: Options | undefined, onlyOne?: true, onlyLinesNumbers?: undefined, tableSchema?: Schema): Promise<Data | null>;
82
81
  get(tableName: string, where?: string | number | (string | number)[] | Criteria | undefined, options?: Options | undefined, onlyOne?: boolean | undefined, onlyLinesNumbers?: true, tableSchema?: Schema): Promise<number[] | null>;
83
- post(tableName: string, data: Data | Data[], options?: Options, returnPostedData?: false): Promise<void | null>;
82
+ post(tableName: string, data: Data | Data[], options?: Options, returnPostedData?: boolean): Promise<void | null>;
84
83
  post(tableName: string, data: Data, options: Options | undefined, returnPostedData: true): Promise<Data | null>;
85
84
  post(tableName: string, data: Data[], options: Options | undefined, returnPostedData: true): Promise<Data[] | null>;
86
85
  put(tableName: string, data: Data | Data[], where?: number | string | (number | string)[] | Criteria, options?: Options, returnPostedData?: false): Promise<void | null>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { unlink, rename, mkdir, readdir } from "node:fs/promises";
1
+ import { unlink, rename, mkdir, readdir, open } from "node:fs/promises";
2
2
  import { existsSync, appendFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { cpus } from "node:os";
@@ -87,9 +87,10 @@ export default class Inibase {
87
87
  return RETURN;
88
88
  }, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath((await this.getTableSchema(tableName)) ?? []), schemaToIdsPath(schema));
89
89
  if (replaceOldPathes)
90
- for await (const [oldPath, newPath] of Object.entries(replaceOldPathes))
90
+ await Promise.all(Object.entries(replaceOldPathes).map(async ([oldPath, newPath]) => {
91
91
  if (await File.isExists(join(TablePath, oldPath)))
92
92
  await rename(join(TablePath, oldPath), join(TablePath, newPath));
93
+ }));
93
94
  }
94
95
  await File.write(join(TablePath, "schema.json"), JSON.stringify(decodeIdFromSchema(schema), null, 2), true);
95
96
  }
@@ -302,7 +303,7 @@ export default class Inibase {
302
303
  async getItemsFromSchema(tableName, schema, linesNumber, options, prefix) {
303
304
  const path = join(this.folder, this.database, tableName);
304
305
  let RETURN = {};
305
- for await (const field of schema) {
306
+ await Promise.all(schema.map(async (field) => {
306
307
  if ((field.type === "array" ||
307
308
  (Array.isArray(field.type) && field.type.includes("array"))) &&
308
309
  field.children) {
@@ -322,14 +323,17 @@ export default class Inibase {
322
323
  if (Utils.isObject(item[child_field.key])) {
323
324
  Object.entries(item[child_field.key]).forEach(([key, value]) => {
324
325
  if (!Utils.isArrayOfArrays(value))
325
- value = value.map((_value) => child_field.type === "array" ? [[_value]] : [_value]);
326
+ value = value.map((_value) => child_field.type === "array"
327
+ ? [[_value]]
328
+ : [_value]);
326
329
  for (let _i = 0; _i < value.length; _i++) {
327
330
  if (Utils.isArrayOfNulls(value[_i]))
328
331
  continue;
329
332
  if (!RETURN[index][field.key][_i])
330
333
  RETURN[index][field.key][_i] = {};
331
334
  if (!RETURN[index][field.key][_i][child_field.key])
332
- RETURN[index][field.key][_i][child_field.key] = [];
335
+ RETURN[index][field.key][_i][child_field.key] =
336
+ [];
333
337
  value[_i].forEach((_element, _index) => {
334
338
  if (!RETURN[index][field.key][_i][child_field.key][_index])
335
339
  RETURN[index][field.key][_i][child_field.key][_index] = {};
@@ -390,13 +394,13 @@ export default class Inibase {
390
394
  .map((column) => column.replace(`${field.key}.`, ""));
391
395
  const items = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field.children, this.salt);
392
396
  if (items)
393
- for await (const [index, item] of Object.entries(items)) {
397
+ await Promise.all(Object.entries(items).map(async ([index, item]) => {
394
398
  if (!RETURN[index])
395
399
  RETURN[index] = {};
396
400
  RETURN[index][field.key] = item
397
401
  ? await this.get(field.key, item, options)
398
402
  : this.getDefaultValue(field);
399
- }
403
+ }));
400
404
  }
401
405
  else if (await File.isExists(join(path, (prefix ?? "") + field.key + ".inib"))) {
402
406
  const items = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field?.children, this.salt);
@@ -455,63 +459,9 @@ export default class Inibase {
455
459
  { ...data, [field.key]: this.getDefaultValue(field) },
456
460
  ]));
457
461
  }
458
- }
462
+ }));
459
463
  return RETURN;
460
464
  }
461
- FormatObjectCriteriaValue(value, isParentArray = false) {
462
- switch (value[0]) {
463
- case ">":
464
- case "<":
465
- return value[1] === "="
466
- ? [
467
- value.slice(0, 2),
468
- value.slice(2),
469
- ]
470
- : [
471
- value.slice(0, 1),
472
- value.slice(1),
473
- ];
474
- case "[":
475
- return value[1] === "]"
476
- ? [
477
- value.slice(0, 2),
478
- value.slice(2).toString().split(","),
479
- ]
480
- : ["[]", value.slice(1)];
481
- case "!":
482
- return ["=", "*"].includes(value[1])
483
- ? [
484
- value.slice(0, 2),
485
- value.slice(2),
486
- ]
487
- : value[1] === "["
488
- ? [
489
- value.slice(0, 3),
490
- value.slice(3),
491
- ]
492
- : [
493
- (value.slice(0, 1) + "="),
494
- value.slice(1),
495
- ];
496
- case "=":
497
- return isParentArray
498
- ? [
499
- value.slice(0, 1),
500
- value.slice(1),
501
- ]
502
- : [
503
- value.slice(0, 1),
504
- (value.slice(1) + ","),
505
- ];
506
- case "*":
507
- return [
508
- value.slice(0, 1),
509
- value.slice(1),
510
- ];
511
- default:
512
- return ["=", value];
513
- }
514
- }
515
465
  async applyCriteria(tableName, schema, options, criteria, allTrue) {
516
466
  let RETURN = {}, RETURN_LineNumbers = null;
517
467
  if (!criteria)
@@ -547,7 +497,7 @@ export default class Inibase {
547
497
  Array.isArray(value?.or)) {
548
498
  const searchCriteria = (value?.or)
549
499
  .map((single_or) => typeof single_or === "string"
550
- ? this.FormatObjectCriteriaValue(single_or)
500
+ ? Utils.FormatObjectCriteriaValue(single_or)
551
501
  : ["=", single_or])
552
502
  .filter((a) => a);
553
503
  if (searchCriteria.length > 0) {
@@ -561,7 +511,7 @@ export default class Inibase {
561
511
  Array.isArray(value?.and)) {
562
512
  const searchCriteria = (value?.and)
563
513
  .map((single_and) => typeof single_and === "string"
564
- ? this.FormatObjectCriteriaValue(single_and)
514
+ ? Utils.FormatObjectCriteriaValue(single_and)
565
515
  : ["=", single_and])
566
516
  .filter((a) => a);
567
517
  if (searchCriteria.length > 0) {
@@ -575,7 +525,7 @@ export default class Inibase {
575
525
  else if (Array.isArray(value)) {
576
526
  const searchCriteria = value
577
527
  .map((single) => typeof single === "string"
578
- ? this.FormatObjectCriteriaValue(single)
528
+ ? Utils.FormatObjectCriteriaValue(single)
579
529
  : ["=", single])
580
530
  .filter((a) => a);
581
531
  if (searchCriteria.length > 0) {
@@ -585,7 +535,7 @@ export default class Inibase {
585
535
  }
586
536
  }
587
537
  else if (typeof value === "string") {
588
- const ComparisonOperatorValue = this.FormatObjectCriteriaValue(value);
538
+ const ComparisonOperatorValue = Utils.FormatObjectCriteriaValue(value);
589
539
  if (ComparisonOperatorValue) {
590
540
  searchOperator = ComparisonOperatorValue[0];
591
541
  searchComparedAtValue = ComparisonOperatorValue[1];
@@ -769,6 +719,17 @@ export default class Inibase {
769
719
  if (!schema)
770
720
  throw this.throwError("NO_SCHEMA", tableName);
771
721
  const idFilePath = join(this.folder, this.database, tableName, "id.inib"), cashFolderPath = join(this.folder, this.database, tableName, ".tmp");
722
+ let testFileHandle;
723
+ try {
724
+ testFileHandle = await open(join(cashFolderPath, "id.inib"), "wx");
725
+ }
726
+ catch ({ message }) {
727
+ if (message.split(":")[0] === "EEXIST")
728
+ return await new Promise((resolve, reject) => setTimeout(() => resolve(this.post(tableName, data, options, returnPostedData)), 13));
729
+ }
730
+ finally {
731
+ await testFileHandle?.close();
732
+ }
772
733
  let lastId = 0, totalItems = 0, lastIdObj;
773
734
  if (await File.isExists(idFilePath)) {
774
735
  if (await File.isExists(join(cashFolderPath, "lastId.inib"))) {
@@ -800,11 +761,8 @@ export default class Inibase {
800
761
  throw this.throwError("NO_DATA");
801
762
  RETURN = this.formatData(RETURN, schema);
802
763
  const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), Array.isArray(RETURN) ? RETURN.toReversed() : RETURN);
803
- const renameList = [];
804
- for await (const [path, content] of Object.entries(pathesContents))
805
- renameList.push(await File.append(path, content));
806
- for await (const [tempPath, filePath] of renameList)
807
- await rename(tempPath, filePath);
764
+ const renameList = await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => File.append(path, content)));
765
+ await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
808
766
  await File.write(join(cashFolderPath, "lastId.inib"), lastId.toString(), true);
809
767
  await File.write(join(cashFolderPath, "totalItems.inib"), String(totalItems + (Array.isArray(RETURN) ? RETURN.length : 1)), true);
810
768
  if (returnPostedData)
@@ -847,13 +805,23 @@ export default class Inibase {
847
805
  ...(({ id, ...restOfData }) => restOfData)(data),
848
806
  updatedAt: Date.now(),
849
807
  });
850
- for await (const [path, content] of Object.entries(pathesContents))
851
- await File.replace(path, content);
808
+ let testFileHandle;
809
+ try {
810
+ testFileHandle = await open(Object.keys(pathesContents)[0].replace(/([^/]+)\/?$/, `.tmp/$1`), "wx");
811
+ }
812
+ catch ({ message }) {
813
+ if (message.split(":")[0] === "EEXIST")
814
+ return await new Promise((resolve, reject) => setTimeout(() => resolve(this.put(tableName, data, where, options)), 13));
815
+ }
816
+ finally {
817
+ await testFileHandle?.close();
818
+ }
819
+ const renameList = await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => File.replace(path, content)));
820
+ await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
852
821
  if (Config.isCacheEnabled) {
853
822
  const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
854
823
  if (cacheFiles.length)
855
- for await (const file of cacheFiles)
856
- await unlink(join(this.folder, this.database, tableName, ".tmp", file));
824
+ await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
857
825
  }
858
826
  if (returnPostedData)
859
827
  return this.get(tableName, where, options, undefined, undefined, schema);
@@ -883,16 +851,23 @@ export default class Inibase {
883
851
  [lineNum]: Array.isArray(content) ? content[index] : content,
884
852
  }), {}),
885
853
  ]));
886
- const renameList = [];
887
- for await (const [path, content] of Object.entries(pathesContents))
888
- renameList.push(await File.replace(path, content));
889
- for await (const [tempPath, filePath] of renameList)
890
- await rename(tempPath, filePath);
854
+ let testFileHandle;
855
+ try {
856
+ testFileHandle = await open(Object.keys(pathesContents)[0].replace(/([^/]+)\/?$/, `.tmp/$1`), "wx");
857
+ }
858
+ catch ({ message }) {
859
+ if (message.split(":")[0] === "EEXIST")
860
+ return await new Promise((resolve, reject) => setTimeout(() => resolve(this.put(tableName, data, where, options)), 13));
861
+ }
862
+ finally {
863
+ await testFileHandle?.close();
864
+ }
865
+ const renameList = await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => File.replace(path, content)));
866
+ await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
891
867
  if (Config.isCacheEnabled) {
892
868
  const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
893
869
  if (cacheFiles.length)
894
- for await (const file of cacheFiles)
895
- await unlink(join(this.folder, this.database, tableName, ".tmp", file));
870
+ await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
896
871
  }
897
872
  if (returnPostedData)
898
873
  return this.get(tableName, where, options, !Array.isArray(where), undefined, schema);
@@ -917,13 +892,11 @@ export default class Inibase {
917
892
  if (!where) {
918
893
  const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
919
894
  if (files.length)
920
- for await (const file of files)
921
- await unlink(join(this.folder, this.database, tableName, file));
895
+ await Promise.all(files.map(async (file) => unlink(join(this.folder, this.database, tableName, file))));
922
896
  if (Config.isCacheEnabled) {
923
897
  const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
924
898
  if (cacheFiles.length)
925
- for await (const file of cacheFiles)
926
- await unlink(join(this.folder, this.database, tableName, ".tmp", file));
899
+ await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
927
900
  }
928
901
  return "*";
929
902
  }
@@ -947,16 +920,23 @@ export default class Inibase {
947
920
  _id = Object.entries((await File.get(join(this.folder, this.database, tableName, "id.inib"), where, "number", undefined, this.salt)) ?? {}).map(([_key, id]) => UtilsServer.encodeID(Number(id), this.salt));
948
921
  if (!_id.length)
949
922
  throw this.throwError("NO_ITEMS", tableName);
950
- const renameList = [];
951
- for await (const file of files)
952
- renameList.push(await File.remove(join(this.folder, this.database, tableName, file), where));
953
- for await (const [tempPath, filePath] of renameList)
954
- await rename(tempPath, filePath);
923
+ let testFileHandle;
924
+ try {
925
+ testFileHandle = await open(join(this.folder, this.database, tableName, ".tmp", "id.inib"), "wx");
926
+ }
927
+ catch ({ message }) {
928
+ if (message.split(":")[0] === "EEXIST")
929
+ return await new Promise((resolve, reject) => setTimeout(() => resolve(this.delete(tableName, where, _id)), 13));
930
+ }
931
+ finally {
932
+ await testFileHandle?.close();
933
+ }
934
+ const renameList = await Promise.all(files.map(async (file) => File.remove(join(this.folder, this.database, tableName, file), where)));
935
+ await Promise.all(renameList.map(async ([tempPath, filePath]) => rename(tempPath, filePath)));
955
936
  if (Config.isCacheEnabled) {
956
937
  const cacheFiles = (await readdir(join(this.folder, this.database, tableName, ".tmp")))?.filter((fileName) => !["lastId.inib", "totalItems.inib"].includes(fileName));
957
938
  if (cacheFiles.length)
958
- for await (const file of cacheFiles)
959
- await unlink(join(this.folder, this.database, tableName, ".tmp", file));
939
+ await Promise.all(cacheFiles.map(async (file) => unlink(join(this.folder, this.database, tableName, ".tmp", file))));
960
940
  await File.write(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), String(((await File.isExists(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib")))
961
941
  ? Number(await File.read(join(this.folder, this.database, tableName, ".tmp", "totalItems.inib"), true))
962
942
  : await File.count(join(this.folder, this.database, tableName, "id.inib"))) - (Array.isArray(where) ? where.length : 1)), true);
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type FieldType } from "./index.js";
1
+ import { type FieldType, ComparisonOperator } from "./index.js";
2
2
  /**
3
3
  * Type guard function to check if the input is an array of objects.
4
4
  *
@@ -174,6 +174,10 @@ export declare const validateFieldType: (value: any, fieldType: FieldType | Fiel
174
174
  * @returns A flattened object using dot notation for keys.
175
175
  */
176
176
  export declare const objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
177
+ export declare function FormatObjectCriteriaValue(value: string, isParentArray?: boolean): [
178
+ ComparisonOperator,
179
+ string | number | boolean | null | (string | number | null)[]
180
+ ];
177
181
  export default class Utils {
178
182
  static isNumber: (input: any) => input is number;
179
183
  static isObject: (obj: any) => obj is Record<any, any>;
@@ -195,4 +199,5 @@ export default class Utils {
195
199
  static validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[] | undefined) => boolean;
196
200
  static objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
197
201
  static isArrayOfNulls: (input: any) => input is null[] | null[][];
202
+ static FormatObjectCriteriaValue: typeof FormatObjectCriteriaValue;
198
203
  }
package/dist/utils.js CHANGED
@@ -363,6 +363,60 @@ export const objectToDotNotation = (input) => {
363
363
  }
364
364
  return result;
365
365
  };
366
+ export function FormatObjectCriteriaValue(value, isParentArray = false) {
367
+ switch (value[0]) {
368
+ case ">":
369
+ case "<":
370
+ return value[1] === "="
371
+ ? [
372
+ value.slice(0, 2),
373
+ value.slice(2),
374
+ ]
375
+ : [
376
+ value.slice(0, 1),
377
+ value.slice(1),
378
+ ];
379
+ case "[":
380
+ return value[1] === "]"
381
+ ? [
382
+ value.slice(0, 2),
383
+ value.slice(2).toString().split(","),
384
+ ]
385
+ : ["[]", value.slice(1)];
386
+ case "!":
387
+ return ["=", "*"].includes(value[1])
388
+ ? [
389
+ value.slice(0, 2),
390
+ value.slice(2),
391
+ ]
392
+ : value[1] === "["
393
+ ? [
394
+ value.slice(0, 3),
395
+ value.slice(3),
396
+ ]
397
+ : [
398
+ (value.slice(0, 1) + "="),
399
+ value.slice(1),
400
+ ];
401
+ case "=":
402
+ return isParentArray
403
+ ? [
404
+ value.slice(0, 1),
405
+ value.slice(1),
406
+ ]
407
+ : [
408
+ value.slice(0, 1),
409
+ (value.slice(1) + ","),
410
+ ];
411
+ case "*":
412
+ return [
413
+ value.slice(0, 1),
414
+ value.slice(1),
415
+ ];
416
+ default:
417
+ return ["=", value];
418
+ }
419
+ }
366
420
  export default class Utils {
367
421
  static isNumber = isNumber;
368
422
  static isObject = isObject;
@@ -384,4 +438,5 @@ export default class Utils {
384
438
  static validateFieldType = validateFieldType;
385
439
  static objectToDotNotation = objectToDotNotation;
386
440
  static isArrayOfNulls = isArrayOfNulls;
441
+ static FormatObjectCriteriaValue = FormatObjectCriteriaValue;
387
442
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.28",
3
+ "version": "1.0.0-rc.29",
4
4
  "author": {
5
5
  "name": "Karim Amahtil",
6
6
  "email": "karim.amahtil@gmail.com"
@@ -10,6 +10,7 @@
10
10
  "exports": {
11
11
  ".": "./dist/index.js",
12
12
  "./file": "./dist/file.js",
13
+ "./config": "./dist/config.js",
13
14
  "./utils": "./dist/utils.js",
14
15
  "./utils.server": "./dist/utils.server.js"
15
16
  },
@@ -53,13 +54,16 @@
53
54
  "utils": [
54
55
  "./dist/utils.d.ts"
55
56
  ],
57
+ "config": [
58
+ "./dist/config.d.ts"
59
+ ],
56
60
  "utils.server": [
57
61
  "./dist/utils.server.d.ts"
58
62
  ]
59
63
  }
60
64
  },
61
65
  "devDependencies": {
62
- "@types/node": "^20.10.4",
66
+ "@types/node": "^20.10.6",
63
67
  "typescript": "^5.3.3"
64
68
  },
65
69
  "scripts": {