inibase 1.0.0-rc.90 → 1.0.0-rc.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +4 -4
- package/dist/file.js +6 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +65 -36
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { parseArgs } from "node:util";
|
|
|
7
7
|
import Inison from "inison";
|
|
8
8
|
import { isExists } from "./file.js";
|
|
9
9
|
import Inibase, {} from "./index.js";
|
|
10
|
-
import {
|
|
10
|
+
import { isStringified, isNumber, setField, unsetField } from "./utils.js";
|
|
11
11
|
const textGreen = (input) => `\u001b[1;32m${input}\u001b[0m`;
|
|
12
12
|
const textRed = (input) => `\u001b[1;31m${input}\u001b[0m`;
|
|
13
13
|
const textBlue = (input) => `\u001b[1;34m${input}\u001b[0m`;
|
|
@@ -215,11 +215,11 @@ rl.on("line", async (input) => {
|
|
|
215
215
|
where = -1;
|
|
216
216
|
else if (isNumber(parsedArgs.where))
|
|
217
217
|
where = Number(parsedArgs.where);
|
|
218
|
-
else if (
|
|
218
|
+
else if (isStringified(parsedArgs.where))
|
|
219
219
|
where = Inison.unstringify(parsedArgs.where);
|
|
220
220
|
}
|
|
221
221
|
if (parsedArgs.sort) {
|
|
222
|
-
if (
|
|
222
|
+
if (isStringified(parsedArgs.sort))
|
|
223
223
|
sort = Inison.unstringify(parsedArgs.sort);
|
|
224
224
|
else
|
|
225
225
|
sort = parsedArgs.sort;
|
|
@@ -227,7 +227,7 @@ rl.on("line", async (input) => {
|
|
|
227
227
|
page = Number(parsedArgs.page) ?? undefined;
|
|
228
228
|
perPage = Number(parsedArgs.perPage) ?? undefined;
|
|
229
229
|
columns = parsedArgs.columns;
|
|
230
|
-
if (parsedArgs.data &&
|
|
230
|
+
if (parsedArgs.data && isStringified(parsedArgs.data))
|
|
231
231
|
data = Inison.unstringify(parsedArgs.data);
|
|
232
232
|
}
|
|
233
233
|
switch (splitedInput[0].toLocaleLowerCase()) {
|
package/dist/file.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Transform } from "node:stream";
|
|
|
5
5
|
import { pipeline } from "node:stream/promises";
|
|
6
6
|
import { createGunzip, createGzip } from "node:zlib";
|
|
7
7
|
import Inison from "inison";
|
|
8
|
-
import { detectFieldType, isArrayOfObjects,
|
|
8
|
+
import { detectFieldType, isArrayOfObjects, isStringified, isNumber, isObject, } from "./utils.js";
|
|
9
9
|
import { compare, encodeID, exec, gunzip, gzip } from "./utils.server.js";
|
|
10
10
|
export const lock = async (folderPath, prefix) => {
|
|
11
11
|
let lockFile = null;
|
|
@@ -100,7 +100,7 @@ const secureString = (input) => {
|
|
|
100
100
|
* @returns The secured and/or joined string.
|
|
101
101
|
*/
|
|
102
102
|
export const encode = (input) => Array.isArray(input)
|
|
103
|
-
? input.every((_input) => typeof _input === "string" &&
|
|
103
|
+
? input.every((_input) => typeof _input === "string" && isStringified(_input))
|
|
104
104
|
? `[${input.join(",")}]`
|
|
105
105
|
: Inison.stringify(input)
|
|
106
106
|
: secureString(input);
|
|
@@ -174,7 +174,7 @@ export const decode = (input, fieldType, fieldChildrenType, secretKey) => {
|
|
|
174
174
|
fieldType = detectFieldType(String(input), fieldType);
|
|
175
175
|
// Decode the input using the decodeHelper function.
|
|
176
176
|
return decodeHelper(typeof input === "string"
|
|
177
|
-
?
|
|
177
|
+
? isStringified(input)
|
|
178
178
|
? Inison.unstringify(input)
|
|
179
179
|
: unSecureString(input)
|
|
180
180
|
: input, fieldType, fieldChildrenType, secretKey);
|
|
@@ -194,7 +194,7 @@ export async function get(filePath, lineNumbers, fieldType, fieldChildrenType, s
|
|
|
194
194
|
else if (lineNumbers == -1) {
|
|
195
195
|
const command = filePath.endsWith(".gz")
|
|
196
196
|
? `zcat ${filePath} | sed -n '$p'`
|
|
197
|
-
: `sed -n '$p' ${filePath}`, foundedLine = (await exec(command)).stdout.
|
|
197
|
+
: `sed -n '$p' ${filePath}`, foundedLine = (await exec(command)).stdout.trimEnd();
|
|
198
198
|
if (foundedLine)
|
|
199
199
|
lines[linesCount] = decode(foundedLine, fieldType, fieldChildrenType, secretKey);
|
|
200
200
|
}
|
|
@@ -215,7 +215,7 @@ export async function get(filePath, lineNumbers, fieldType, fieldChildrenType, s
|
|
|
215
215
|
}
|
|
216
216
|
const command = filePath.endsWith(".gz")
|
|
217
217
|
? `zcat ${filePath} | sed -n '${lineNumbers.join("p;")}p'`
|
|
218
|
-
: `sed -n '${lineNumbers.join("p;")}p' ${filePath}`, foundedLines = (await exec(command)).stdout.
|
|
218
|
+
: `sed -n '${lineNumbers.join("p;")}p' ${filePath}`, foundedLines = (await exec(command)).stdout.trimEnd().split("\n");
|
|
219
219
|
let index = 0;
|
|
220
220
|
for (const line of foundedLines) {
|
|
221
221
|
lines[lineNumbers[index]] = decode(line, fieldType, fieldChildrenType, secretKey);
|
|
@@ -461,7 +461,7 @@ export const search = async (filePath, operator, comparedAtValue, logicalOperato
|
|
|
461
461
|
* Note: Reads through the file line by line to count the total number of lines.
|
|
462
462
|
*/
|
|
463
463
|
export const count = async (filePath) => {
|
|
464
|
-
// Number((await exec(`wc -l < ${filePath}`)).stdout.
|
|
464
|
+
// Number((await exec(`wc -l < ${filePath}`)).stdout.trimEnd());
|
|
465
465
|
let linesCount = 0;
|
|
466
466
|
if (await isExists(filePath)) {
|
|
467
467
|
let fileHandle = null;
|
package/dist/index.d.ts
CHANGED
|
@@ -93,6 +93,7 @@ export default class Inibase {
|
|
|
93
93
|
getTableSchema(tableName: string, encodeIDs?: boolean): Promise<Schema | undefined>;
|
|
94
94
|
private throwErrorIfTableEmpty;
|
|
95
95
|
private validateData;
|
|
96
|
+
private cleanObject;
|
|
96
97
|
private formatField;
|
|
97
98
|
private checkUnique;
|
|
98
99
|
private formatData;
|
package/dist/index.js
CHANGED
|
@@ -318,12 +318,22 @@ export default class Inibase {
|
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
|
+
cleanObject(obj) {
|
|
322
|
+
const cleanedObject = Object.entries(obj).reduce((acc, [key, value]) => {
|
|
323
|
+
if (value !== undefined && value !== null && value !== "")
|
|
324
|
+
acc[key] = value;
|
|
325
|
+
return acc;
|
|
326
|
+
}, {});
|
|
327
|
+
return Object.keys(cleanedObject).length > 0 ? cleanedObject : null;
|
|
328
|
+
}
|
|
321
329
|
formatField(value, fieldType, fieldChildrenType, _formatOnlyAvailiableKeys) {
|
|
322
330
|
if (Array.isArray(fieldType))
|
|
323
331
|
fieldType = (Utils.detectFieldType(value, fieldType) ??
|
|
324
332
|
fieldType[0]);
|
|
325
333
|
if (!value)
|
|
326
334
|
return null;
|
|
335
|
+
if (fieldType !== "array" && Array.isArray(value))
|
|
336
|
+
value = value[0];
|
|
327
337
|
switch (fieldType) {
|
|
328
338
|
case "array":
|
|
329
339
|
if (!fieldChildrenType)
|
|
@@ -332,16 +342,14 @@ export default class Inibase {
|
|
|
332
342
|
value = [value];
|
|
333
343
|
if (Utils.isArrayOfObjects(fieldChildrenType))
|
|
334
344
|
return this.formatData(value, fieldChildrenType, _formatOnlyAvailiableKeys);
|
|
345
|
+
if (!value.length)
|
|
346
|
+
return null;
|
|
335
347
|
return value.map((_value) => this.formatField(_value, fieldChildrenType));
|
|
336
348
|
case "object":
|
|
337
|
-
if (Array.isArray(value))
|
|
338
|
-
value = value[0];
|
|
339
349
|
if (Utils.isArrayOfObjects(fieldChildrenType))
|
|
340
350
|
return this.formatData(value, fieldChildrenType, _formatOnlyAvailiableKeys);
|
|
341
351
|
break;
|
|
342
352
|
case "table":
|
|
343
|
-
if (Array.isArray(value))
|
|
344
|
-
value = value[0];
|
|
345
353
|
if (Utils.isObject(value)) {
|
|
346
354
|
if (Object.hasOwn(value, "id") &&
|
|
347
355
|
(Utils.isValidID(value.id) ||
|
|
@@ -356,33 +364,29 @@ export default class Inibase {
|
|
|
356
364
|
: UtilsServer.decodeID(value, this.salt);
|
|
357
365
|
break;
|
|
358
366
|
case "password":
|
|
359
|
-
if (Array.isArray(value))
|
|
360
|
-
value = value[0];
|
|
361
367
|
return Utils.isPassword(value)
|
|
362
368
|
? value
|
|
363
369
|
: UtilsServer.hashPassword(String(value));
|
|
364
370
|
case "number":
|
|
365
|
-
if (Array.isArray(value))
|
|
366
|
-
value = value[0];
|
|
367
371
|
return Utils.isNumber(value) ? Number(value) : null;
|
|
368
372
|
case "date": {
|
|
369
|
-
if (Array.isArray(value))
|
|
370
|
-
value = value[0];
|
|
371
373
|
if (Utils.isNumber(value))
|
|
372
374
|
return value;
|
|
373
375
|
const dateToTimestamp = Date.parse(value);
|
|
374
376
|
return Number.isNaN(dateToTimestamp) ? null : dateToTimestamp;
|
|
375
377
|
}
|
|
376
378
|
case "id":
|
|
377
|
-
if (Array.isArray(value))
|
|
378
|
-
value = value[0];
|
|
379
379
|
return Utils.isNumber(value)
|
|
380
380
|
? value
|
|
381
381
|
: UtilsServer.decodeID(value, this.salt);
|
|
382
|
-
case "json":
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
382
|
+
case "json": {
|
|
383
|
+
if (typeof value === "string" && Utils.isStringified(value))
|
|
384
|
+
return value;
|
|
385
|
+
const cleanedObject = this.cleanObject(value);
|
|
386
|
+
if (cleanedObject)
|
|
387
|
+
return Inison.stringify(cleanedObject);
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
386
390
|
default:
|
|
387
391
|
return value;
|
|
388
392
|
}
|
|
@@ -602,19 +606,32 @@ export default class Inibase {
|
|
|
602
606
|
if (field.table &&
|
|
603
607
|
(await File.isExists(join(this.databasePath, field.table))) &&
|
|
604
608
|
(await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`)))) {
|
|
605
|
-
const
|
|
606
|
-
if (
|
|
607
|
-
|
|
609
|
+
const itemsIDs = await File.get(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`), linesNumber, field.type, field.children, this.salt);
|
|
610
|
+
if (itemsIDs) {
|
|
611
|
+
const searchableIDs = {};
|
|
612
|
+
for (const [index, item] of Object.entries(itemsIDs)) {
|
|
608
613
|
if (!RETURN[index])
|
|
609
614
|
RETURN[index] = {};
|
|
610
615
|
if (item !== null && item !== undefined)
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
616
|
+
searchableIDs[index] = item;
|
|
617
|
+
}
|
|
618
|
+
if (Object.keys(searchableIDs).length) {
|
|
619
|
+
const items = await this.get(field.table, [].concat(...Object.values(searchableIDs)), {
|
|
620
|
+
...options,
|
|
621
|
+
perPage: Number.POSITIVE_INFINITY,
|
|
622
|
+
columns: options.columns
|
|
623
|
+
?.filter((column) => column.includes(`${field.key}.`))
|
|
624
|
+
.map((column) => column.replace(`${field.key}.`, "")),
|
|
625
|
+
});
|
|
626
|
+
if (items) {
|
|
627
|
+
let cursor = 0;
|
|
628
|
+
for (const [index, Ids] of Object.entries(searchableIDs)) {
|
|
629
|
+
RETURN[index][field.key] = items.slice(cursor, cursor + Ids.length);
|
|
630
|
+
cursor += Ids.length;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
617
633
|
}
|
|
634
|
+
}
|
|
618
635
|
}
|
|
619
636
|
}
|
|
620
637
|
else if (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`))) {
|
|
@@ -644,19 +661,32 @@ export default class Inibase {
|
|
|
644
661
|
if (field.table &&
|
|
645
662
|
(await File.isExists(join(this.databasePath, field.table))) &&
|
|
646
663
|
(await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`)))) {
|
|
647
|
-
const
|
|
648
|
-
if (
|
|
649
|
-
|
|
664
|
+
const itemsIDs = await File.get(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`), linesNumber, field.type, field.children, this.salt);
|
|
665
|
+
if (itemsIDs) {
|
|
666
|
+
const searchableIDs = {};
|
|
667
|
+
for (const [index, item] of Object.entries(itemsIDs)) {
|
|
650
668
|
if (!RETURN[index])
|
|
651
669
|
RETURN[index] = {};
|
|
652
670
|
if (item !== null && item !== undefined)
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
671
|
+
searchableIDs[index] = item;
|
|
672
|
+
}
|
|
673
|
+
if (Object.keys(searchableIDs).length) {
|
|
674
|
+
const items = await this.get(field.table, Object.values(searchableIDs), {
|
|
675
|
+
...options,
|
|
676
|
+
perPage: Number.POSITIVE_INFINITY,
|
|
677
|
+
columns: options.columns
|
|
678
|
+
?.filter((column) => column.includes(`${field.key}.`))
|
|
679
|
+
.map((column) => column.replace(`${field.key}.`, "")),
|
|
680
|
+
});
|
|
681
|
+
if (items) {
|
|
682
|
+
let cursor = 0;
|
|
683
|
+
for (const [index] of Object.entries(searchableIDs)) {
|
|
684
|
+
RETURN[index][field.key] = items[cursor];
|
|
685
|
+
cursor++;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
659
688
|
}
|
|
689
|
+
}
|
|
660
690
|
}
|
|
661
691
|
}
|
|
662
692
|
else if (await File.isExists(join(tablePath, `${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`))) {
|
|
@@ -906,7 +936,7 @@ export default class Inibase {
|
|
|
906
936
|
: `${pasteCommand} | ${sortCommand} | ${awkCommand}`, {
|
|
907
937
|
encoding: "utf-8",
|
|
908
938
|
})).stdout
|
|
909
|
-
.
|
|
939
|
+
.trimEnd()
|
|
910
940
|
.split("\n");
|
|
911
941
|
if (where)
|
|
912
942
|
lines = lines.slice((options.page - 1) * options.perPage, options.page * options.perPage);
|
|
@@ -1130,7 +1160,6 @@ export default class Inibase {
|
|
|
1130
1160
|
if (Utils.isArrayOfObjects(data)) {
|
|
1131
1161
|
if (!data.every((item) => Object.hasOwn(item, "id") && Utils.isValidID(item.id)))
|
|
1132
1162
|
throw this.throwError("INVALID_ID");
|
|
1133
|
-
// TODO: Reduce I/O
|
|
1134
1163
|
return this.put(tableName, data, data.map(({ id }) => id), options, returnUpdatedData || undefined);
|
|
1135
1164
|
}
|
|
1136
1165
|
if (Object.hasOwn(data, "id")) {
|
package/dist/utils.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export declare const isValidID: (input: any) => input is string;
|
|
|
139
139
|
* @param {string} str - The string to be checked.
|
|
140
140
|
* @returns {boolean} Returns true if the string is valid JSON, otherwise false.
|
|
141
141
|
*/
|
|
142
|
-
export declare const
|
|
142
|
+
export declare const isStringified: (str: string) => boolean;
|
|
143
143
|
/**
|
|
144
144
|
* Identifies and returns properties that have changed between two objects.
|
|
145
145
|
*
|
package/dist/utils.js
CHANGED
|
@@ -170,7 +170,7 @@ export const isValidID = (input) => {
|
|
|
170
170
|
* @param {string} str - The string to be checked.
|
|
171
171
|
* @returns {boolean} Returns true if the string is valid JSON, otherwise false.
|
|
172
172
|
*/
|
|
173
|
-
export const
|
|
173
|
+
export const isStringified = (str) => str === "null" || str === "undefined" || str[0] === "{" || str[0] === "[";
|
|
174
174
|
/**
|
|
175
175
|
* Identifies and returns properties that have changed between two objects.
|
|
176
176
|
*
|
|
@@ -222,7 +222,7 @@ export const detectFieldType = (input, availableTypes) => {
|
|
|
222
222
|
return "url";
|
|
223
223
|
if (availableTypes.includes("password") && isPassword(input))
|
|
224
224
|
return "password";
|
|
225
|
-
if (availableTypes.includes("json") &&
|
|
225
|
+
if (availableTypes.includes("json") && isStringified(input))
|
|
226
226
|
return "json";
|
|
227
227
|
if (availableTypes.includes("json") && isDate(input))
|
|
228
228
|
return "json";
|
|
@@ -355,7 +355,7 @@ export const validateFieldType = (value, fieldType, fieldChildrenType) => {
|
|
|
355
355
|
case "id":
|
|
356
356
|
return isNumber(value) || isValidID(value);
|
|
357
357
|
case "json":
|
|
358
|
-
return
|
|
358
|
+
return isStringified(value) || Array.isArray(value) || isObject(value);
|
|
359
359
|
default:
|
|
360
360
|
return false;
|
|
361
361
|
}
|