inibase 1.0.0-rc.22 → 1.0.0-rc.24
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 +22 -10
- package/dist/file.d.ts +10 -10
- package/dist/file.js +192 -284
- package/dist/index.d.ts +6 -5
- package/dist/index.js +182 -137
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +3 -12
- package/dist/utils.server.d.ts +2 -2
- package/dist/utils.server.js +5 -5
- package/package.json +39 -35
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { unlink, rename, readFile, writeFile, mkdir, readdir, } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { existsSync, appendFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { scryptSync, randomBytes } from "node:crypto";
|
|
4
5
|
import File from "./file.js";
|
|
5
6
|
import Utils from "./utils.js";
|
|
6
7
|
import UtilsServer from "./utils.server.js";
|
|
@@ -19,7 +20,13 @@ export default class Inibase {
|
|
|
19
20
|
this.cache = new Map();
|
|
20
21
|
this.totalItems = {};
|
|
21
22
|
this.pageInfo = { page: 1, per_page: 15 };
|
|
22
|
-
|
|
23
|
+
if (!existsSync(".env") || !process.env.INIBASE_SECRET) {
|
|
24
|
+
this.salt = scryptSync(randomBytes(16), randomBytes(16), 32);
|
|
25
|
+
appendFileSync(".env", `INIBASE_SECRET=${this.salt.toString("hex")}\n`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.salt = Buffer.from(process.env.INIBASE_SECRET, "hex");
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
throwError(code, variable, language = "en") {
|
|
25
32
|
const errorMessages = {
|
|
@@ -50,7 +57,7 @@ export default class Inibase {
|
|
|
50
57
|
const decodeIdFromSchema = (schema) => schema.map((field) => {
|
|
51
58
|
if (field.children && Utils.isArrayOfObjects(field.children))
|
|
52
59
|
field.children = decodeIdFromSchema(field.children);
|
|
53
|
-
if (!Utils.isNumber(field.id))
|
|
60
|
+
if (field.id && !Utils.isNumber(field.id))
|
|
54
61
|
field.id = UtilsServer.decodeID(field.id, this.salt);
|
|
55
62
|
return field;
|
|
56
63
|
});
|
|
@@ -72,7 +79,7 @@ export default class Inibase {
|
|
|
72
79
|
RETURN[UtilsServer.decodeID(field.id, this.salt)] =
|
|
73
80
|
(prefix ?? "") + field.key + ".inib";
|
|
74
81
|
return RETURN;
|
|
75
|
-
}, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath(await this.getTableSchema(tableName)), schemaToIdsPath(schema));
|
|
82
|
+
}, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath((await this.getTableSchema(tableName)) ?? []), schemaToIdsPath(schema));
|
|
76
83
|
if (replaceOldPathes)
|
|
77
84
|
for await (const [oldPath, newPath] of Object.entries(replaceOldPathes))
|
|
78
85
|
if (await File.isExists(join(TablePath, oldPath)))
|
|
@@ -88,7 +95,7 @@ export default class Inibase {
|
|
|
88
95
|
this.cache.set(TableSchemaPath, await readFile(TableSchemaPath, "utf8"));
|
|
89
96
|
if (!this.cache.get(TableSchemaPath))
|
|
90
97
|
return undefined;
|
|
91
|
-
const schema = JSON.parse(this.cache.get(TableSchemaPath)), lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
98
|
+
const schema = JSON.parse(this.cache.get(TableSchemaPath) ?? ""), lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
92
99
|
return [
|
|
93
100
|
{
|
|
94
101
|
id: UtilsServer.encodeID(0, this.salt),
|
|
@@ -149,7 +156,7 @@ export default class Inibase {
|
|
|
149
156
|
throw this.throwError("FIELD_REQUIRED", key);
|
|
150
157
|
if (data.hasOwnProperty(key) &&
|
|
151
158
|
!Utils.validateFieldType(data[key], type, children && !Utils.isArrayOfObjects(children) ? children : undefined))
|
|
152
|
-
throw this.throwError("INVALID_TYPE", key);
|
|
159
|
+
throw this.throwError("INVALID_TYPE", key + " " + type + " " + data[key]);
|
|
153
160
|
if ((type === "array" || type === "object") &&
|
|
154
161
|
children &&
|
|
155
162
|
Utils.isArrayOfObjects(children))
|
|
@@ -157,85 +164,87 @@ export default class Inibase {
|
|
|
157
164
|
}
|
|
158
165
|
}
|
|
159
166
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
value.map((item) => Utils.isNumber(item.id)
|
|
167
|
+
formatField(value, field, formatOnlyAvailiableKeys) {
|
|
168
|
+
if (Array.isArray(field.type))
|
|
169
|
+
field.type = Utils.detectFieldType(value, field.type) ?? field.type[0];
|
|
170
|
+
switch (field.type) {
|
|
171
|
+
case "array":
|
|
172
|
+
if (!Array.isArray(value))
|
|
173
|
+
value = [value];
|
|
174
|
+
if (typeof field.children === "string") {
|
|
175
|
+
if (field.type === "array" && field.children === "table") {
|
|
176
|
+
if (Array.isArray(value)) {
|
|
177
|
+
if (Utils.isArrayOfObjects(value)) {
|
|
178
|
+
if (value.every((item) => item.hasOwnProperty("id") &&
|
|
179
|
+
(Utils.isValidID(item.id) || Utils.isNumber(item.id))))
|
|
180
|
+
value.map((item) => item.id
|
|
181
|
+
? Utils.isNumber(item.id)
|
|
176
182
|
? Number(item.id)
|
|
177
|
-
: UtilsServer.decodeID(item.id, this.salt)
|
|
178
|
-
|
|
179
|
-
else if (value.every(Utils.isValidID) ||
|
|
180
|
-
value.every(Utils.isNumber))
|
|
181
|
-
return value.map((item) => Utils.isNumber(item)
|
|
182
|
-
? Number(item)
|
|
183
|
-
: UtilsServer.decodeID(item, this.salt));
|
|
183
|
+
: UtilsServer.decodeID(item.id, this.salt)
|
|
184
|
+
: null);
|
|
184
185
|
}
|
|
185
|
-
else if (Utils.isValidID
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
186
|
+
else if (value.every(Utils.isValidID) ||
|
|
187
|
+
value.every(Utils.isNumber))
|
|
188
|
+
return value.map((item) => Utils.isNumber(item)
|
|
189
|
+
? Number(item)
|
|
190
|
+
: UtilsServer.decodeID(item, this.salt));
|
|
189
191
|
}
|
|
190
|
-
else if (
|
|
191
|
-
return value;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return this.formatData(value, field.children, formatOnlyAvailiableKeys);
|
|
195
|
-
else if (Array.isArray(field.children))
|
|
196
|
-
return Array.isArray(value) ? value : [value];
|
|
197
|
-
break;
|
|
198
|
-
case "object":
|
|
199
|
-
if (Utils.isArrayOfObjects(field.children))
|
|
200
|
-
return this.formatData(value, field.children, formatOnlyAvailiableKeys);
|
|
201
|
-
break;
|
|
202
|
-
case "table":
|
|
203
|
-
if (Array.isArray(value))
|
|
204
|
-
value = value[0];
|
|
205
|
-
if (Utils.isObject(value)) {
|
|
206
|
-
if (value.hasOwnProperty("id") &&
|
|
207
|
-
(Utils.isValidID(value.id) ||
|
|
208
|
-
Utils.isNumber(value.id)))
|
|
209
|
-
return Utils.isNumber(value.id)
|
|
210
|
-
? Number(value.id)
|
|
211
|
-
: UtilsServer.decodeID(value.id, this.salt);
|
|
192
|
+
else if (Utils.isValidID(value))
|
|
193
|
+
return [UtilsServer.decodeID(value, this.salt)];
|
|
194
|
+
else if (Utils.isNumber(value))
|
|
195
|
+
return [Number(value)];
|
|
212
196
|
}
|
|
213
|
-
else if (
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
value
|
|
197
|
+
else if (value.hasOwnProperty(field.key))
|
|
198
|
+
return value;
|
|
199
|
+
}
|
|
200
|
+
else if (Utils.isArrayOfObjects(field.children))
|
|
201
|
+
return this.formatData(value, field.children, formatOnlyAvailiableKeys);
|
|
202
|
+
else if (Array.isArray(field.children))
|
|
203
|
+
return Array.isArray(value) ? value : [value];
|
|
204
|
+
break;
|
|
205
|
+
case "object":
|
|
206
|
+
if (Utils.isArrayOfObjects(field.children))
|
|
207
|
+
return this.formatData(value, field.children, formatOnlyAvailiableKeys);
|
|
208
|
+
break;
|
|
209
|
+
case "table":
|
|
210
|
+
if (Array.isArray(value))
|
|
211
|
+
value = value[0];
|
|
212
|
+
if (Utils.isObject(value)) {
|
|
213
|
+
if (value.hasOwnProperty("id") &&
|
|
214
|
+
(Utils.isValidID(value.id) ||
|
|
215
|
+
Utils.isNumber(value.id)))
|
|
216
|
+
return Utils.isNumber(value.id)
|
|
217
|
+
? Number(value.id)
|
|
218
|
+
: UtilsServer.decodeID(value.id, this.salt);
|
|
219
|
+
}
|
|
220
|
+
else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
231
221
|
return Utils.isNumber(value)
|
|
232
|
-
? value
|
|
222
|
+
? Number(value)
|
|
233
223
|
: UtilsServer.decodeID(value, this.salt);
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
break;
|
|
225
|
+
case "password":
|
|
226
|
+
if (Array.isArray(value))
|
|
227
|
+
value = value[0];
|
|
228
|
+
return typeof value === "string" && value.length === 161
|
|
229
|
+
? value
|
|
230
|
+
: UtilsServer.hashPassword(String(value));
|
|
231
|
+
case "number":
|
|
232
|
+
if (Array.isArray(value))
|
|
233
|
+
value = value[0];
|
|
234
|
+
return Utils.isNumber(value) ? Number(value) : null;
|
|
235
|
+
case "id":
|
|
236
|
+
if (Array.isArray(value))
|
|
237
|
+
value = value[0];
|
|
238
|
+
return Utils.isNumber(value)
|
|
239
|
+
? value
|
|
240
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
241
|
+
default:
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
formatData(data, schema, formatOnlyAvailiableKeys) {
|
|
247
|
+
this.validateData(data, schema, formatOnlyAvailiableKeys);
|
|
239
248
|
if (Utils.isArrayOfObjects(data))
|
|
240
249
|
return data.map((single_data) => this.formatData(single_data, schema, formatOnlyAvailiableKeys));
|
|
241
250
|
else if (Utils.isObject(data)) {
|
|
@@ -247,7 +256,7 @@ export default class Inibase {
|
|
|
247
256
|
RETURN[field.key] = this.getDefaultValue(field);
|
|
248
257
|
continue;
|
|
249
258
|
}
|
|
250
|
-
RETURN[field.key] = formatField(data[field.key], field);
|
|
259
|
+
RETURN[field.key] = this.formatField(data[field.key], field, formatOnlyAvailiableKeys);
|
|
251
260
|
}
|
|
252
261
|
return RETURN;
|
|
253
262
|
}
|
|
@@ -382,22 +391,24 @@ export default class Inibase {
|
|
|
382
391
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
383
392
|
const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field.children, this.salt);
|
|
384
393
|
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
RETURN[index]
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
394
|
+
if (items)
|
|
395
|
+
for await (const [index, item] of Object.entries(items)) {
|
|
396
|
+
if (!RETURN[index])
|
|
397
|
+
RETURN[index] = {};
|
|
398
|
+
RETURN[index][field.key] = item
|
|
399
|
+
? await this.get(field.key, item, options)
|
|
400
|
+
: this.getDefaultValue(field);
|
|
401
|
+
}
|
|
392
402
|
}
|
|
393
403
|
else if (await File.isExists(join(path, (prefix ?? "") + field.key + ".inib"))) {
|
|
394
404
|
const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field?.children, this.salt);
|
|
395
405
|
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
RETURN[index]
|
|
399
|
-
|
|
400
|
-
|
|
406
|
+
if (items)
|
|
407
|
+
for (const [index, item] of Object.entries(items)) {
|
|
408
|
+
if (!RETURN[index])
|
|
409
|
+
RETURN[index] = {};
|
|
410
|
+
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
411
|
+
}
|
|
401
412
|
}
|
|
402
413
|
}
|
|
403
414
|
else if (field.type === "object") {
|
|
@@ -424,23 +435,30 @@ export default class Inibase {
|
|
|
424
435
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
425
436
|
const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, "number", undefined, this.salt);
|
|
426
437
|
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
RETURN[index]
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
438
|
+
if (items)
|
|
439
|
+
for await (const [index, item] of Object.entries(items)) {
|
|
440
|
+
if (!RETURN[index])
|
|
441
|
+
RETURN[index] = {};
|
|
442
|
+
RETURN[index][field.key] = item
|
|
443
|
+
? await this.get(field.key, item, options)
|
|
444
|
+
: this.getDefaultValue(field);
|
|
445
|
+
}
|
|
434
446
|
}
|
|
435
447
|
}
|
|
436
448
|
else if (await File.isExists(join(path, (prefix ?? "") + field.key + ".inib"))) {
|
|
437
449
|
const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field?.children, this.salt);
|
|
438
450
|
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
RETURN[index]
|
|
442
|
-
|
|
443
|
-
|
|
451
|
+
if (items)
|
|
452
|
+
for (const [index, item] of Object.entries(items)) {
|
|
453
|
+
if (!RETURN[index])
|
|
454
|
+
RETURN[index] = {};
|
|
455
|
+
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
456
|
+
}
|
|
457
|
+
else
|
|
458
|
+
RETURN = Object.fromEntries(Object.entries(RETURN).map(([index, data]) => [
|
|
459
|
+
index,
|
|
460
|
+
{ ...data, [field.key]: this.getDefaultValue(field) },
|
|
461
|
+
]));
|
|
444
462
|
}
|
|
445
463
|
}
|
|
446
464
|
return RETURN;
|
|
@@ -528,8 +546,8 @@ export default class Inibase {
|
|
|
528
546
|
let searchOperator = undefined, searchComparedAtValue = undefined, searchLogicalOperator = undefined;
|
|
529
547
|
if (Utils.isObject(value)) {
|
|
530
548
|
if (value?.or &&
|
|
531
|
-
Array.isArray(value
|
|
532
|
-
const searchCriteria = value
|
|
549
|
+
Array.isArray(value?.or)) {
|
|
550
|
+
const searchCriteria = (value?.or)
|
|
533
551
|
.map((single_or) => typeof single_or === "string"
|
|
534
552
|
? this.FormatObjectCriteriaValue(single_or)
|
|
535
553
|
: ["=", single_or])
|
|
@@ -539,11 +557,11 @@ export default class Inibase {
|
|
|
539
557
|
searchComparedAtValue = searchCriteria.map((single_or) => single_or[1]);
|
|
540
558
|
searchLogicalOperator = "or";
|
|
541
559
|
}
|
|
542
|
-
delete value
|
|
560
|
+
delete value?.or;
|
|
543
561
|
}
|
|
544
562
|
if (value?.and &&
|
|
545
|
-
Array.isArray(value
|
|
546
|
-
const searchCriteria = value
|
|
563
|
+
Array.isArray(value?.and)) {
|
|
564
|
+
const searchCriteria = (value?.and)
|
|
547
565
|
.map((single_and) => typeof single_and === "string"
|
|
548
566
|
? this.FormatObjectCriteriaValue(single_and)
|
|
549
567
|
: ["=", single_and])
|
|
@@ -553,7 +571,7 @@ export default class Inibase {
|
|
|
553
571
|
searchComparedAtValue = searchCriteria.map((single_and) => single_and[1]);
|
|
554
572
|
searchLogicalOperator = "and";
|
|
555
573
|
}
|
|
556
|
-
delete value
|
|
574
|
+
delete value?.and;
|
|
557
575
|
}
|
|
558
576
|
}
|
|
559
577
|
else if (Array.isArray(value)) {
|
|
@@ -579,9 +597,14 @@ export default class Inibase {
|
|
|
579
597
|
searchOperator = "=";
|
|
580
598
|
searchComparedAtValue = value;
|
|
581
599
|
}
|
|
582
|
-
const [searchResult, total_lines] = await File.search(join(this.folder, this.database, tableName, key + ".inib"), searchOperator, searchComparedAtValue, searchLogicalOperator, field?.type, field?.children, options.per_page, options.page - 1 * options.per_page + 1, true, this.salt);
|
|
600
|
+
const [searchResult, total_lines] = await File.search(join(this.folder, this.database, tableName, key + ".inib"), searchOperator ?? "=", searchComparedAtValue ?? null, searchLogicalOperator, field?.type, field?.children, options.per_page, options.page - 1 * options.per_page + 1, true, this.salt);
|
|
583
601
|
if (searchResult) {
|
|
584
|
-
RETURN = Utils.deepMerge(RETURN, searchResult)
|
|
602
|
+
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).map(([id, value]) => [
|
|
603
|
+
id,
|
|
604
|
+
{
|
|
605
|
+
[key]: value,
|
|
606
|
+
},
|
|
607
|
+
])));
|
|
585
608
|
this.totalItems[tableName + "-" + key] = total_lines;
|
|
586
609
|
}
|
|
587
610
|
if (allTrue && index > 0) {
|
|
@@ -599,12 +622,13 @@ export default class Inibase {
|
|
|
599
622
|
page: 1,
|
|
600
623
|
per_page: 15,
|
|
601
624
|
}, onlyOne, onlyLinesNumbers) {
|
|
602
|
-
if (
|
|
603
|
-
options.columns
|
|
604
|
-
|
|
605
|
-
options.columns
|
|
606
|
-
|
|
607
|
-
|
|
625
|
+
if (options.columns) {
|
|
626
|
+
if (!Array.isArray(options.columns))
|
|
627
|
+
options.columns = [options.columns];
|
|
628
|
+
if (options.columns.length &&
|
|
629
|
+
!options.columns.includes("id"))
|
|
630
|
+
options.columns.push("id");
|
|
631
|
+
}
|
|
608
632
|
if (!options.page)
|
|
609
633
|
options.page = 1;
|
|
610
634
|
if (!options.per_page)
|
|
@@ -635,7 +659,7 @@ export default class Inibase {
|
|
|
635
659
|
return null;
|
|
636
660
|
})
|
|
637
661
|
.filter((i) => i);
|
|
638
|
-
if (options.columns.length)
|
|
662
|
+
if (options.columns && options.columns.length)
|
|
639
663
|
schema = filterSchemaByColumns(schema, options.columns);
|
|
640
664
|
if (!where) {
|
|
641
665
|
// Display all data
|
|
@@ -658,7 +682,7 @@ export default class Inibase {
|
|
|
658
682
|
? Object.keys(lineNumbers).map(Number)
|
|
659
683
|
: null;
|
|
660
684
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
|
|
661
|
-
if (RETURN.length && !Array.isArray(where))
|
|
685
|
+
if (RETURN && RETURN.length && !Array.isArray(where))
|
|
662
686
|
RETURN = RETURN[0];
|
|
663
687
|
}
|
|
664
688
|
else if (Utils.isObject(where)) {
|
|
@@ -667,7 +691,7 @@ export default class Inibase {
|
|
|
667
691
|
if (RETURN) {
|
|
668
692
|
if (onlyLinesNumbers)
|
|
669
693
|
return Object.keys(RETURN).map(Number);
|
|
670
|
-
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0])
|
|
694
|
+
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]);
|
|
671
695
|
RETURN = Object.values(Utils.deepMerge(RETURN, await this.getItemsFromSchema(tableName, schema.filter((field) => !alreadyExistsColumns.includes(field.key)), Object.keys(RETURN).map(Number), options)));
|
|
672
696
|
}
|
|
673
697
|
}
|
|
@@ -685,10 +709,14 @@ export default class Inibase {
|
|
|
685
709
|
};
|
|
686
710
|
return onlyOne && Array.isArray(RETURN) ? RETURN[0] : RETURN;
|
|
687
711
|
}
|
|
688
|
-
async post(tableName, data, options
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
712
|
+
async post(tableName, data, options, returnPostedData) {
|
|
713
|
+
if (!options)
|
|
714
|
+
options = {
|
|
715
|
+
page: 1,
|
|
716
|
+
per_page: 15,
|
|
717
|
+
};
|
|
718
|
+
if (!returnPostedData)
|
|
719
|
+
returnPostedData = false;
|
|
692
720
|
const schema = await this.getTableSchema(tableName);
|
|
693
721
|
let RETURN;
|
|
694
722
|
if (!schema)
|
|
@@ -696,7 +724,7 @@ export default class Inibase {
|
|
|
696
724
|
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
697
725
|
let [last_line_number, last_id] = (await File.isExists(idFilePath))
|
|
698
726
|
? Object.entries((await File.get(idFilePath, -1, "number", undefined, this.salt))[0] ??
|
|
699
|
-
{})[0]
|
|
727
|
+
{})[0].map(Number) ?? [0, 0]
|
|
700
728
|
: [0, 0];
|
|
701
729
|
if (Utils.isArrayOfObjects(data))
|
|
702
730
|
RETURN = data.map(({ id, updatedAt, createdAt, ...rest }) => ({
|
|
@@ -716,10 +744,17 @@ export default class Inibase {
|
|
|
716
744
|
const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), RETURN);
|
|
717
745
|
last_line_number += 1;
|
|
718
746
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
719
|
-
await File.append(path,
|
|
747
|
+
await File.append(path,
|
|
748
|
+
// Array.isArray(content)
|
|
749
|
+
// ? content.reduce((obj, value, index) => {
|
|
750
|
+
// obj[last_line_number + index] = value;
|
|
751
|
+
// return obj;
|
|
752
|
+
// }, {})
|
|
753
|
+
// : { [last_line_number]: content }
|
|
754
|
+
content, last_line_number);
|
|
720
755
|
if (returnPostedData)
|
|
721
756
|
return this.get(tableName, Utils.isArrayOfObjects(RETURN)
|
|
722
|
-
? RETURN.map((data) => data.id)
|
|
757
|
+
? RETURN.map((data) => Number(data.id))
|
|
723
758
|
: RETURN.id, options, !Utils.isArrayOfObjects(data) // return only one item if data is not array of objects
|
|
724
759
|
);
|
|
725
760
|
}
|
|
@@ -738,7 +773,9 @@ export default class Inibase {
|
|
|
738
773
|
if (Utils.isArrayOfObjects(data)) {
|
|
739
774
|
if (!data.every((item) => item.hasOwnProperty("id") && Utils.isValidID(item.id)))
|
|
740
775
|
throw this.throwError("INVALID_ID");
|
|
741
|
-
return this.put(tableName, data, data
|
|
776
|
+
return this.put(tableName, data, data
|
|
777
|
+
.filter((item) => item.id !== undefined)
|
|
778
|
+
.map((item) => item.id));
|
|
742
779
|
}
|
|
743
780
|
else if (data.hasOwnProperty("id")) {
|
|
744
781
|
if (!Utils.isValidID(data.id))
|
|
@@ -821,6 +858,8 @@ export default class Inibase {
|
|
|
821
858
|
if ((Array.isArray(where) && where.every(Utils.isValidID)) ||
|
|
822
859
|
Utils.isValidID(where)) {
|
|
823
860
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
861
|
+
if (!lineNumbers)
|
|
862
|
+
return null;
|
|
824
863
|
return this.delete(tableName, lineNumbers, where);
|
|
825
864
|
}
|
|
826
865
|
else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
@@ -829,7 +868,7 @@ export default class Inibase {
|
|
|
829
868
|
const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
|
|
830
869
|
if (files.length) {
|
|
831
870
|
if (!_id)
|
|
832
|
-
_id = Object.
|
|
871
|
+
_id = Object.entries((await File.get(join(this.folder, this.database, tableName, "id.inib"), where, "number", undefined, this.salt))[0] ?? {}).map(([_key, id]) => UtilsServer.encodeID(Number(id), this.salt));
|
|
833
872
|
if (!_id.length)
|
|
834
873
|
throw this.throwError("NO_ITEMS", tableName);
|
|
835
874
|
for await (const file of files)
|
|
@@ -849,7 +888,7 @@ export default class Inibase {
|
|
|
849
888
|
return null;
|
|
850
889
|
}
|
|
851
890
|
async sum(tableName, columns, where) {
|
|
852
|
-
let RETURN;
|
|
891
|
+
let RETURN = {};
|
|
853
892
|
const schema = await this.getTableSchema(tableName);
|
|
854
893
|
if (!schema)
|
|
855
894
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
@@ -862,7 +901,9 @@ export default class Inibase {
|
|
|
862
901
|
if (await File.isExists(columnPath)) {
|
|
863
902
|
if (where) {
|
|
864
903
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
865
|
-
RETURN[column] =
|
|
904
|
+
RETURN[column] = lineNumbers
|
|
905
|
+
? await File.sum(columnPath, lineNumbers)
|
|
906
|
+
: 0;
|
|
866
907
|
}
|
|
867
908
|
else
|
|
868
909
|
RETURN[column] = await File.sum(columnPath);
|
|
@@ -871,7 +912,7 @@ export default class Inibase {
|
|
|
871
912
|
return Array.isArray(columns) ? RETURN : Object.values(RETURN)[0];
|
|
872
913
|
}
|
|
873
914
|
async max(tableName, columns, where) {
|
|
874
|
-
let RETURN;
|
|
915
|
+
let RETURN = {};
|
|
875
916
|
const schema = await this.getTableSchema(tableName);
|
|
876
917
|
if (!schema)
|
|
877
918
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
@@ -884,7 +925,9 @@ export default class Inibase {
|
|
|
884
925
|
if (await File.isExists(columnPath)) {
|
|
885
926
|
if (where) {
|
|
886
927
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
887
|
-
RETURN[column] =
|
|
928
|
+
RETURN[column] = lineNumbers
|
|
929
|
+
? await File.max(columnPath, lineNumbers)
|
|
930
|
+
: 0;
|
|
888
931
|
}
|
|
889
932
|
else
|
|
890
933
|
RETURN[column] = await File.max(columnPath);
|
|
@@ -893,7 +936,7 @@ export default class Inibase {
|
|
|
893
936
|
return RETURN;
|
|
894
937
|
}
|
|
895
938
|
async min(tableName, columns, where) {
|
|
896
|
-
let RETURN;
|
|
939
|
+
let RETURN = {};
|
|
897
940
|
const schema = await this.getTableSchema(tableName);
|
|
898
941
|
if (!schema)
|
|
899
942
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
@@ -906,7 +949,9 @@ export default class Inibase {
|
|
|
906
949
|
if (await File.isExists(columnPath)) {
|
|
907
950
|
if (where) {
|
|
908
951
|
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
909
|
-
RETURN[column] =
|
|
952
|
+
RETURN[column] = lineNumbers
|
|
953
|
+
? await File.min(columnPath, lineNumbers)
|
|
954
|
+
: 0;
|
|
910
955
|
}
|
|
911
956
|
else
|
|
912
957
|
RETURN[column] = await File.min(columnPath);
|
package/dist/utils.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type FieldType } from "./index.js";
|
|
|
2
2
|
export declare const isArrayOfObjects: (input: any) => input is Record<any, any>[];
|
|
3
3
|
export declare const isArrayOfArrays: (input: any) => input is any[][];
|
|
4
4
|
export declare const isArrayOfNulls: (input: any) => input is null[] | null[][];
|
|
5
|
-
export declare const isObject: (obj: any) =>
|
|
5
|
+
export declare const isObject: (obj: any) => obj is Record<any, any>;
|
|
6
6
|
export declare const deepMerge: (target: any, source: any) => any;
|
|
7
7
|
export declare const combineObjects: (arr: Record<string, any>[]) => Record<string, any>;
|
|
8
8
|
export declare const isNumber: (input: any) => input is number;
|
|
@@ -21,7 +21,7 @@ export declare const validateFieldType: (value: any, fieldType: FieldType | Fiel
|
|
|
21
21
|
export declare const objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
|
|
22
22
|
export default class Utils {
|
|
23
23
|
static isNumber: (input: any) => input is number;
|
|
24
|
-
static isObject: (obj: any) =>
|
|
24
|
+
static isObject: (obj: any) => obj is Record<any, any>;
|
|
25
25
|
static isEmail: (input: any) => boolean;
|
|
26
26
|
static isDate: (input: any) => boolean;
|
|
27
27
|
static isURL: (input: any) => boolean;
|
|
@@ -30,14 +30,14 @@ export default class Utils {
|
|
|
30
30
|
static deepMerge: (target: any, source: any) => any;
|
|
31
31
|
static combineObjects: (arr: Record<string, any>[]) => Record<string, any>;
|
|
32
32
|
static isArrayOfObjects: (input: any) => input is Record<any, any>[];
|
|
33
|
-
static findChangedProperties: (obj1: Record<string, string>, obj2: Record<string, string>) => Record<string, string
|
|
34
|
-
static detectFieldType: (input: any, availableTypes: FieldType[]) => FieldType;
|
|
33
|
+
static findChangedProperties: (obj1: Record<string, string>, obj2: Record<string, string>) => Record<string, string> | null;
|
|
34
|
+
static detectFieldType: (input: any, availableTypes: FieldType[]) => FieldType | undefined;
|
|
35
35
|
static isArrayOfArrays: (input: any) => input is any[][];
|
|
36
36
|
static isBoolean: (input: any) => input is boolean;
|
|
37
37
|
static isString: (input: any) => input is string;
|
|
38
38
|
static isHTML: (input: any) => boolean;
|
|
39
39
|
static isIP: (input: any) => boolean;
|
|
40
|
-
static validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => boolean;
|
|
40
|
+
static validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[] | undefined) => boolean;
|
|
41
41
|
static objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
|
|
42
42
|
static isArrayOfNulls: (input: any) => input is null[] | null[][];
|
|
43
43
|
}
|
package/dist/utils.js
CHANGED
|
@@ -54,12 +54,10 @@ export const isEmail = (input) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(input
|
|
|
54
54
|
export const isURL = (input) => {
|
|
55
55
|
if (typeof input !== "string")
|
|
56
56
|
return false;
|
|
57
|
-
if (input[0] === "#" ||
|
|
57
|
+
if ((input[0] === "#" && !input.includes(" ")) ||
|
|
58
58
|
input.startsWith("tel:") ||
|
|
59
59
|
input.startsWith("mailto:"))
|
|
60
60
|
return true;
|
|
61
|
-
else if ("canParse" in URL)
|
|
62
|
-
return URL.canParse(input);
|
|
63
61
|
else {
|
|
64
62
|
var pattern = new RegExp("^(https?:\\/\\/)?" + // protocol
|
|
65
63
|
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name
|
|
@@ -72,13 +70,7 @@ export const isURL = (input) => {
|
|
|
72
70
|
};
|
|
73
71
|
export const isHTML = (input) => /<\/?\s*[a-z-][^>]*\s*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);)/g.test(input);
|
|
74
72
|
export const isString = (input) => Object.prototype.toString.call(input) === "[object String]" &&
|
|
75
|
-
|
|
76
|
-
!isBoolean(input) &&
|
|
77
|
-
!isEmail(input) &&
|
|
78
|
-
!isDate(input) &&
|
|
79
|
-
!isURL(input) &&
|
|
80
|
-
!isIP(input) &&
|
|
81
|
-
!isHTML(input);
|
|
73
|
+
[isNumber, isBoolean, isEmail, isURL, isIP].every((fn) => !fn(input));
|
|
82
74
|
export const isIP = (input) => /^(?:(?:^|\.)(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)){4}$/.test(input);
|
|
83
75
|
export const isBoolean = (input) => typeof input === "boolean" ||
|
|
84
76
|
input === "true" ||
|
|
@@ -86,8 +78,7 @@ export const isBoolean = (input) => typeof input === "boolean" ||
|
|
|
86
78
|
input === true ||
|
|
87
79
|
input === false;
|
|
88
80
|
export const isPassword = (input) => input.length === 161;
|
|
89
|
-
export const isDate = (input) => (
|
|
90
|
-
(!isNaN(Date.parse(String(input))) && Date.parse(String(input)) >= 0);
|
|
81
|
+
export const isDate = (input) => !isNaN(new Date(input).getTime()) || !isNaN(Date.parse(input));
|
|
91
82
|
export const isValidID = (input) => {
|
|
92
83
|
return typeof input === "string" && input.length === 32;
|
|
93
84
|
};
|
package/dist/utils.server.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ export declare const comparePassword: (hashedPassword: string, inputPassword: st
|
|
|
5
5
|
export declare const encodeID: (id: number | string, secretKeyOrSalt: string | number | Buffer) => string;
|
|
6
6
|
export declare const decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
7
7
|
export declare const findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
|
|
8
|
-
export declare const addIdToSchema: (schema: Schema, oldIndex: number, secretKeyOrSalt: string | number | Buffer) => import("./index.js").Field[];
|
|
8
|
+
export declare const addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer) => import("./index.js").Field[];
|
|
9
9
|
export default class UtilsServer {
|
|
10
10
|
static encodeID: (id: string | number, secretKeyOrSalt: string | number | Buffer) => string;
|
|
11
11
|
static decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
12
12
|
static hashPassword: (password: string) => string;
|
|
13
13
|
static comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
|
|
14
14
|
static findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
|
|
15
|
-
static addIdToSchema: (schema: Schema, oldIndex: number, secretKeyOrSalt: string | number | Buffer) => import("./index.js").Field[];
|
|
15
|
+
static addIdToSchema: (schema: Schema, oldIndex: number | undefined, secretKeyOrSalt: string | number | Buffer) => import("./index.js").Field[];
|
|
16
16
|
}
|