inibase 1.0.0-rc.6 → 1.0.0-rc.8
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 +1 -55
- package/file.ts +70 -26
- package/index.test.ts +8 -2
- package/index.ts +176 -242
- package/package.json +5 -5
- package/utils.server.ts +79 -0
- package/utils.ts +77 -86
package/index.ts
CHANGED
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
readdir,
|
|
9
9
|
} from "node:fs/promises";
|
|
10
10
|
import { join, parse } from "node:path";
|
|
11
|
-
import Utils from "./utils";
|
|
12
|
-
import File from "./file";
|
|
13
11
|
import { scryptSync } from "node:crypto";
|
|
12
|
+
import File from "./file";
|
|
13
|
+
import Utils from "./utils";
|
|
14
|
+
import UtilsServer from "./utils.server";
|
|
14
15
|
|
|
15
16
|
export type Data = {
|
|
16
17
|
id?: number | string;
|
|
@@ -88,7 +89,7 @@ export type ComparisonOperator =
|
|
|
88
89
|
| "![]";
|
|
89
90
|
|
|
90
91
|
type pageInfo = {
|
|
91
|
-
|
|
92
|
+
total?: number;
|
|
92
93
|
total_pages?: number;
|
|
93
94
|
} & Options;
|
|
94
95
|
|
|
@@ -112,20 +113,22 @@ declare global {
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
export default class Inibase {
|
|
116
|
+
public folder: string;
|
|
115
117
|
public database: string;
|
|
116
|
-
public
|
|
117
|
-
public cache: Map<string, string>;
|
|
118
|
-
public pageInfoArray: Record<string, Record<string, number>>;
|
|
118
|
+
public table: string;
|
|
119
119
|
public pageInfo: pageInfo;
|
|
120
|
+
private cache: Map<string, string>;
|
|
121
|
+
private totalItems: Record<string, number>;
|
|
120
122
|
private salt: Buffer;
|
|
121
123
|
|
|
122
|
-
constructor(
|
|
123
|
-
this.database =
|
|
124
|
-
this.
|
|
124
|
+
constructor(database: string, mainFolder: string = ".") {
|
|
125
|
+
this.database = database;
|
|
126
|
+
this.folder = mainFolder;
|
|
127
|
+
this.table = null;
|
|
125
128
|
this.cache = new Map<string, any>();
|
|
126
|
-
this.
|
|
129
|
+
this.totalItems = {};
|
|
127
130
|
this.pageInfo = { page: 1, per_page: 15 };
|
|
128
|
-
this.salt = scryptSync(
|
|
131
|
+
this.salt = scryptSync(database, "salt", 32);
|
|
129
132
|
}
|
|
130
133
|
|
|
131
134
|
private throwError(
|
|
@@ -183,7 +186,7 @@ export default class Inibase {
|
|
|
183
186
|
)
|
|
184
187
|
return this.findLastIdNumber(lastField.children as Schema);
|
|
185
188
|
else if (lastField.id && Utils.isValidID(lastField.id))
|
|
186
|
-
return
|
|
189
|
+
return UtilsServer.decodeID(lastField.id as string, this.salt);
|
|
187
190
|
}
|
|
188
191
|
return 0;
|
|
189
192
|
}
|
|
@@ -198,7 +201,9 @@ export default class Inibase {
|
|
|
198
201
|
for (const field of schema) {
|
|
199
202
|
if (!RETURN[index]) RETURN[index] = [];
|
|
200
203
|
RETURN[index].push(
|
|
201
|
-
field.id
|
|
204
|
+
field.id
|
|
205
|
+
? UtilsServer.decodeID(field.id as string, this.salt)
|
|
206
|
+
: null
|
|
202
207
|
);
|
|
203
208
|
RETURN[index].push(field.key ?? null);
|
|
204
209
|
RETURN[index].push(field.required ?? null);
|
|
@@ -224,18 +229,19 @@ export default class Inibase {
|
|
|
224
229
|
oldIndex++;
|
|
225
230
|
field = {
|
|
226
231
|
...field,
|
|
227
|
-
id:
|
|
232
|
+
id: UtilsServer.encodeID(oldIndex, this.salt),
|
|
228
233
|
};
|
|
229
|
-
} else
|
|
234
|
+
} else
|
|
235
|
+
oldIndex = UtilsServer.decodeID(field.id as string, this.salt);
|
|
230
236
|
field.children = addIdToSchema(field.children as Schema, oldIndex);
|
|
231
237
|
oldIndex += field.children.length;
|
|
232
238
|
} else if (field.id)
|
|
233
|
-
oldIndex =
|
|
239
|
+
oldIndex = UtilsServer.decodeID(field.id as string, this.salt);
|
|
234
240
|
else {
|
|
235
241
|
oldIndex++;
|
|
236
242
|
field = {
|
|
237
243
|
...field,
|
|
238
|
-
id:
|
|
244
|
+
id: UtilsServer.encodeID(oldIndex, this.salt),
|
|
239
245
|
};
|
|
240
246
|
}
|
|
241
247
|
return field;
|
|
@@ -246,8 +252,8 @@ export default class Inibase {
|
|
|
246
252
|
(field) => !["id", "created_at", "updated_at"].includes(field.key)
|
|
247
253
|
);
|
|
248
254
|
schema = addIdToSchema(schema, this.findLastIdNumber(schema));
|
|
249
|
-
const TablePath = join(this.
|
|
250
|
-
TableSchemaPath = join(TablePath, "schema
|
|
255
|
+
const TablePath = join(this.folder, this.database, tableName),
|
|
256
|
+
TableSchemaPath = join(TablePath, "schema");
|
|
251
257
|
if (!(await File.isExists(TablePath)))
|
|
252
258
|
await mkdir(TablePath, { recursive: true });
|
|
253
259
|
if (await File.isExists(TableSchemaPath)) {
|
|
@@ -266,10 +272,8 @@ export default class Inibase {
|
|
|
266
272
|
)
|
|
267
273
|
);
|
|
268
274
|
} else if (Utils.isValidID(field.id))
|
|
269
|
-
RETURN[
|
|
270
|
-
(prefix ?? "") + field.key,
|
|
271
|
-
"inib"
|
|
272
|
-
);
|
|
275
|
+
RETURN[UtilsServer.decodeID(field.id, this.salt)] =
|
|
276
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib");
|
|
273
277
|
|
|
274
278
|
return RETURN;
|
|
275
279
|
},
|
|
@@ -284,7 +288,7 @@ export default class Inibase {
|
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
await writeFile(
|
|
287
|
-
join(TablePath, "schema
|
|
291
|
+
join(TablePath, "schema"),
|
|
288
292
|
JSON.stringify(encodeSchema(schema))
|
|
289
293
|
);
|
|
290
294
|
}
|
|
@@ -296,7 +300,7 @@ export default class Inibase {
|
|
|
296
300
|
? decodeSchema(field)
|
|
297
301
|
: Object.fromEntries(
|
|
298
302
|
Object.entries({
|
|
299
|
-
id:
|
|
303
|
+
id: UtilsServer.encodeID(field[0], this.salt),
|
|
300
304
|
key: field[1],
|
|
301
305
|
required: field[2],
|
|
302
306
|
type: field[3],
|
|
@@ -309,7 +313,7 @@ export default class Inibase {
|
|
|
309
313
|
)
|
|
310
314
|
);
|
|
311
315
|
},
|
|
312
|
-
TableSchemaPath = join(this.
|
|
316
|
+
TableSchemaPath = join(this.folder, this.database, tableName, "schema");
|
|
313
317
|
if (!(await File.isExists(TableSchemaPath))) return undefined;
|
|
314
318
|
if (!this.cache.has(TableSchemaPath)) {
|
|
315
319
|
const TableSchemaPathContent = await readFile(TableSchemaPath, {
|
|
@@ -326,20 +330,20 @@ export default class Inibase {
|
|
|
326
330
|
lastIdNumber = this.findLastIdNumber(schema);
|
|
327
331
|
return [
|
|
328
332
|
{
|
|
329
|
-
id:
|
|
333
|
+
id: UtilsServer.encodeID(0, this.salt),
|
|
330
334
|
key: "id",
|
|
331
|
-
type: "
|
|
335
|
+
type: "id",
|
|
332
336
|
required: true,
|
|
333
337
|
},
|
|
334
338
|
...schema,
|
|
335
339
|
{
|
|
336
|
-
id:
|
|
340
|
+
id: UtilsServer.encodeID(lastIdNumber + 1, this.salt),
|
|
337
341
|
key: "created_at",
|
|
338
342
|
type: "date",
|
|
339
343
|
required: true,
|
|
340
344
|
},
|
|
341
345
|
{
|
|
342
|
-
id:
|
|
346
|
+
id: UtilsServer.encodeID(lastIdNumber + 2, this.salt),
|
|
343
347
|
key: "updated_at",
|
|
344
348
|
type: "date",
|
|
345
349
|
required: false,
|
|
@@ -388,79 +392,6 @@ export default class Inibase {
|
|
|
388
392
|
schema: Schema,
|
|
389
393
|
skipRequiredField: boolean = false
|
|
390
394
|
): void {
|
|
391
|
-
const validateFieldType = (
|
|
392
|
-
value: any,
|
|
393
|
-
fieldType: FieldType | FieldType[],
|
|
394
|
-
fieldChildrenType?: FieldType | FieldType[]
|
|
395
|
-
): boolean => {
|
|
396
|
-
if (value === null) return true;
|
|
397
|
-
if (Array.isArray(fieldType))
|
|
398
|
-
return Utils.detectFieldType(value, fieldType) !== undefined;
|
|
399
|
-
if (fieldType === "array" && fieldChildrenType && Array.isArray(value))
|
|
400
|
-
return value.some(
|
|
401
|
-
(v) =>
|
|
402
|
-
Utils.detectFieldType(
|
|
403
|
-
v,
|
|
404
|
-
Array.isArray(fieldChildrenType)
|
|
405
|
-
? fieldChildrenType
|
|
406
|
-
: [fieldChildrenType]
|
|
407
|
-
) !== undefined
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
switch (fieldType) {
|
|
411
|
-
case "string":
|
|
412
|
-
return Utils.isString(value);
|
|
413
|
-
case "password":
|
|
414
|
-
return (
|
|
415
|
-
Utils.isNumber(value) ||
|
|
416
|
-
Utils.isString(value) ||
|
|
417
|
-
Utils.isPassword(value)
|
|
418
|
-
);
|
|
419
|
-
case "number":
|
|
420
|
-
return Utils.isNumber(value);
|
|
421
|
-
case "html":
|
|
422
|
-
return Utils.isHTML(value);
|
|
423
|
-
case "ip":
|
|
424
|
-
return Utils.isIP(value);
|
|
425
|
-
case "boolean":
|
|
426
|
-
return Utils.isBoolean(value);
|
|
427
|
-
case "date":
|
|
428
|
-
return Utils.isDate(value);
|
|
429
|
-
case "object":
|
|
430
|
-
return Utils.isObject(value);
|
|
431
|
-
case "array":
|
|
432
|
-
return Array.isArray(value);
|
|
433
|
-
case "email":
|
|
434
|
-
return Utils.isEmail(value);
|
|
435
|
-
case "url":
|
|
436
|
-
return Utils.isURL(value);
|
|
437
|
-
case "table":
|
|
438
|
-
// feat: check if id exists
|
|
439
|
-
if (Array.isArray(value))
|
|
440
|
-
return (
|
|
441
|
-
(Utils.isArrayOfObjects(value) &&
|
|
442
|
-
value.every(
|
|
443
|
-
(element: Data) =>
|
|
444
|
-
element.hasOwnProperty("id") &&
|
|
445
|
-
(Utils.isValidID(element.id) || Utils.isNumber(element.id))
|
|
446
|
-
)) ||
|
|
447
|
-
value.every(Utils.isNumber) ||
|
|
448
|
-
Utils.isValidID(value)
|
|
449
|
-
);
|
|
450
|
-
else if (Utils.isObject(value))
|
|
451
|
-
return (
|
|
452
|
-
value.hasOwnProperty("id") &&
|
|
453
|
-
(Utils.isValidID((value as Data).id) ||
|
|
454
|
-
Utils.isNumber((value as Data).id))
|
|
455
|
-
);
|
|
456
|
-
else return Utils.isNumber(value) || Utils.isValidID(value);
|
|
457
|
-
case "id":
|
|
458
|
-
return Utils.isNumber(value) || Utils.isValidID(value);
|
|
459
|
-
default:
|
|
460
|
-
return false;
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
|
|
464
395
|
if (Utils.isArrayOfObjects(data))
|
|
465
396
|
for (const single_data of data as Data[])
|
|
466
397
|
this.validateData(single_data, schema, skipRequiredField);
|
|
@@ -474,7 +405,7 @@ export default class Inibase {
|
|
|
474
405
|
throw this.throwError("FIELD_REQUIRED", field.key);
|
|
475
406
|
if (
|
|
476
407
|
data.hasOwnProperty(field.key) &&
|
|
477
|
-
!validateFieldType(
|
|
408
|
+
!Utils.validateFieldType(
|
|
478
409
|
data[field.key],
|
|
479
410
|
field.type,
|
|
480
411
|
(field as any)?.children &&
|
|
@@ -525,16 +456,16 @@ export default class Inibase {
|
|
|
525
456
|
value.map((item: any) =>
|
|
526
457
|
Utils.isNumber(item.id)
|
|
527
458
|
? Number(item.id)
|
|
528
|
-
:
|
|
459
|
+
: UtilsServer.decodeID(item.id, this.salt)
|
|
529
460
|
);
|
|
530
461
|
} else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
531
462
|
return value.map((item: number | string) =>
|
|
532
463
|
Utils.isNumber(item)
|
|
533
464
|
? Number(item as string)
|
|
534
|
-
:
|
|
465
|
+
: UtilsServer.decodeID(item as string, this.salt)
|
|
535
466
|
);
|
|
536
467
|
} else if (Utils.isValidID(value))
|
|
537
|
-
return [
|
|
468
|
+
return [UtilsServer.decodeID(value, this.salt)];
|
|
538
469
|
else if (Utils.isNumber(value)) return [Number(value)];
|
|
539
470
|
} else if (data.hasOwnProperty(field.key)) return value;
|
|
540
471
|
} else if (Utils.isArrayOfObjects(field.children))
|
|
@@ -562,20 +493,20 @@ export default class Inibase {
|
|
|
562
493
|
)
|
|
563
494
|
return Utils.isNumber(value.id)
|
|
564
495
|
? Number(value.id)
|
|
565
|
-
:
|
|
496
|
+
: UtilsServer.decodeID(value.id, this.salt);
|
|
566
497
|
} else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
567
498
|
return Utils.isNumber(value)
|
|
568
499
|
? Number(value)
|
|
569
|
-
:
|
|
500
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
570
501
|
break;
|
|
571
502
|
case "password":
|
|
572
|
-
return value.length === 161 ? value :
|
|
503
|
+
return value.length === 161 ? value : UtilsServer.hashPassword(value);
|
|
573
504
|
case "number":
|
|
574
505
|
return Utils.isNumber(value) ? Number(value) : null;
|
|
575
506
|
case "id":
|
|
576
507
|
return Utils.isNumber(value)
|
|
577
|
-
?
|
|
578
|
-
: value;
|
|
508
|
+
? value
|
|
509
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
579
510
|
default:
|
|
580
511
|
return value;
|
|
581
512
|
}
|
|
@@ -726,7 +657,7 @@ export default class Inibase {
|
|
|
726
657
|
let RETURN!: Data | Data[] | null;
|
|
727
658
|
let schema = await this.getTableSchema(tableName);
|
|
728
659
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
729
|
-
const idFilePath = join(this.
|
|
660
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
730
661
|
if (!(await File.isExists(idFilePath))) return null;
|
|
731
662
|
const filterSchemaByColumns = (schema: Schema, columns: string[]): Schema =>
|
|
732
663
|
schema
|
|
@@ -914,21 +845,23 @@ export default class Inibase {
|
|
|
914
845
|
options.columns = (options.columns as string[])
|
|
915
846
|
.filter((column) => column.includes(`${field.key}.*.`))
|
|
916
847
|
.map((column) => column.replace(`${field.key}.*.`, ""));
|
|
917
|
-
|
|
918
|
-
(
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
848
|
+
const [items, total_lines] = await File.get(
|
|
849
|
+
join(
|
|
850
|
+
path,
|
|
851
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
852
|
+
),
|
|
853
|
+
linesNumber,
|
|
854
|
+
field.type,
|
|
855
|
+
(field as FieldDefault & (FieldArrayType | FieldArrayArrayType))
|
|
856
|
+
.children as FieldType | FieldType[],
|
|
857
|
+
this.salt
|
|
858
|
+
);
|
|
859
|
+
|
|
860
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
861
|
+
for (const [index, item] of Object.entries(items)) {
|
|
929
862
|
if (!RETURN[index]) RETURN[index] = {};
|
|
930
|
-
RETURN[index][field.key] =
|
|
931
|
-
? await this.get(field.key,
|
|
863
|
+
RETURN[index][field.key] = item
|
|
864
|
+
? await this.get(field.key, item as number, options)
|
|
932
865
|
: this.getDefaultValue(field);
|
|
933
866
|
}
|
|
934
867
|
} else if (
|
|
@@ -938,40 +871,45 @@ export default class Inibase {
|
|
|
938
871
|
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
939
872
|
)
|
|
940
873
|
)
|
|
941
|
-
)
|
|
942
|
-
|
|
943
|
-
(
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
874
|
+
) {
|
|
875
|
+
const [items, total_lines] = await File.get(
|
|
876
|
+
join(
|
|
877
|
+
path,
|
|
878
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
879
|
+
),
|
|
880
|
+
linesNumber,
|
|
881
|
+
field.type,
|
|
882
|
+
(field as any)?.children,
|
|
883
|
+
this.salt
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
887
|
+
for (const [index, item] of Object.entries(items)) {
|
|
953
888
|
if (!RETURN[index]) RETURN[index] = {};
|
|
954
889
|
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
955
|
-
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
956
892
|
} else if (field.type === "object") {
|
|
957
|
-
Object.entries(
|
|
893
|
+
for (const [index, item] of Object.entries(
|
|
958
894
|
(await getItemsFromSchema(
|
|
959
895
|
path,
|
|
960
896
|
field.children as Schema,
|
|
961
897
|
linesNumber,
|
|
962
898
|
(prefix ?? "") + field.key + "."
|
|
963
899
|
)) ?? {}
|
|
964
|
-
)
|
|
900
|
+
)) {
|
|
965
901
|
if (!RETURN[index]) RETURN[index] = {};
|
|
966
902
|
if (Utils.isObject(item)) {
|
|
967
903
|
if (!Object.values(item).every((i) => i === null))
|
|
968
904
|
RETURN[index][field.key] = item;
|
|
969
905
|
else RETURN[index][field.key] = null;
|
|
970
906
|
} else RETURN[index][field.key] = null;
|
|
971
|
-
}
|
|
907
|
+
}
|
|
972
908
|
} else if (field.type === "table") {
|
|
973
909
|
if (
|
|
974
|
-
(await File.isExists(
|
|
910
|
+
(await File.isExists(
|
|
911
|
+
join(this.folder, this.database, field.key)
|
|
912
|
+
)) &&
|
|
975
913
|
(await File.isExists(
|
|
976
914
|
join(
|
|
977
915
|
path,
|
|
@@ -987,19 +925,21 @@ export default class Inibase {
|
|
|
987
925
|
!column.includes(`${field.key}.*.`)
|
|
988
926
|
)
|
|
989
927
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
990
|
-
|
|
991
|
-
(
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
)
|
|
928
|
+
const [items, total_lines] = await File.get(
|
|
929
|
+
join(
|
|
930
|
+
path,
|
|
931
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
932
|
+
),
|
|
933
|
+
linesNumber,
|
|
934
|
+
"number",
|
|
935
|
+
undefined,
|
|
936
|
+
this.salt
|
|
937
|
+
);
|
|
938
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
939
|
+
for (const [index, item] of Object.entries(items)) {
|
|
1000
940
|
if (!RETURN[index]) RETURN[index] = {};
|
|
1001
|
-
RETURN[index][field.key] =
|
|
1002
|
-
? await this.get(field.key,
|
|
941
|
+
RETURN[index][field.key] = item
|
|
942
|
+
? await this.get(field.key, item as number, options)
|
|
1003
943
|
: this.getDefaultValue(field);
|
|
1004
944
|
}
|
|
1005
945
|
}
|
|
@@ -1007,21 +947,21 @@ export default class Inibase {
|
|
|
1007
947
|
await File.isExists(
|
|
1008
948
|
join(path, File.encodeFileName((prefix ?? "") + field.key, "inib"))
|
|
1009
949
|
)
|
|
1010
|
-
)
|
|
1011
|
-
|
|
1012
|
-
(
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
).forEach(([index, item]) => {
|
|
950
|
+
) {
|
|
951
|
+
const [items, total_lines] = await File.get(
|
|
952
|
+
join(path, File.encodeFileName((prefix ?? "") + field.key, "inib")),
|
|
953
|
+
linesNumber,
|
|
954
|
+
field.type,
|
|
955
|
+
(field as any)?.children,
|
|
956
|
+
this.salt
|
|
957
|
+
);
|
|
958
|
+
|
|
959
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
960
|
+
for (const [index, item] of Object.entries(items)) {
|
|
1022
961
|
if (!RETURN[index]) RETURN[index] = {};
|
|
1023
962
|
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
1024
|
-
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
1025
965
|
}
|
|
1026
966
|
return RETURN;
|
|
1027
967
|
};
|
|
@@ -1029,7 +969,7 @@ export default class Inibase {
|
|
|
1029
969
|
// Display all data
|
|
1030
970
|
RETURN = Object.values(
|
|
1031
971
|
await getItemsFromSchema(
|
|
1032
|
-
join(this.
|
|
972
|
+
join(this.folder, this.database, tableName),
|
|
1033
973
|
schema,
|
|
1034
974
|
Array.from(
|
|
1035
975
|
{ length: options.per_page },
|
|
@@ -1048,14 +988,14 @@ export default class Inibase {
|
|
|
1048
988
|
"[]",
|
|
1049
989
|
Utils.isNumber(Ids)
|
|
1050
990
|
? Ids.map((id) => Number(id as string))
|
|
1051
|
-
: Ids.map((id) =>
|
|
991
|
+
: Ids.map((id) => UtilsServer.decodeID(id as string, this.salt)),
|
|
1052
992
|
undefined,
|
|
1053
993
|
"number",
|
|
1054
994
|
undefined,
|
|
1055
995
|
Ids.length,
|
|
1056
996
|
0,
|
|
1057
997
|
false,
|
|
1058
|
-
this.
|
|
998
|
+
this.salt
|
|
1059
999
|
);
|
|
1060
1000
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1061
1001
|
throw this.throwError(
|
|
@@ -1064,7 +1004,7 @@ export default class Inibase {
|
|
|
1064
1004
|
);
|
|
1065
1005
|
RETURN = Object.values(
|
|
1066
1006
|
(await getItemsFromSchema(
|
|
1067
|
-
join(this.
|
|
1007
|
+
join(this.folder, this.database, tableName),
|
|
1068
1008
|
schema,
|
|
1069
1009
|
Object.keys(lineNumbers).map(Number)
|
|
1070
1010
|
)) ?? {}
|
|
@@ -1257,9 +1197,10 @@ export default class Inibase {
|
|
|
1257
1197
|
searchOperator = "=";
|
|
1258
1198
|
searchComparedAtValue = value as number | boolean;
|
|
1259
1199
|
}
|
|
1260
|
-
const [searchResult,
|
|
1200
|
+
const [searchResult, total_lines] = await File.search(
|
|
1261
1201
|
join(
|
|
1262
|
-
this.
|
|
1202
|
+
this.folder,
|
|
1203
|
+
this.database,
|
|
1263
1204
|
tableName,
|
|
1264
1205
|
File.encodeFileName(key, "inib")
|
|
1265
1206
|
),
|
|
@@ -1271,12 +1212,11 @@ export default class Inibase {
|
|
|
1271
1212
|
options.per_page,
|
|
1272
1213
|
(options.page as number) - 1 * (options.per_page as number) + 1,
|
|
1273
1214
|
true,
|
|
1274
|
-
this.
|
|
1215
|
+
this.salt
|
|
1275
1216
|
);
|
|
1276
1217
|
if (searchResult) {
|
|
1277
1218
|
RETURN = Utils.deepMerge(RETURN, searchResult);
|
|
1278
|
-
|
|
1279
|
-
this.pageInfoArray[key].total_items = totlaItems;
|
|
1219
|
+
this.totalItems[tableName + "-" + key] = total_lines;
|
|
1280
1220
|
}
|
|
1281
1221
|
if (allTrue && index > 0) {
|
|
1282
1222
|
if (!Object.keys(RETURN).length) RETURN = {};
|
|
@@ -1295,30 +1235,12 @@ export default class Inibase {
|
|
|
1295
1235
|
if (RETURN) {
|
|
1296
1236
|
if (onlyLinesNumbers) return Object.keys(RETURN).map(Number);
|
|
1297
1237
|
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]).map(
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
greatestColumnTotalItems = alreadyExistsColumns.reduce(
|
|
1301
|
-
(maxItem: string, currentItem: string) =>
|
|
1302
|
-
this.pageInfoArray[currentItem]?.total_items ||
|
|
1303
|
-
(0 > (this.pageInfoArray[maxItem]?.total_items || 0) &&
|
|
1304
|
-
this.pageInfoArray[currentItem].total_items)
|
|
1305
|
-
? currentItem
|
|
1306
|
-
: maxItem,
|
|
1307
|
-
""
|
|
1308
|
-
);
|
|
1309
|
-
if (greatestColumnTotalItems)
|
|
1310
|
-
this.pageInfo = {
|
|
1311
|
-
...(({ columns, ...restOfOptions }) => restOfOptions)(options),
|
|
1312
|
-
...this.pageInfoArray[greatestColumnTotalItems],
|
|
1313
|
-
total_pages: Math.ceil(
|
|
1314
|
-
this.pageInfoArray[greatestColumnTotalItems].total_items /
|
|
1315
|
-
options.per_page
|
|
1316
|
-
),
|
|
1317
|
-
};
|
|
1238
|
+
(key) => File.decodeFileName(parse(key).name)
|
|
1239
|
+
);
|
|
1318
1240
|
RETURN = Object.values(
|
|
1319
1241
|
Utils.deepMerge(
|
|
1320
1242
|
await getItemsFromSchema(
|
|
1321
|
-
join(this.
|
|
1243
|
+
join(this.folder, this.database, tableName),
|
|
1322
1244
|
schema.filter(
|
|
1323
1245
|
(field) => !alreadyExistsColumns.includes(field.key)
|
|
1324
1246
|
),
|
|
@@ -1335,15 +1257,18 @@ export default class Inibase {
|
|
|
1335
1257
|
(Array.isArray(RETURN) && !RETURN.length)
|
|
1336
1258
|
)
|
|
1337
1259
|
return null;
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1260
|
+
|
|
1261
|
+
const greatestTotalItems = Math.max(
|
|
1262
|
+
...Object.entries(this.totalItems)
|
|
1263
|
+
.filter(([k]) => k.startsWith(tableName + "-"))
|
|
1264
|
+
.map(([, v]) => v)
|
|
1265
|
+
);
|
|
1266
|
+
this.pageInfo = {
|
|
1267
|
+
...(({ columns, ...restOfOptions }) => restOfOptions)(options),
|
|
1268
|
+
total_pages: Math.ceil(greatestTotalItems / options.per_page),
|
|
1269
|
+
total: greatestTotalItems,
|
|
1270
|
+
};
|
|
1271
|
+
return RETURN;
|
|
1347
1272
|
}
|
|
1348
1273
|
|
|
1349
1274
|
public async post(
|
|
@@ -1352,14 +1277,19 @@ export default class Inibase {
|
|
|
1352
1277
|
options: Options = {
|
|
1353
1278
|
page: 1,
|
|
1354
1279
|
per_page: 15,
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1280
|
+
},
|
|
1281
|
+
returnPostedData: boolean = true
|
|
1282
|
+
): Promise<Data | Data[] | null | void> {
|
|
1357
1283
|
const schema = await this.getTableSchema(tableName);
|
|
1358
1284
|
let RETURN: Data | Data[] | null | undefined;
|
|
1359
1285
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1360
|
-
const idFilePath = join(this.
|
|
1286
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1361
1287
|
let last_id = (await File.isExists(idFilePath))
|
|
1362
|
-
? Number(
|
|
1288
|
+
? Number(
|
|
1289
|
+
Object.values(
|
|
1290
|
+
await File.get(idFilePath, -1, "number", undefined, this.salt)
|
|
1291
|
+
)[0]
|
|
1292
|
+
)
|
|
1363
1293
|
: 0;
|
|
1364
1294
|
if (Utils.isArrayOfObjects(data))
|
|
1365
1295
|
(data as Data[]).forEach((single_data, index) => {
|
|
@@ -1379,7 +1309,7 @@ export default class Inibase {
|
|
|
1379
1309
|
if (!RETURN) throw this.throwError("NO_DATA");
|
|
1380
1310
|
RETURN = this.formatData(RETURN, schema);
|
|
1381
1311
|
const pathesContents = this.joinPathesContents(
|
|
1382
|
-
join(this.
|
|
1312
|
+
join(this.folder, this.database, tableName),
|
|
1383
1313
|
RETURN
|
|
1384
1314
|
);
|
|
1385
1315
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
@@ -1388,13 +1318,14 @@ export default class Inibase {
|
|
|
1388
1318
|
(Array.isArray(content) ? content.join("\n") : content ?? "") + "\n"
|
|
1389
1319
|
);
|
|
1390
1320
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1321
|
+
if (returnPostedData)
|
|
1322
|
+
return this.get(
|
|
1323
|
+
tableName,
|
|
1324
|
+
Utils.isArrayOfObjects(RETURN)
|
|
1325
|
+
? RETURN.map((data: Data) => data.id)
|
|
1326
|
+
: ((RETURN as Data).id as number),
|
|
1327
|
+
options
|
|
1328
|
+
);
|
|
1398
1329
|
}
|
|
1399
1330
|
|
|
1400
1331
|
public async put(
|
|
@@ -1404,11 +1335,12 @@ export default class Inibase {
|
|
|
1404
1335
|
options: Options = {
|
|
1405
1336
|
page: 1,
|
|
1406
1337
|
per_page: 15,
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1338
|
+
},
|
|
1339
|
+
returnPostedData: boolean = true
|
|
1340
|
+
): Promise<Data | Data[] | null | void> {
|
|
1409
1341
|
const schema = await this.getTableSchema(tableName);
|
|
1410
1342
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1411
|
-
const idFilePath = join(this.
|
|
1343
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1412
1344
|
if (!(await File.isExists(idFilePath)))
|
|
1413
1345
|
throw this.throwError("NO_ITEMS", tableName);
|
|
1414
1346
|
data = this.formatData(data, schema, true);
|
|
@@ -1431,11 +1363,11 @@ export default class Inibase {
|
|
|
1431
1363
|
return this.put(
|
|
1432
1364
|
tableName,
|
|
1433
1365
|
data,
|
|
1434
|
-
|
|
1366
|
+
UtilsServer.decodeID((data as Data).id as string, this.salt)
|
|
1435
1367
|
);
|
|
1436
1368
|
} else {
|
|
1437
1369
|
const pathesContents = this.joinPathesContents(
|
|
1438
|
-
join(this.
|
|
1370
|
+
join(this.folder, this.database, tableName),
|
|
1439
1371
|
Utils.isArrayOfObjects(data)
|
|
1440
1372
|
? (data as Data[]).map((item) => ({
|
|
1441
1373
|
...(({ id, ...restOfData }) => restOfData)(item),
|
|
@@ -1448,7 +1380,7 @@ export default class Inibase {
|
|
|
1448
1380
|
);
|
|
1449
1381
|
for (const [path, content] of Object.entries(pathesContents))
|
|
1450
1382
|
await File.replace(path, content);
|
|
1451
|
-
return this.get(tableName, where, options);
|
|
1383
|
+
if (returnPostedData) return this.get(tableName, where, options);
|
|
1452
1384
|
}
|
|
1453
1385
|
} else if (Utils.isValidID(where)) {
|
|
1454
1386
|
let Ids = where as string | string[];
|
|
@@ -1456,14 +1388,14 @@ export default class Inibase {
|
|
|
1456
1388
|
const [lineNumbers, countItems] = await File.search(
|
|
1457
1389
|
idFilePath,
|
|
1458
1390
|
"[]",
|
|
1459
|
-
Ids.map((id) =>
|
|
1391
|
+
Ids.map((id) => UtilsServer.decodeID(id, this.salt)),
|
|
1460
1392
|
undefined,
|
|
1461
1393
|
"number",
|
|
1462
1394
|
undefined,
|
|
1463
1395
|
Ids.length,
|
|
1464
1396
|
0,
|
|
1465
1397
|
false,
|
|
1466
|
-
this.
|
|
1398
|
+
this.salt
|
|
1467
1399
|
);
|
|
1468
1400
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1469
1401
|
throw this.throwError("INVALID_ID");
|
|
@@ -1473,7 +1405,7 @@ export default class Inibase {
|
|
|
1473
1405
|
const pathesContents = Object.fromEntries(
|
|
1474
1406
|
Object.entries(
|
|
1475
1407
|
this.joinPathesContents(
|
|
1476
|
-
join(this.
|
|
1408
|
+
join(this.folder, this.database, tableName),
|
|
1477
1409
|
Utils.isArrayOfObjects(data)
|
|
1478
1410
|
? (data as Data[]).map((item) => ({
|
|
1479
1411
|
...item,
|
|
@@ -1494,7 +1426,7 @@ export default class Inibase {
|
|
|
1494
1426
|
);
|
|
1495
1427
|
for (const [path, content] of Object.entries(pathesContents))
|
|
1496
1428
|
await File.replace(path, content);
|
|
1497
|
-
return this.get(tableName, where, options);
|
|
1429
|
+
if (returnPostedData) return this.get(tableName, where, options);
|
|
1498
1430
|
} else if (typeof where === "object" && !Array.isArray(where)) {
|
|
1499
1431
|
const lineNumbers = this.get(tableName, where, undefined, true);
|
|
1500
1432
|
if (!lineNumbers || !Array.isArray(lineNumbers) || !lineNumbers.length)
|
|
@@ -1510,16 +1442,16 @@ export default class Inibase {
|
|
|
1510
1442
|
): Promise<string | string[] | null> {
|
|
1511
1443
|
const schema = await this.getTableSchema(tableName);
|
|
1512
1444
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1513
|
-
const idFilePath = join(this.
|
|
1445
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1514
1446
|
if (!(await File.isExists(idFilePath)))
|
|
1515
1447
|
throw this.throwError("NO_ITEMS", tableName);
|
|
1516
1448
|
if (!where) {
|
|
1517
|
-
const files = await readdir(join(this.
|
|
1449
|
+
const files = await readdir(join(this.folder, this.database, tableName));
|
|
1518
1450
|
if (files.length) {
|
|
1519
1451
|
for (const file in files.filter(
|
|
1520
|
-
(fileName: string) => fileName !== "schema
|
|
1452
|
+
(fileName: string) => fileName !== "schema"
|
|
1521
1453
|
))
|
|
1522
|
-
await unlink(join(this.
|
|
1454
|
+
await unlink(join(this.folder, this.database, tableName, file));
|
|
1523
1455
|
}
|
|
1524
1456
|
return "*";
|
|
1525
1457
|
} else if (Utils.isValidID(where)) {
|
|
@@ -1528,14 +1460,14 @@ export default class Inibase {
|
|
|
1528
1460
|
const [lineNumbers, countItems] = await File.search(
|
|
1529
1461
|
idFilePath,
|
|
1530
1462
|
"[]",
|
|
1531
|
-
Ids.map((id) =>
|
|
1463
|
+
Ids.map((id) => UtilsServer.decodeID(id, this.salt)),
|
|
1532
1464
|
undefined,
|
|
1533
1465
|
"number",
|
|
1534
1466
|
undefined,
|
|
1535
1467
|
Ids.length,
|
|
1536
1468
|
0,
|
|
1537
1469
|
false,
|
|
1538
|
-
this.
|
|
1470
|
+
this.salt
|
|
1539
1471
|
);
|
|
1540
1472
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1541
1473
|
throw this.throwError("INVALID_ID");
|
|
@@ -1545,24 +1477,26 @@ export default class Inibase {
|
|
|
1545
1477
|
where as string | string[]
|
|
1546
1478
|
);
|
|
1547
1479
|
} else if (Utils.isNumber(where)) {
|
|
1548
|
-
const files = await readdir(join(this.
|
|
1480
|
+
const files = await readdir(join(this.folder, this.database, tableName));
|
|
1549
1481
|
if (files.length) {
|
|
1550
1482
|
if (!_id)
|
|
1551
1483
|
_id = Object.values(
|
|
1552
1484
|
await File.get(
|
|
1553
|
-
join(this.
|
|
1485
|
+
join(this.folder, this.database, tableName, "id.inib"),
|
|
1554
1486
|
where as number | number[],
|
|
1555
|
-
"number"
|
|
1487
|
+
"number",
|
|
1488
|
+
undefined,
|
|
1489
|
+
this.salt
|
|
1556
1490
|
)
|
|
1557
1491
|
)
|
|
1558
1492
|
.map(Number)
|
|
1559
|
-
.map((id) =>
|
|
1493
|
+
.map((id) => UtilsServer.encodeID(id, this.salt));
|
|
1560
1494
|
for (const file of files.filter(
|
|
1561
1495
|
(fileName: string) =>
|
|
1562
|
-
fileName.endsWith(".inib") && fileName !== "schema
|
|
1496
|
+
fileName.endsWith(".inib") && fileName !== "schema"
|
|
1563
1497
|
))
|
|
1564
1498
|
await File.remove(
|
|
1565
|
-
join(this.
|
|
1499
|
+
join(this.folder, this.database, tableName, file),
|
|
1566
1500
|
where as number | number[]
|
|
1567
1501
|
);
|
|
1568
1502
|
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|