inibase 1.0.0-rc.95 → 1.0.0-rc.97
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/index.d.ts +1 -1
- package/dist/index.js +50 -62
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +16 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -25,14 +25,14 @@ export default class Inibase {
|
|
|
25
25
|
if (!process.env.INIBASE_SECRET) {
|
|
26
26
|
if (existsSync(".env") &&
|
|
27
27
|
readFileSync(".env").includes("INIBASE_SECRET="))
|
|
28
|
-
throw this.
|
|
28
|
+
throw this.Error("NO_ENV");
|
|
29
29
|
this.salt = scryptSync(randomBytes(16), randomBytes(16), 32);
|
|
30
30
|
appendFileSync(".env", `\nINIBASE_SECRET=${this.salt.toString("hex")}\n`);
|
|
31
31
|
}
|
|
32
32
|
else
|
|
33
33
|
this.salt = Buffer.from(process.env.INIBASE_SECRET, "hex");
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
Error(code, variable, language = "en") {
|
|
36
36
|
const errorMessages = {
|
|
37
37
|
en: {
|
|
38
38
|
FIELD_UNIQUE: "Field {variable} should be unique, got {variable} instead",
|
|
@@ -90,7 +90,7 @@ export default class Inibase {
|
|
|
90
90
|
async createTable(tableName, schema, config) {
|
|
91
91
|
const tablePath = join(this.databasePath, tableName);
|
|
92
92
|
if (await File.isExists(tablePath))
|
|
93
|
-
throw this.
|
|
93
|
+
throw this.Error("TABLE_EXISTS", tableName);
|
|
94
94
|
await mkdir(join(tablePath, ".tmp"), { recursive: true });
|
|
95
95
|
await mkdir(join(tablePath, ".cache"));
|
|
96
96
|
// if config not set => load default global env config
|
|
@@ -228,7 +228,7 @@ export default class Inibase {
|
|
|
228
228
|
async getTable(tableName) {
|
|
229
229
|
const tablePath = join(this.databasePath, tableName);
|
|
230
230
|
if (!(await File.isExists(tablePath)))
|
|
231
|
-
throw this.
|
|
231
|
+
throw this.Error("TABLE_NOT_EXISTS", tableName);
|
|
232
232
|
if (!this.tables[tableName])
|
|
233
233
|
this.tables[tableName] = {
|
|
234
234
|
schema: await this.getTableSchema(tableName),
|
|
@@ -277,9 +277,9 @@ export default class Inibase {
|
|
|
277
277
|
async throwErrorIfTableEmpty(tableName) {
|
|
278
278
|
const table = await this.getTable(tableName);
|
|
279
279
|
if (!table.schema)
|
|
280
|
-
throw this.
|
|
280
|
+
throw this.Error("NO_SCHEMA", tableName);
|
|
281
281
|
if (!(await File.isExists(join(this.databasePath, tableName, `id${this.getFileExtension(tableName)}`))))
|
|
282
|
-
throw this.
|
|
282
|
+
throw this.Error("NO_ITEMS", tableName);
|
|
283
283
|
return table;
|
|
284
284
|
}
|
|
285
285
|
validateData(data, schema, skipRequiredField = false) {
|
|
@@ -290,18 +290,18 @@ export default class Inibase {
|
|
|
290
290
|
for (const field of schema) {
|
|
291
291
|
if (!Object.hasOwn(data, field.key) ||
|
|
292
292
|
data[field.key] === null ||
|
|
293
|
-
data[field.key] === undefined
|
|
293
|
+
data[field.key] === undefined ||
|
|
294
|
+
data[field.key] === "") {
|
|
294
295
|
if (field.required && !skipRequiredField)
|
|
295
|
-
throw this.
|
|
296
|
+
throw this.Error("FIELD_REQUIRED", field.key);
|
|
296
297
|
return;
|
|
297
298
|
}
|
|
298
|
-
if (
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
throw this.throwError("INVALID_TYPE", [
|
|
299
|
+
if (!Utils.validateFieldType(data[field.key], field.type, (field.type === "array" || field.type === "object") &&
|
|
300
|
+
field.children &&
|
|
301
|
+
!Utils.isArrayOfObjects(field.children)
|
|
302
|
+
? field.children
|
|
303
|
+
: undefined))
|
|
304
|
+
throw this.Error("INVALID_TYPE", [
|
|
305
305
|
field.key,
|
|
306
306
|
Array.isArray(field.type) ? field.type.join(", ") : field.type,
|
|
307
307
|
data[field.key],
|
|
@@ -328,11 +328,10 @@ export default class Inibase {
|
|
|
328
328
|
}
|
|
329
329
|
formatField(value, fieldType, fieldChildrenType, _formatOnlyAvailiableKeys) {
|
|
330
330
|
if (Array.isArray(fieldType))
|
|
331
|
-
fieldType =
|
|
332
|
-
fieldType[0]);
|
|
331
|
+
fieldType = Utils.detectFieldType(value, fieldType) ?? fieldType[0];
|
|
333
332
|
if (!value)
|
|
334
333
|
return null;
|
|
335
|
-
if (
|
|
334
|
+
if (Array.isArray(value) && !["array", "json"].includes(fieldType))
|
|
336
335
|
value = value[0];
|
|
337
336
|
switch (fieldType) {
|
|
338
337
|
case "array":
|
|
@@ -369,12 +368,6 @@ export default class Inibase {
|
|
|
369
368
|
: UtilsServer.hashPassword(String(value));
|
|
370
369
|
case "number":
|
|
371
370
|
return Utils.isNumber(value) ? Number(value) : null;
|
|
372
|
-
case "date": {
|
|
373
|
-
if (Utils.isNumber(value))
|
|
374
|
-
return value;
|
|
375
|
-
const dateToTimestamp = Date.parse(value);
|
|
376
|
-
return Number.isNaN(dateToTimestamp) ? null : dateToTimestamp;
|
|
377
|
-
}
|
|
378
371
|
case "id":
|
|
379
372
|
return Utils.isNumber(value)
|
|
380
373
|
? value
|
|
@@ -404,7 +397,7 @@ export default class Inibase {
|
|
|
404
397
|
continue;
|
|
405
398
|
const [searchResult, totalLines] = await File.search(join(tablePath, `${key}${this.getFileExtension(tableName)}`), Array.isArray(values) ? "=" : "[]", values, undefined, field.type, field.children, 1, undefined, false, this.salt);
|
|
406
399
|
if (searchResult && totalLines > 0)
|
|
407
|
-
throw this.
|
|
400
|
+
throw this.Error("FIELD_UNIQUE", [
|
|
408
401
|
field.key,
|
|
409
402
|
Array.isArray(values) ? values.join(", ") : values,
|
|
410
403
|
]);
|
|
@@ -702,13 +695,6 @@ export default class Inibase {
|
|
|
702
695
|
if (item !== null && item !== undefined)
|
|
703
696
|
RETURN[index][field.key] = item;
|
|
704
697
|
}
|
|
705
|
-
// else
|
|
706
|
-
// RETURN = Object.fromEntries(
|
|
707
|
-
// Object.entries(RETURN).map(([index, data]) => [
|
|
708
|
-
// index,
|
|
709
|
-
// { ...data, [field.key]: this.getDefaultValue(field) },
|
|
710
|
-
// ]),
|
|
711
|
-
// );
|
|
712
698
|
}
|
|
713
699
|
}
|
|
714
700
|
return RETURN;
|
|
@@ -871,7 +857,7 @@ export default class Inibase {
|
|
|
871
857
|
let RETURN;
|
|
872
858
|
let schema = (await this.getTable(tableName)).schema;
|
|
873
859
|
if (!schema)
|
|
874
|
-
throw this.
|
|
860
|
+
throw this.Error("NO_SCHEMA", tableName);
|
|
875
861
|
if (!(await File.isExists(join(tablePath, `id${this.getFileExtension(tableName)}`))))
|
|
876
862
|
return null;
|
|
877
863
|
if (options.columns?.length)
|
|
@@ -1085,11 +1071,12 @@ export default class Inibase {
|
|
|
1085
1071
|
};
|
|
1086
1072
|
const tablePath = join(this.databasePath, tableName), schema = (await this.getTable(tableName)).schema;
|
|
1087
1073
|
if (!schema)
|
|
1088
|
-
throw this.
|
|
1074
|
+
throw this.Error("NO_SCHEMA", tableName);
|
|
1089
1075
|
if (!returnPostedData)
|
|
1090
1076
|
returnPostedData = false;
|
|
1091
|
-
let RETURN;
|
|
1092
1077
|
const keys = UtilsServer.hashString(Object.keys(Array.isArray(data) ? data[0] : data).join("."));
|
|
1078
|
+
// Skip Id and (created|updated)At
|
|
1079
|
+
this.validateData(data, schema.slice(1, -2));
|
|
1093
1080
|
let lastId = 0, renameList = [];
|
|
1094
1081
|
try {
|
|
1095
1082
|
await File.lock(join(tablePath, ".tmp"), keys);
|
|
@@ -1107,25 +1094,24 @@ export default class Inibase {
|
|
|
1107
1094
|
else
|
|
1108
1095
|
this.totalItems[`${tableName}-*`] = 0;
|
|
1109
1096
|
if (Utils.isArrayOfObjects(data))
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
createdAt
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
this.validateData(RETURN, schema);
|
|
1097
|
+
for (let index = 0; index < data.length; index++) {
|
|
1098
|
+
const element = data[index];
|
|
1099
|
+
element.id = ++lastId;
|
|
1100
|
+
element.createdAt = Date.now();
|
|
1101
|
+
element.updatedAt = undefined;
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
data.id = ++lastId;
|
|
1105
|
+
data.createdAt = Date.now();
|
|
1106
|
+
data.updatedAt = undefined;
|
|
1107
|
+
}
|
|
1122
1108
|
await this.checkUnique(tableName, schema);
|
|
1123
|
-
|
|
1109
|
+
data = this.formatData(data, schema);
|
|
1124
1110
|
const pathesContents = this.joinPathesContents(tableName, this.tables[tableName].config.prepend
|
|
1125
|
-
? Array.isArray(
|
|
1126
|
-
?
|
|
1127
|
-
:
|
|
1128
|
-
:
|
|
1111
|
+
? Array.isArray(data)
|
|
1112
|
+
? data.toReversed()
|
|
1113
|
+
: data
|
|
1114
|
+
: data);
|
|
1129
1115
|
await Promise.all(Object.entries(pathesContents).map(async ([path, content]) => renameList.push(this.tables[tableName].config.prepend
|
|
1130
1116
|
? await File.prepend(path, content)
|
|
1131
1117
|
: await File.append(path, content))));
|
|
@@ -1133,17 +1119,19 @@ export default class Inibase {
|
|
|
1133
1119
|
renameList = [];
|
|
1134
1120
|
if (this.tables[tableName].config.cache)
|
|
1135
1121
|
await this.clearCache(tableName);
|
|
1136
|
-
this.totalItems[`${tableName}-*`] += Array.isArray(
|
|
1137
|
-
?
|
|
1122
|
+
this.totalItems[`${tableName}-*`] += Array.isArray(data)
|
|
1123
|
+
? data.length
|
|
1138
1124
|
: 1;
|
|
1139
1125
|
await writeFile(join(tablePath, ".cache", ".pagination"), `${lastId},${this.totalItems[`${tableName}-*`]}`);
|
|
1140
1126
|
if (returnPostedData)
|
|
1141
1127
|
return this.get(tableName, this.tables[tableName].config.prepend
|
|
1142
|
-
? Array.isArray(
|
|
1143
|
-
?
|
|
1128
|
+
? Array.isArray(data)
|
|
1129
|
+
? data.map((_, index) => index + 1).toReversed()
|
|
1144
1130
|
: 1
|
|
1145
|
-
: Array.isArray(
|
|
1146
|
-
?
|
|
1131
|
+
: Array.isArray(data)
|
|
1132
|
+
? data
|
|
1133
|
+
.map((_, index) => this.totalItems[`${tableName}-*`] - index)
|
|
1134
|
+
.toReversed()
|
|
1147
1135
|
: this.totalItems[`${tableName}-*`], options, !Utils.isArrayOfObjects(data));
|
|
1148
1136
|
}
|
|
1149
1137
|
finally {
|
|
@@ -1163,12 +1151,12 @@ export default class Inibase {
|
|
|
1163
1151
|
if (!where) {
|
|
1164
1152
|
if (Utils.isArrayOfObjects(data)) {
|
|
1165
1153
|
if (!data.every((item) => Object.hasOwn(item, "id") && Utils.isValidID(item.id)))
|
|
1166
|
-
throw this.
|
|
1154
|
+
throw this.Error("INVALID_ID");
|
|
1167
1155
|
return this.put(tableName, data, data.map(({ id }) => id), options, returnUpdatedData || undefined);
|
|
1168
1156
|
}
|
|
1169
1157
|
if (Object.hasOwn(data, "id")) {
|
|
1170
1158
|
if (!Utils.isValidID(data.id))
|
|
1171
|
-
throw this.
|
|
1159
|
+
throw this.Error("INVALID_ID", data.id);
|
|
1172
1160
|
return this.put(tableName, data, data.id, options, returnUpdatedData || undefined);
|
|
1173
1161
|
}
|
|
1174
1162
|
let totalItems;
|
|
@@ -1251,7 +1239,7 @@ export default class Inibase {
|
|
|
1251
1239
|
return this.put(tableName, data, lineNumbers, options, returnUpdatedData || undefined);
|
|
1252
1240
|
}
|
|
1253
1241
|
else
|
|
1254
|
-
throw this.
|
|
1242
|
+
throw this.Error("INVALID_PARAMETERS");
|
|
1255
1243
|
}
|
|
1256
1244
|
/**
|
|
1257
1245
|
* Delete item(s) in a table
|
|
@@ -1314,7 +1302,7 @@ export default class Inibase {
|
|
|
1314
1302
|
return this.delete(tableName, lineNumbers);
|
|
1315
1303
|
}
|
|
1316
1304
|
else
|
|
1317
|
-
throw this.
|
|
1305
|
+
throw this.Error("INVALID_PARAMETERS");
|
|
1318
1306
|
return false;
|
|
1319
1307
|
}
|
|
1320
1308
|
async sum(tableName, columns, where) {
|
package/dist/utils.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ export declare const isPassword: (input: any) => input is string;
|
|
|
125
125
|
* @param input - The input to be checked, can be of any type.
|
|
126
126
|
* @returns A boolean indicating whether the input is a valid date.
|
|
127
127
|
*/
|
|
128
|
-
export declare
|
|
128
|
+
export declare function isDate(input?: any): boolean;
|
|
129
129
|
/**
|
|
130
130
|
* Checks if the input is a valid ID.
|
|
131
131
|
*
|
package/dist/utils.js
CHANGED
|
@@ -34,8 +34,8 @@ export const isArrayOfNulls = (input) => input.every((_input) => Array.isArray(_
|
|
|
34
34
|
* Note: Checks if the input is non-null and either has 'Object' as its constructor name or is of type 'object' without being an array.
|
|
35
35
|
*/
|
|
36
36
|
export const isObject = (obj) => obj != null &&
|
|
37
|
-
(obj
|
|
38
|
-
|
|
37
|
+
((typeof obj === "object" && !Array.isArray(obj)) ||
|
|
38
|
+
obj.constructor?.name === "Object");
|
|
39
39
|
/**
|
|
40
40
|
* Recursively merges properties from a source object into a target object. If a property exists in both, the source's value overwrites the target's.
|
|
41
41
|
*
|
|
@@ -152,9 +152,20 @@ export const isPassword = (input) => typeof input === "string" && input.length =
|
|
|
152
152
|
* @param input - The input to be checked, can be of any type.
|
|
153
153
|
* @returns A boolean indicating whether the input is a valid date.
|
|
154
154
|
*/
|
|
155
|
-
export
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
export function isDate(input) {
|
|
156
|
+
// Check if the input is null, undefined, or an empty string
|
|
157
|
+
if (input == null || input === "")
|
|
158
|
+
return false;
|
|
159
|
+
// Convert to number and check if it's a valid number
|
|
160
|
+
const numTimestamp = Number(input);
|
|
161
|
+
// Check if the converted number is NaN or not finite
|
|
162
|
+
if (Number.isNaN(numTimestamp) || !Number.isFinite(numTimestamp))
|
|
163
|
+
return false;
|
|
164
|
+
// Create a Date object from the timestamp
|
|
165
|
+
const date = new Date(numTimestamp);
|
|
166
|
+
// Check if the date is valid
|
|
167
|
+
return date.getTime() === numTimestamp;
|
|
168
|
+
}
|
|
158
169
|
/**
|
|
159
170
|
* Checks if the input is a valid ID.
|
|
160
171
|
*
|