inibase 1.0.0-rc.5 → 1.0.0-rc.6

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/index.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import {
2
- readFileSync,
3
- writeFileSync,
4
- mkdirSync,
5
- existsSync,
6
- appendFileSync,
7
- readdirSync,
8
- unlinkSync,
9
- renameSync,
10
- } from "fs";
11
- import { join, parse } from "path";
2
+ unlink,
3
+ rename,
4
+ readFile,
5
+ writeFile,
6
+ appendFile,
7
+ mkdir,
8
+ readdir,
9
+ } from "node:fs/promises";
10
+ import { join, parse } from "node:path";
12
11
  import Utils from "./utils";
13
12
  import File from "./file";
13
+ import { scryptSync } from "node:crypto";
14
14
 
15
15
  export type Data = {
16
16
  id?: number | string;
@@ -29,11 +29,15 @@ export type FieldType =
29
29
  | "table"
30
30
  | "object"
31
31
  | "array"
32
- | "password";
32
+ | "password"
33
+ | "html"
34
+ | "ip"
35
+ | "id";
33
36
  type FieldDefault = {
34
37
  id?: string | number | null | undefined;
35
38
  key: string;
36
39
  required?: boolean;
40
+ children?: any;
37
41
  };
38
42
  type FieldStringType = {
39
43
  type: Exclude<FieldType, "array" | "object">;
@@ -54,7 +58,7 @@ type FieldObjectType = {
54
58
  children: Schema;
55
59
  };
56
60
  // if "type" is array, make "array" at first place, and "number" & "string" at last place of the array
57
- type Field = FieldDefault &
61
+ export type Field = FieldDefault &
58
62
  (
59
63
  | FieldStringType
60
64
  | FieldStringArrayType
@@ -113,6 +117,7 @@ export default class Inibase {
113
117
  public cache: Map<string, string>;
114
118
  public pageInfoArray: Record<string, Record<string, number>>;
115
119
  public pageInfo: pageInfo;
120
+ private salt: Buffer;
116
121
 
117
122
  constructor(databaseName: string, mainFolder: string = ".") {
118
123
  this.database = databaseName;
@@ -120,6 +125,7 @@ export default class Inibase {
120
125
  this.cache = new Map<string, any>();
121
126
  this.pageInfoArray = {};
122
127
  this.pageInfo = { page: 1, per_page: 15 };
128
+ this.salt = scryptSync(this.databasePath, "salt", 32);
123
129
  }
124
130
 
125
131
  private throwError(
@@ -168,25 +174,40 @@ export default class Inibase {
168
174
  return new Error(errorMessage);
169
175
  }
170
176
 
171
- public setTableSchema(tableName: string, schema: Schema): void {
177
+ private findLastIdNumber(schema: Schema): number {
178
+ const lastField = schema[schema.length - 1];
179
+ if (lastField) {
180
+ if (
181
+ (lastField.type === "array" || lastField.type === "object") &&
182
+ Utils.isArrayOfObjects(lastField.children)
183
+ )
184
+ return this.findLastIdNumber(lastField.children as Schema);
185
+ else if (lastField.id && Utils.isValidID(lastField.id))
186
+ return Utils.decodeID(lastField.id as string, this.salt);
187
+ }
188
+ return 0;
189
+ }
190
+
191
+ public async setTableSchema(
192
+ tableName: string,
193
+ schema: Schema
194
+ ): Promise<void> {
172
195
  const encodeSchema = (schema: Schema) => {
173
196
  let RETURN: any[][] = [],
174
197
  index = 0;
175
198
  for (const field of schema) {
176
199
  if (!RETURN[index]) RETURN[index] = [];
177
200
  RETURN[index].push(
178
- field.id
179
- ? Utils.decodeID(field.id as string, this.databasePath)
180
- : null
201
+ field.id ? Utils.decodeID(field.id as string, this.salt) : null
181
202
  );
182
203
  RETURN[index].push(field.key ?? null);
183
204
  RETURN[index].push(field.required ?? null);
184
205
  RETURN[index].push(field.type ?? null);
185
206
  RETURN[index].push(
186
- (field.type === "array" || field.type === "object") &&
187
- field.children &&
188
- Utils.isArrayOfObjects(field.children)
189
- ? encodeSchema(field.children as Schema) ?? null
207
+ (field as any).children
208
+ ? Utils.isArrayOfObjects((field as any).children)
209
+ ? encodeSchema((field as any).children as Schema) ?? null
210
+ : (field as any).children
190
211
  : null
191
212
  );
192
213
  index++;
@@ -203,44 +224,33 @@ export default class Inibase {
203
224
  oldIndex++;
204
225
  field = {
205
226
  ...field,
206
- id: Utils.encodeID(oldIndex, this.databasePath),
227
+ id: Utils.encodeID(oldIndex, this.salt),
207
228
  };
208
- } else
209
- oldIndex = Utils.decodeID(field.id as string, this.databasePath);
229
+ } else oldIndex = Utils.decodeID(field.id as string, this.salt);
210
230
  field.children = addIdToSchema(field.children as Schema, oldIndex);
211
231
  oldIndex += field.children.length;
212
232
  } else if (field.id)
213
- oldIndex = Utils.decodeID(field.id as string, this.databasePath);
233
+ oldIndex = Utils.decodeID(field.id as string, this.salt);
214
234
  else {
215
235
  oldIndex++;
216
236
  field = {
217
237
  ...field,
218
- id: Utils.encodeID(oldIndex, this.databasePath),
238
+ id: Utils.encodeID(oldIndex, this.salt),
219
239
  };
220
240
  }
221
241
  return field;
222
- }),
223
- findLastIdNumber = (schema: Schema): number => {
224
- const lastField = schema[schema.length - 1];
225
- if (lastField) {
226
- if (
227
- (lastField.type === "array" || lastField.type === "object") &&
228
- Utils.isArrayOfObjects(lastField.children)
229
- )
230
- return findLastIdNumber(lastField.children as Schema);
231
- else if (lastField.id && Utils.isValidID(lastField.id))
232
- return Utils.decodeID(lastField.id as string, this.databasePath);
233
- }
234
- return 0;
235
- };
242
+ });
236
243
 
237
244
  // remove id from schema
238
- schema = schema.filter((field) => field.key !== "id");
239
- schema = addIdToSchema(schema, findLastIdNumber(schema));
245
+ schema = schema.filter(
246
+ (field) => !["id", "created_at", "updated_at"].includes(field.key)
247
+ );
248
+ schema = addIdToSchema(schema, this.findLastIdNumber(schema));
240
249
  const TablePath = join(this.databasePath, tableName),
241
250
  TableSchemaPath = join(TablePath, "schema.inib");
242
- if (!existsSync(TablePath)) mkdirSync(TablePath, { recursive: true });
243
- if (existsSync(TableSchemaPath)) {
251
+ if (!(await File.isExists(TablePath)))
252
+ await mkdir(TablePath, { recursive: true });
253
+ if (await File.isExists(TableSchemaPath)) {
244
254
  // update columns files names based on field id
245
255
  const schemaToIdsPath = (schema: any, prefix = "") => {
246
256
  let RETURN: any = {};
@@ -256,35 +266,37 @@ export default class Inibase {
256
266
  )
257
267
  );
258
268
  } else if (Utils.isValidID(field.id))
259
- RETURN[Utils.decodeID(field.id, this.databasePath)] =
260
- File.encodeFileName((prefix ?? "") + field.key, "inib");
269
+ RETURN[Utils.decodeID(field.id, this.salt)] = File.encodeFileName(
270
+ (prefix ?? "") + field.key,
271
+ "inib"
272
+ );
261
273
 
262
274
  return RETURN;
263
275
  },
264
276
  replaceOldPathes = Utils.findChangedProperties(
265
- schemaToIdsPath(this.getTableSchema(tableName)),
277
+ schemaToIdsPath(await this.getTableSchema(tableName)),
266
278
  schemaToIdsPath(schema)
267
279
  );
268
280
  if (replaceOldPathes)
269
281
  for (const [oldPath, newPath] of Object.entries(replaceOldPathes))
270
- if (existsSync(join(TablePath, oldPath)))
271
- renameSync(join(TablePath, oldPath), join(TablePath, newPath));
282
+ if (await File.isExists(join(TablePath, oldPath)))
283
+ await rename(join(TablePath, oldPath), join(TablePath, newPath));
272
284
  }
273
285
 
274
- writeFileSync(
286
+ await writeFile(
275
287
  join(TablePath, "schema.inib"),
276
288
  JSON.stringify(encodeSchema(schema))
277
289
  );
278
290
  }
279
291
 
280
- public getTableSchema(tableName: string): Schema | undefined {
292
+ public async getTableSchema(tableName: string): Promise<Schema | undefined> {
281
293
  const decodeSchema = (encodedSchema: any) => {
282
294
  return encodedSchema.map((field: any) =>
283
295
  Array.isArray(field[0])
284
296
  ? decodeSchema(field)
285
297
  : Object.fromEntries(
286
298
  Object.entries({
287
- id: Utils.encodeID(field[0], this.databasePath),
299
+ id: Utils.encodeID(field[0], this.salt),
288
300
  key: field[1],
289
301
  required: field[2],
290
302
  type: field[3],
@@ -298,9 +310,11 @@ export default class Inibase {
298
310
  );
299
311
  },
300
312
  TableSchemaPath = join(this.databasePath, tableName, "schema.inib");
301
- if (!existsSync(TableSchemaPath)) return undefined;
313
+ if (!(await File.isExists(TableSchemaPath))) return undefined;
302
314
  if (!this.cache.has(TableSchemaPath)) {
303
- const TableSchemaPathContent = readFileSync(TableSchemaPath);
315
+ const TableSchemaPathContent = await readFile(TableSchemaPath, {
316
+ encoding: "utf8",
317
+ });
304
318
  this.cache.set(
305
319
  TableSchemaPath,
306
320
  TableSchemaPathContent
@@ -308,14 +322,28 @@ export default class Inibase {
308
322
  : ""
309
323
  );
310
324
  }
325
+ const schema = this.cache.get(TableSchemaPath) as unknown as Schema,
326
+ lastIdNumber = this.findLastIdNumber(schema);
311
327
  return [
312
328
  {
313
- id: Utils.encodeID(0, this.databasePath),
329
+ id: Utils.encodeID(0, this.salt),
314
330
  key: "id",
315
331
  type: "number",
316
332
  required: true,
317
333
  },
318
- ...(this.cache.get(TableSchemaPath) as unknown as Schema),
334
+ ...schema,
335
+ {
336
+ id: Utils.encodeID(lastIdNumber, this.salt),
337
+ key: "created_at",
338
+ type: "date",
339
+ required: true,
340
+ },
341
+ {
342
+ id: Utils.encodeID(lastIdNumber + 1, this.salt),
343
+ key: "updated_at",
344
+ type: "date",
345
+ required: false,
346
+ },
319
347
  ];
320
348
  }
321
349
 
@@ -381,16 +409,21 @@ export default class Inibase {
381
409
 
382
410
  switch (fieldType) {
383
411
  case "string":
384
- // TO-DO: and not email, url, password ...
385
- return !Utils.isNumber(value);
412
+ return Utils.isString(value);
386
413
  case "password":
387
- return !Utils.isNumber(value) && Utils.isPassword(value);
414
+ return (
415
+ Utils.isNumber(value) ||
416
+ Utils.isString(value) ||
417
+ Utils.isPassword(value)
418
+ );
388
419
  case "number":
389
420
  return Utils.isNumber(value);
421
+ case "html":
422
+ return Utils.isHTML(value);
423
+ case "ip":
424
+ return Utils.isIP(value);
390
425
  case "boolean":
391
- return (
392
- typeof value === "boolean" || value === "true" || value === "false"
393
- );
426
+ return Utils.isBoolean(value);
394
427
  case "date":
395
428
  return Utils.isDate(value);
396
429
  case "object":
@@ -421,10 +454,13 @@ export default class Inibase {
421
454
  Utils.isNumber((value as Data).id))
422
455
  );
423
456
  else return Utils.isNumber(value) || Utils.isValidID(value);
457
+ case "id":
458
+ return Utils.isNumber(value) || Utils.isValidID(value);
424
459
  default:
425
460
  return false;
426
461
  }
427
462
  };
463
+
428
464
  if (Utils.isArrayOfObjects(data))
429
465
  for (const single_data of data as Data[])
430
466
  this.validateData(single_data, schema, skipRequiredField);
@@ -437,6 +473,7 @@ export default class Inibase {
437
473
  )
438
474
  throw this.throwError("FIELD_REQUIRED", field.key);
439
475
  if (
476
+ data.hasOwnProperty(field.key) &&
440
477
  !validateFieldType(
441
478
  data[field.key],
442
479
  field.type,
@@ -472,7 +509,6 @@ export default class Inibase {
472
509
  ): Data | Data[] | number | string => {
473
510
  if (Array.isArray(field.type))
474
511
  field.type = Utils.detectFieldType(value, field.type);
475
-
476
512
  switch (field.type) {
477
513
  case "array":
478
514
  if (typeof field.children === "string") {
@@ -489,16 +525,16 @@ export default class Inibase {
489
525
  value.map((item: any) =>
490
526
  Utils.isNumber(item.id)
491
527
  ? Number(item.id)
492
- : Utils.decodeID(item.id, this.databasePath)
528
+ : Utils.decodeID(item.id, this.salt)
493
529
  );
494
530
  } else if (Utils.isValidID(value) || Utils.isNumber(value))
495
531
  return value.map((item: number | string) =>
496
532
  Utils.isNumber(item)
497
533
  ? Number(item as string)
498
- : Utils.decodeID(item as string, this.databasePath)
534
+ : Utils.decodeID(item as string, this.salt)
499
535
  );
500
536
  } else if (Utils.isValidID(value))
501
- return [Utils.decodeID(value, this.databasePath)];
537
+ return [Utils.decodeID(value, this.salt)];
502
538
  else if (Utils.isNumber(value)) return [Number(value)];
503
539
  } else if (data.hasOwnProperty(field.key)) return value;
504
540
  } else if (Utils.isArrayOfObjects(field.children))
@@ -526,21 +562,28 @@ export default class Inibase {
526
562
  )
527
563
  return Utils.isNumber(value.id)
528
564
  ? Number(value.id)
529
- : Utils.decodeID(value.id, this.databasePath);
565
+ : Utils.decodeID(value.id, this.salt);
530
566
  } else if (Utils.isValidID(value) || Utils.isNumber(value))
531
567
  return Utils.isNumber(value)
532
568
  ? Number(value)
533
- : Utils.decodeID(value, this.databasePath);
569
+ : Utils.decodeID(value, this.salt);
534
570
  break;
535
571
  case "password":
536
572
  return value.length === 161 ? value : Utils.hashPassword(value);
537
573
  case "number":
538
574
  return Utils.isNumber(value) ? Number(value) : null;
575
+ case "id":
576
+ return Utils.isNumber(value)
577
+ ? Utils.encodeID(value, this.salt)
578
+ : value;
539
579
  default:
540
580
  return value;
541
581
  }
542
582
  return null;
543
583
  };
584
+
585
+ this.validateData(data, schema, formatOnlyAvailiableKeys);
586
+
544
587
  if (Utils.isArrayOfObjects(data))
545
588
  return data.map((single_data: Data) =>
546
589
  this.formatData(single_data, schema, formatOnlyAvailiableKeys)
@@ -549,7 +592,7 @@ export default class Inibase {
549
592
  let RETURN: Data = {};
550
593
  for (const field of schema) {
551
594
  if (!data.hasOwnProperty(field.key)) {
552
- if (formatOnlyAvailiableKeys) continue;
595
+ if (formatOnlyAvailiableKeys || !field.required) continue;
553
596
  RETURN[field.key] = this.getDefaultValue(field);
554
597
  continue;
555
598
  }
@@ -676,16 +719,15 @@ export default class Inibase {
676
719
  if (!options.columns) options.columns = [];
677
720
  else if (!Array.isArray(options.columns))
678
721
  options.columns = [options.columns];
679
- else if (
680
- options.columns.length &&
681
- !(options.columns as string[]).includes("id")
682
- )
722
+ if (options.columns.length && !(options.columns as string[]).includes("id"))
683
723
  options.columns.push("id");
684
724
  if (!options.page) options.page = 1;
685
725
  if (!options.per_page) options.per_page = 15;
686
726
  let RETURN!: Data | Data[] | null;
687
- let schema = this.getTableSchema(tableName);
727
+ let schema = await this.getTableSchema(tableName);
688
728
  if (!schema) throw this.throwError("NO_SCHEMA", tableName);
729
+ const idFilePath = join(this.databasePath, tableName, "id.inib");
730
+ if (!(await File.isExists(idFilePath))) return null;
689
731
  const filterSchemaByColumns = (schema: Schema, columns: string[]): Schema =>
690
732
  schema
691
733
  .map((field) => {
@@ -699,12 +741,8 @@ export default class Inibase {
699
741
  Utils.isArrayOfObjects(field.children) &&
700
742
  columns.filter(
701
743
  (column) =>
702
- column.startsWith(
703
- field.key + (field.type === "array" ? ".*." : ".")
704
- ) ||
705
- column.startsWith(
706
- "!" + field.key + (field.type === "array" ? ".*." : ".")
707
- )
744
+ column.startsWith(field.key + ".") ||
745
+ column.startsWith("!" + field.key + ".")
708
746
  ).length
709
747
  ) {
710
748
  field.children = filterSchemaByColumns(
@@ -712,19 +750,10 @@ export default class Inibase {
712
750
  columns
713
751
  .filter(
714
752
  (column) =>
715
- column.startsWith(
716
- field.key + (field.type === "array" ? ".*." : ".")
717
- ) ||
718
- column.startsWith(
719
- "!" + field.key + (field.type === "array" ? ".*." : ".")
720
- )
721
- )
722
- .map((column) =>
723
- column.replace(
724
- field.key + (field.type === "array" ? ".*." : "."),
725
- ""
726
- )
753
+ column.startsWith(field.key + ".") ||
754
+ column.startsWith("!" + field.key + ".")
727
755
  )
756
+ .map((column) => column.replace(field.key + ".", ""))
728
757
  );
729
758
  return field;
730
759
  }
@@ -851,7 +880,7 @@ export default class Inibase {
851
880
  if (RETURN[index][field.key])
852
881
  Object.entries(item).forEach(([key, value], _index) => {
853
882
  RETURN[index][field.key] = RETURN[index][field.key].map(
854
- (_obj, _i) => ({ ..._obj, [key]: value[_index] })
883
+ (_obj, _i) => ({ ..._obj, [key]: value[_i] })
855
884
  );
856
885
  });
857
886
  else if (Object.values(item).every(Utils.isArrayOfArrays))
@@ -903,7 +932,7 @@ export default class Inibase {
903
932
  : this.getDefaultValue(field);
904
933
  }
905
934
  } else if (
906
- existsSync(
935
+ await File.isExists(
907
936
  join(
908
937
  path,
909
938
  File.encodeFileName((prefix ?? "") + field.key, "inib")
@@ -942,13 +971,13 @@ export default class Inibase {
942
971
  });
943
972
  } else if (field.type === "table") {
944
973
  if (
945
- existsSync(join(this.databasePath, field.key)) &&
946
- existsSync(
974
+ (await File.isExists(join(this.databasePath, field.key))) &&
975
+ (await File.isExists(
947
976
  join(
948
977
  path,
949
978
  File.encodeFileName((prefix ?? "") + field.key, "inib")
950
979
  )
951
- )
980
+ ))
952
981
  ) {
953
982
  if (options.columns)
954
983
  options.columns = (options.columns as string[])
@@ -975,7 +1004,7 @@ export default class Inibase {
975
1004
  }
976
1005
  }
977
1006
  } else if (
978
- existsSync(
1007
+ await File.isExists(
979
1008
  join(path, File.encodeFileName((prefix ?? "") + field.key, "inib"))
980
1009
  )
981
1010
  )
@@ -1014,18 +1043,19 @@ export default class Inibase {
1014
1043
  } else if (Utils.isValidID(where) || Utils.isNumber(where)) {
1015
1044
  let Ids = where as string | number | (string | number)[];
1016
1045
  if (!Array.isArray(Ids)) Ids = [Ids];
1017
- const idFilePath = join(this.databasePath, tableName, "id.inib");
1018
- if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
1019
1046
  const [lineNumbers, countItems] = await File.search(
1020
1047
  idFilePath,
1021
1048
  "[]",
1022
1049
  Utils.isNumber(Ids)
1023
1050
  ? Ids.map((id) => Number(id as string))
1024
- : Ids.map((id) => Utils.decodeID(id as string, this.databasePath)),
1051
+ : Ids.map((id) => Utils.decodeID(id as string, this.salt)),
1025
1052
  undefined,
1026
1053
  "number",
1027
1054
  undefined,
1028
- Ids.length
1055
+ Ids.length,
1056
+ 0,
1057
+ false,
1058
+ this.databasePath
1029
1059
  );
1030
1060
  if (!lineNumbers || !Object.keys(lineNumbers).length)
1031
1061
  throw this.throwError(
@@ -1240,7 +1270,8 @@ export default class Inibase {
1240
1270
  (field as any)?.children,
1241
1271
  options.per_page,
1242
1272
  (options.page as number) - 1 * (options.per_page as number) + 1,
1243
- true
1273
+ true,
1274
+ this.databasePath
1244
1275
  );
1245
1276
  if (searchResult) {
1246
1277
  RETURN = Utils.deepMerge(RETURN, searchResult);
@@ -1306,12 +1337,12 @@ export default class Inibase {
1306
1337
  return null;
1307
1338
  return Utils.isArrayOfObjects(RETURN)
1308
1339
  ? (RETURN as Data[]).map((data: Data) => {
1309
- data.id = Utils.encodeID(data.id as number, this.databasePath);
1340
+ data.id = Utils.encodeID(data.id as number, this.salt);
1310
1341
  return data;
1311
1342
  })
1312
1343
  : {
1313
1344
  ...(RETURN as Data),
1314
- id: Utils.encodeID((RETURN as Data).id as number, this.databasePath),
1345
+ id: Utils.encodeID((RETURN as Data).id as number, this.salt),
1315
1346
  };
1316
1347
  }
1317
1348
 
@@ -1323,41 +1354,38 @@ export default class Inibase {
1323
1354
  per_page: 15,
1324
1355
  }
1325
1356
  ): Promise<Data | Data[] | null> {
1326
- const schema = this.getTableSchema(tableName);
1357
+ const schema = await this.getTableSchema(tableName);
1327
1358
  let RETURN: Data | Data[] | null | undefined;
1328
1359
  if (!schema) throw this.throwError("NO_SCHEMA", tableName);
1329
1360
  const idFilePath = join(this.databasePath, tableName, "id.inib");
1330
- let last_id = existsSync(idFilePath)
1361
+ let last_id = (await File.isExists(idFilePath))
1331
1362
  ? Number(Object.values(await File.get(idFilePath, -1, "number"))[0])
1332
1363
  : 0;
1333
1364
  if (Utils.isArrayOfObjects(data))
1334
1365
  (data as Data[]).forEach((single_data, index) => {
1335
1366
  if (!RETURN) RETURN = [];
1336
- RETURN[index] = (({ id, updated_at, created_at, ...rest }) => rest)(
1337
- single_data
1338
- );
1339
- RETURN[index].id = ++last_id;
1340
- RETURN[index].created_at = new Date();
1367
+ RETURN[index] = (({ id, updated_at, created_at, ...rest }) => ({
1368
+ id: ++last_id,
1369
+ ...rest,
1370
+ created_at: new Date(),
1371
+ }))(single_data);
1341
1372
  });
1342
- else {
1343
- RETURN = (({ id, updated_at, created_at, ...rest }) => rest)(
1344
- data as Data
1345
- );
1346
- RETURN.id = ++last_id;
1347
- RETURN.created_at = new Date();
1348
- }
1373
+ else
1374
+ RETURN = (({ id, updated_at, created_at, ...rest }) => ({
1375
+ id: ++last_id,
1376
+ ...rest,
1377
+ created_at: new Date(),
1378
+ }))(data as Data);
1349
1379
  if (!RETURN) throw this.throwError("NO_DATA");
1350
- this.validateData(RETURN, schema);
1351
1380
  RETURN = this.formatData(RETURN, schema);
1352
1381
  const pathesContents = this.joinPathesContents(
1353
1382
  join(this.databasePath, tableName),
1354
1383
  RETURN
1355
1384
  );
1356
- for (const [path, content] of Object.entries(pathesContents))
1357
- appendFileSync(
1385
+ for await (const [path, content] of Object.entries(pathesContents))
1386
+ await appendFile(
1358
1387
  path,
1359
- (Array.isArray(content) ? content.join("\n") : content ?? "") + "\n",
1360
- "utf8"
1388
+ (Array.isArray(content) ? content.join("\n") : content ?? "") + "\n"
1361
1389
  );
1362
1390
 
1363
1391
  return this.get(
@@ -1378,9 +1406,11 @@ export default class Inibase {
1378
1406
  per_page: 15,
1379
1407
  }
1380
1408
  ): Promise<Data | Data[] | null> {
1381
- const schema = this.getTableSchema(tableName);
1409
+ const schema = await this.getTableSchema(tableName);
1382
1410
  if (!schema) throw this.throwError("NO_SCHEMA", tableName);
1383
- this.validateData(data, schema, true);
1411
+ const idFilePath = join(this.databasePath, tableName, "id.inib");
1412
+ if (!(await File.isExists(idFilePath)))
1413
+ throw this.throwError("NO_ITEMS", tableName);
1384
1414
  data = this.formatData(data, schema, true);
1385
1415
  if (!where) {
1386
1416
  if (Utils.isArrayOfObjects(data)) {
@@ -1401,7 +1431,7 @@ export default class Inibase {
1401
1431
  return this.put(
1402
1432
  tableName,
1403
1433
  data,
1404
- Utils.decodeID((data as Data).id as string, this.databasePath)
1434
+ Utils.decodeID((data as Data).id as string, this.salt)
1405
1435
  );
1406
1436
  } else {
1407
1437
  const pathesContents = this.joinPathesContents(
@@ -1423,16 +1453,17 @@ export default class Inibase {
1423
1453
  } else if (Utils.isValidID(where)) {
1424
1454
  let Ids = where as string | string[];
1425
1455
  if (!Array.isArray(Ids)) Ids = [Ids];
1426
- const idFilePath = join(this.databasePath, tableName, "id.inib");
1427
- if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
1428
1456
  const [lineNumbers, countItems] = await File.search(
1429
1457
  idFilePath,
1430
1458
  "[]",
1431
- Ids.map((id) => Utils.decodeID(id, this.databasePath)),
1459
+ Ids.map((id) => Utils.decodeID(id, this.salt)),
1432
1460
  undefined,
1433
1461
  "number",
1434
1462
  undefined,
1435
- Ids.length
1463
+ Ids.length,
1464
+ 0,
1465
+ false,
1466
+ this.databasePath
1436
1467
  );
1437
1468
  if (!lineNumbers || !Object.keys(lineNumbers).length)
1438
1469
  throw this.throwError("INVALID_ID");
@@ -1476,31 +1507,35 @@ export default class Inibase {
1476
1507
  tableName: string,
1477
1508
  where?: number | string | (number | string)[] | Criteria,
1478
1509
  _id?: string | string[]
1479
- ): Promise<string | string[]> {
1480
- const schema = this.getTableSchema(tableName);
1510
+ ): Promise<string | string[] | null> {
1511
+ const schema = await this.getTableSchema(tableName);
1481
1512
  if (!schema) throw this.throwError("NO_SCHEMA", tableName);
1513
+ const idFilePath = join(this.databasePath, tableName, "id.inib");
1514
+ if (!(await File.isExists(idFilePath)))
1515
+ throw this.throwError("NO_ITEMS", tableName);
1482
1516
  if (!where) {
1483
- const files = readdirSync(join(this.databasePath, tableName));
1517
+ const files = await readdir(join(this.databasePath, tableName));
1484
1518
  if (files.length) {
1485
1519
  for (const file in files.filter(
1486
1520
  (fileName: string) => fileName !== "schema.inib"
1487
1521
  ))
1488
- unlinkSync(join(this.databasePath, tableName, file));
1522
+ await unlink(join(this.databasePath, tableName, file));
1489
1523
  }
1490
1524
  return "*";
1491
1525
  } else if (Utils.isValidID(where)) {
1492
1526
  let Ids = where as string | string[];
1493
1527
  if (!Array.isArray(Ids)) Ids = [Ids];
1494
- const idFilePath = join(this.databasePath, tableName, "id.inib");
1495
- if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
1496
1528
  const [lineNumbers, countItems] = await File.search(
1497
1529
  idFilePath,
1498
1530
  "[]",
1499
- Ids.map((id) => Utils.decodeID(id, this.databasePath)),
1531
+ Ids.map((id) => Utils.decodeID(id, this.salt)),
1500
1532
  undefined,
1501
1533
  "number",
1502
1534
  undefined,
1503
- Ids.length
1535
+ Ids.length,
1536
+ 0,
1537
+ false,
1538
+ this.databasePath
1504
1539
  );
1505
1540
  if (!lineNumbers || !Object.keys(lineNumbers).length)
1506
1541
  throw this.throwError("INVALID_ID");
@@ -1510,7 +1545,7 @@ export default class Inibase {
1510
1545
  where as string | string[]
1511
1546
  );
1512
1547
  } else if (Utils.isNumber(where)) {
1513
- const files = readdirSync(join(this.databasePath, tableName));
1548
+ const files = await readdir(join(this.databasePath, tableName));
1514
1549
  if (files.length) {
1515
1550
  if (!_id)
1516
1551
  _id = Object.values(
@@ -1521,9 +1556,10 @@ export default class Inibase {
1521
1556
  )
1522
1557
  )
1523
1558
  .map(Number)
1524
- .map((id) => Utils.encodeID(id, this.databasePath));
1525
- for (const file in files.filter(
1526
- (fileName: string) => fileName !== "schema.inib"
1559
+ .map((id) => Utils.encodeID(id, this.salt));
1560
+ for (const file of files.filter(
1561
+ (fileName: string) =>
1562
+ fileName.endsWith(".inib") && fileName !== "schema.inib"
1527
1563
  ))
1528
1564
  await File.remove(
1529
1565
  join(this.databasePath, tableName, file),
@@ -1537,5 +1573,6 @@ export default class Inibase {
1537
1573
  throw this.throwError("NO_ITEMS", tableName);
1538
1574
  return this.delete(tableName, lineNumbers);
1539
1575
  } else throw this.throwError("INVALID_PARAMETERS", tableName);
1576
+ return null;
1540
1577
  }
1541
1578
  }