inibase 1.0.0-rc.10 → 1.0.0-rc.11
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/file.ts +112 -69
- package/index.test.ts +44 -3
- package/index.ts +28 -12
- package/package.json +1 -1
package/file.ts
CHANGED
|
@@ -20,6 +20,8 @@ export const isExists = async (path: string) => {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
const delimiters = [",", "|", "&", "$", "#", "@", "^", "%", ":", "!", ";"];
|
|
24
|
+
|
|
23
25
|
export const encode = (
|
|
24
26
|
input:
|
|
25
27
|
| string
|
|
@@ -30,23 +32,42 @@ export const encode = (
|
|
|
30
32
|
secretKey?: string | Buffer
|
|
31
33
|
) => {
|
|
32
34
|
const secureString = (input: string | number | boolean | null) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
if (["true", "false"].includes(String(input))) return input ? 1 : 0;
|
|
36
|
+
return typeof input === "string"
|
|
37
|
+
? decodeURIComponent(input)
|
|
38
|
+
.replaceAll("<", "<")
|
|
39
|
+
.replaceAll(">", ">")
|
|
40
|
+
.replaceAll(",", "%2C")
|
|
41
|
+
.replaceAll("|", "%7C")
|
|
42
|
+
.replaceAll("&", "%26")
|
|
43
|
+
.replaceAll("$", "%24")
|
|
44
|
+
.replaceAll("#", "%23")
|
|
45
|
+
.replaceAll("@", "%40")
|
|
46
|
+
.replaceAll("^", "%5E")
|
|
47
|
+
.replaceAll("%", "%25")
|
|
48
|
+
.replaceAll(":", "%3A")
|
|
49
|
+
.replaceAll("!", "%21")
|
|
50
|
+
.replaceAll(";", "%3B")
|
|
51
|
+
.replaceAll("\n", "\\n")
|
|
52
|
+
.replaceAll("\r", "\\r")
|
|
53
|
+
: input;
|
|
54
|
+
},
|
|
55
|
+
secureArray = (arr_str: any[] | any): any[] | any =>
|
|
56
|
+
Array.isArray(arr_str) ? arr_str.map(secureArray) : secureString(arr_str),
|
|
57
|
+
joinMultidimensionalArray = (
|
|
58
|
+
arr: any[] | any[][],
|
|
59
|
+
delimiter_index = 0
|
|
60
|
+
): string => {
|
|
61
|
+
delimiter_index++;
|
|
62
|
+
if (isArrayOfArrays(arr))
|
|
63
|
+
arr = arr.map((ar: any[]) =>
|
|
64
|
+
joinMultidimensionalArray(ar, delimiter_index)
|
|
65
|
+
);
|
|
66
|
+
delimiter_index--;
|
|
67
|
+
return arr.join(delimiters[delimiter_index]);
|
|
68
|
+
};
|
|
44
69
|
return Array.isArray(input)
|
|
45
|
-
?
|
|
46
|
-
? (input as any[])
|
|
47
|
-
.map((_input) => _input.map(secureString).join(","))
|
|
48
|
-
.join("|")
|
|
49
|
-
: input.map(secureString).join(",")
|
|
70
|
+
? joinMultidimensionalArray(secureArray(input))
|
|
50
71
|
: secureString(input);
|
|
51
72
|
};
|
|
52
73
|
|
|
@@ -58,65 +79,87 @@ export const decode = (
|
|
|
58
79
|
): string | number | boolean | null | (string | number | null | boolean)[] => {
|
|
59
80
|
if (!fieldType) return null;
|
|
60
81
|
const unSecureString = (input: string) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
decodeURIComponent(input)
|
|
83
|
+
.replaceAll("<", "<")
|
|
84
|
+
.replaceAll(">", ">")
|
|
85
|
+
.replaceAll("%2C", ",")
|
|
86
|
+
.replaceAll("%7C", "|")
|
|
87
|
+
.replaceAll("%26", "&")
|
|
88
|
+
.replaceAll("%24", "$")
|
|
89
|
+
.replaceAll("%23", "#")
|
|
90
|
+
.replaceAll("%40", "@")
|
|
91
|
+
.replaceAll("%5E", "^")
|
|
92
|
+
.replaceAll("%25", "%")
|
|
93
|
+
.replaceAll("%3A", ":")
|
|
94
|
+
.replaceAll("%21", "!")
|
|
95
|
+
.replaceAll("%3B", ";")
|
|
96
|
+
.replaceAll("\\n", "\n")
|
|
97
|
+
.replaceAll("\\r", "\r") || null,
|
|
98
|
+
unSecureArray = (arr_str: any[] | any): any[] | any =>
|
|
99
|
+
Array.isArray(arr_str)
|
|
100
|
+
? arr_str.map(unSecureArray)
|
|
101
|
+
: unSecureString(arr_str),
|
|
102
|
+
reverseJoinMultidimensionalArray = (
|
|
103
|
+
joinedString: string | any[] | any[][]
|
|
104
|
+
): any | any[] | any[][] => {
|
|
105
|
+
const reverseJoinMultidimensionalArrayHelper = (
|
|
106
|
+
arr: any | any[] | any[][],
|
|
107
|
+
delimiter: string
|
|
108
|
+
) =>
|
|
109
|
+
Array.isArray(arr)
|
|
110
|
+
? arr.map((ar: any) =>
|
|
111
|
+
reverseJoinMultidimensionalArrayHelper(ar, delimiter)
|
|
112
|
+
)
|
|
113
|
+
: arr.split(delimiter);
|
|
114
|
+
|
|
115
|
+
const availableDelimiters = delimiters.filter((delimiter) =>
|
|
116
|
+
joinedString.includes(delimiter)
|
|
117
|
+
);
|
|
118
|
+
for (const delimiter of availableDelimiters) {
|
|
119
|
+
joinedString = Array.isArray(joinedString)
|
|
120
|
+
? reverseJoinMultidimensionalArrayHelper(joinedString, delimiter)
|
|
121
|
+
: joinedString.split(delimiter);
|
|
122
|
+
}
|
|
123
|
+
return joinedString;
|
|
124
|
+
},
|
|
125
|
+
decodeHelper = (value: string | number | any[]) => {
|
|
126
|
+
if (Array.isArray(value) && fieldType !== "array")
|
|
127
|
+
return value.map(decodeHelper);
|
|
128
|
+
switch (fieldType as FieldType) {
|
|
129
|
+
case "table":
|
|
130
|
+
case "number":
|
|
131
|
+
return isNumber(value) ? Number(value) : null;
|
|
132
|
+
case "boolean":
|
|
133
|
+
return typeof value === "string" ? value === "true" : Boolean(value);
|
|
134
|
+
case "array":
|
|
135
|
+
if (!Array.isArray(value)) return [value];
|
|
136
|
+
|
|
137
|
+
if (fieldChildrenType)
|
|
138
|
+
return value.map(
|
|
139
|
+
(v) =>
|
|
140
|
+
decode(
|
|
141
|
+
v,
|
|
142
|
+
Array.isArray(fieldChildrenType)
|
|
143
|
+
? detectFieldType(v, fieldChildrenType)
|
|
144
|
+
: fieldChildrenType,
|
|
145
|
+
undefined,
|
|
146
|
+
secretKey
|
|
147
|
+
) as string | number | boolean | null
|
|
148
|
+
);
|
|
149
|
+
else return value;
|
|
150
|
+
case "id":
|
|
151
|
+
return isNumber(value) ? encodeID(value as number, secretKey) : value;
|
|
152
|
+
default:
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
68
156
|
if (input === null || input === "") return null;
|
|
69
157
|
if (Array.isArray(fieldType))
|
|
70
158
|
fieldType = detectFieldType(String(input), fieldType);
|
|
71
|
-
const decodeHelper = (value: string | number | any[]) => {
|
|
72
|
-
if (Array.isArray(value) && fieldType !== "array")
|
|
73
|
-
return value.map(decodeHelper);
|
|
74
|
-
switch (fieldType as FieldType) {
|
|
75
|
-
case "table":
|
|
76
|
-
case "number":
|
|
77
|
-
return isNumber(value) ? Number(value) : null;
|
|
78
|
-
case "boolean":
|
|
79
|
-
return typeof value === "string" ? value === "true" : Boolean(value);
|
|
80
|
-
case "array":
|
|
81
|
-
if (!Array.isArray(value)) return [value];
|
|
82
|
-
|
|
83
|
-
if (fieldChildrenType)
|
|
84
|
-
return value.map(
|
|
85
|
-
(v) =>
|
|
86
|
-
decode(
|
|
87
|
-
v,
|
|
88
|
-
Array.isArray(fieldChildrenType)
|
|
89
|
-
? detectFieldType(v, fieldChildrenType)
|
|
90
|
-
: fieldChildrenType,
|
|
91
|
-
undefined,
|
|
92
|
-
secretKey
|
|
93
|
-
) as string | number | boolean | null
|
|
94
|
-
);
|
|
95
|
-
else return value;
|
|
96
|
-
case "id":
|
|
97
|
-
return isNumber(value) ? encodeID(value as number, secretKey) : value;
|
|
98
|
-
default:
|
|
99
|
-
return value;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
159
|
return decodeHelper(
|
|
103
160
|
typeof input === "string"
|
|
104
161
|
? input.includes(",")
|
|
105
|
-
? input
|
|
106
|
-
? input
|
|
107
|
-
.split("|")
|
|
108
|
-
.map((_input) => _input.split(",").map(unSecureString))
|
|
109
|
-
: input.split(",").map(unSecureString)
|
|
110
|
-
: input.includes("|")
|
|
111
|
-
? input
|
|
112
|
-
.split("|")
|
|
113
|
-
.map((_input) => [
|
|
114
|
-
_input
|
|
115
|
-
? fieldType === "array"
|
|
116
|
-
? [unSecureString(_input)]
|
|
117
|
-
: unSecureString(_input)
|
|
118
|
-
: null,
|
|
119
|
-
])
|
|
162
|
+
? unSecureArray(reverseJoinMultidimensionalArray(input))
|
|
120
163
|
: unSecureString(input)
|
|
121
164
|
: input
|
|
122
165
|
);
|
package/index.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decode } from "./file";
|
|
1
2
|
import Inibase, { Schema, Data } from "./index";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
// import os from "os";
|
|
@@ -197,9 +198,49 @@ const data_2 = [
|
|
|
197
198
|
try {
|
|
198
199
|
// db.setTableSchema("database", schema_2);
|
|
199
200
|
// const DATA = await db.post("database", data_2);
|
|
200
|
-
const DATA = await db.
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
// const DATA = await db.delete("database", 2);
|
|
202
|
+
// const DATA = await db.post("database", {
|
|
203
|
+
// slug: "demo",
|
|
204
|
+
// tables: [
|
|
205
|
+
// {
|
|
206
|
+
// id: 1,
|
|
207
|
+
// slug: "user",
|
|
208
|
+
// allowed_methods: [
|
|
209
|
+
// {
|
|
210
|
+
// role: "user",
|
|
211
|
+
// methods: ["c", "r", "u"],
|
|
212
|
+
// },
|
|
213
|
+
// {
|
|
214
|
+
// role: "guest",
|
|
215
|
+
// methods: ["c"],
|
|
216
|
+
// },
|
|
217
|
+
// {
|
|
218
|
+
// role: "admin",
|
|
219
|
+
// methods: ["d", "u"],
|
|
220
|
+
// },
|
|
221
|
+
// ],
|
|
222
|
+
// },
|
|
223
|
+
// {
|
|
224
|
+
// id: 1,
|
|
225
|
+
// slug: "user",
|
|
226
|
+
// allowed_methods: [
|
|
227
|
+
// {
|
|
228
|
+
// role: "user",
|
|
229
|
+
// methods: ["c", "r", "u"],
|
|
230
|
+
// },
|
|
231
|
+
// {
|
|
232
|
+
// role: "guest",
|
|
233
|
+
// methods: ["c"],
|
|
234
|
+
// },
|
|
235
|
+
// {
|
|
236
|
+
// role: "admin",
|
|
237
|
+
// methods: ["d", "u"],
|
|
238
|
+
// },
|
|
239
|
+
// ],
|
|
240
|
+
// },
|
|
241
|
+
// ],
|
|
242
|
+
// });
|
|
243
|
+
const DATA = await db.get("database");
|
|
203
244
|
console.log(JSON.stringify(DATA, null, 4));
|
|
204
245
|
} catch (er) {
|
|
205
246
|
console.log(er);
|
package/index.ts
CHANGED
|
@@ -609,12 +609,13 @@ export default class Inibase {
|
|
|
609
609
|
(prefix ?? "") + key + "."
|
|
610
610
|
)
|
|
611
611
|
);
|
|
612
|
-
else
|
|
612
|
+
else {
|
|
613
613
|
RETURN[(prefix ?? "") + key] = File.encode(value) as
|
|
614
614
|
| boolean
|
|
615
615
|
| number
|
|
616
616
|
| string
|
|
617
617
|
| null;
|
|
618
|
+
}
|
|
618
619
|
} else
|
|
619
620
|
RETURN[(prefix ?? "") + key] = File.encode(value) as
|
|
620
621
|
| boolean
|
|
@@ -635,6 +636,20 @@ export default class Inibase {
|
|
|
635
636
|
return addPathToKeys(CombineData(data), mainPath);
|
|
636
637
|
}
|
|
637
638
|
|
|
639
|
+
public async getOne(
|
|
640
|
+
tableName: string,
|
|
641
|
+
where?: string | number | (string | number)[] | Criteria,
|
|
642
|
+
options: Options = {
|
|
643
|
+
page: 1,
|
|
644
|
+
per_page: 15,
|
|
645
|
+
}
|
|
646
|
+
): Promise<Data | null> {
|
|
647
|
+
const _get = await this.get(tableName, where, options);
|
|
648
|
+
if (!_get) return null;
|
|
649
|
+
else if (Array.isArray(_get)) return (_get as Data)[0];
|
|
650
|
+
else return _get;
|
|
651
|
+
}
|
|
652
|
+
|
|
638
653
|
public async get(
|
|
639
654
|
tableName: string,
|
|
640
655
|
where?: string | number | (string | number)[] | Criteria,
|
|
@@ -1269,7 +1284,7 @@ export default class Inibase {
|
|
|
1269
1284
|
let last_id = (await File.isExists(idFilePath))
|
|
1270
1285
|
? Number(
|
|
1271
1286
|
Object.values(
|
|
1272
|
-
await File.get(idFilePath, -1, "number", undefined, this.salt)
|
|
1287
|
+
(await File.get(idFilePath, -1, "number", undefined, this.salt))[0]
|
|
1273
1288
|
)[0]
|
|
1274
1289
|
)
|
|
1275
1290
|
: 0;
|
|
@@ -1289,6 +1304,7 @@ export default class Inibase {
|
|
|
1289
1304
|
created_at: new Date(),
|
|
1290
1305
|
}))(data as Data);
|
|
1291
1306
|
if (!RETURN) throw this.throwError("NO_DATA");
|
|
1307
|
+
|
|
1292
1308
|
RETURN = this.formatData(RETURN, schema);
|
|
1293
1309
|
const pathesContents = this.joinPathesContents(
|
|
1294
1310
|
join(this.folder, this.database, tableName),
|
|
@@ -1463,16 +1479,16 @@ export default class Inibase {
|
|
|
1463
1479
|
if (files.length) {
|
|
1464
1480
|
if (!_id)
|
|
1465
1481
|
_id = Object.values(
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1482
|
+
(
|
|
1483
|
+
await File.get(
|
|
1484
|
+
join(this.folder, this.database, tableName, "id.inib"),
|
|
1485
|
+
where as number | number[],
|
|
1486
|
+
"number",
|
|
1487
|
+
undefined,
|
|
1488
|
+
this.salt
|
|
1489
|
+
)
|
|
1490
|
+
)[0]
|
|
1491
|
+
).map((id) => UtilsServer.encodeID(Number(id), this.salt));
|
|
1476
1492
|
for (const file of files.filter(
|
|
1477
1493
|
(fileName: string) =>
|
|
1478
1494
|
fileName.endsWith(".inib") && fileName !== "schema"
|