inibase 1.0.0-rc.15 → 1.0.0-rc.16
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 -1
- package/dist/file.d.ts +8 -6
- package/dist/file.js +365 -413
- package/dist/index.d.ts +5 -7
- package/dist/index.js +38 -69
- package/dist/utils.d.ts +1 -14
- package/dist/utils.js +9 -76
- package/dist/utils.server.d.ts +16 -0
- package/dist/utils.server.js +77 -0
- package/package.json +30 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
export interface Data {
|
|
3
3
|
id?: number | string;
|
|
4
4
|
[key: string]: any;
|
|
@@ -46,7 +46,7 @@ type pageInfo = {
|
|
|
46
46
|
export type Criteria = ({
|
|
47
47
|
[logic in "and" | "or"]?: Criteria | (string | number | boolean | null)[];
|
|
48
48
|
} & {
|
|
49
|
-
[key: string]: string | number | boolean | Criteria;
|
|
49
|
+
[key: string]: string | number | boolean | undefined | Criteria;
|
|
50
50
|
}) | null;
|
|
51
51
|
declare global {
|
|
52
52
|
type Entries<T> = {
|
|
@@ -72,11 +72,9 @@ export default class Inibase {
|
|
|
72
72
|
validateData(data: Data | Data[], schema: Schema, skipRequiredField?: boolean): void;
|
|
73
73
|
formatData<dataType extends Data | Data[]>(data: dataType, schema: Schema, formatOnlyAvailiableKeys?: boolean): dataType extends Data ? Data : Data[];
|
|
74
74
|
private getDefaultValue;
|
|
75
|
-
private
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
get<O extends boolean = false, N extends boolean = false>(tableName: string, where?: string | number | (string | number)[] | Criteria, options?: Options, onlyOne?: O, onlyLinesNumbers?: N): Promise<(N extends true ? number[] : O extends true ? Data : Data[]) | null>;
|
|
75
|
+
private joinPathesContents;
|
|
76
|
+
get(tableName: string, where?: string | number | (string | number)[] | Criteria | undefined, options?: Options | undefined, onlyOne?: true, onlyLinesNumbers?: undefined): Promise<Data | null>;
|
|
77
|
+
get(tableName: string, where?: string | number | (string | number)[] | Criteria | undefined, options?: Options | undefined, onlyOne?: boolean | undefined, onlyLinesNumbers?: true): Promise<number[] | null>;
|
|
80
78
|
post<DataType extends Data | Data[]>(tableName: string, data: DataType, options?: Options, returnPostedData?: boolean): Promise<DataType extends Data ? Data | null | void : Data[] | null | void>;
|
|
81
79
|
put<returnPostedDataType extends boolean = true>(tableName: string, data: Data | Data[], where?: number | string | (number | string)[] | Criteria, options?: Options, returnPostedData?: returnPostedDataType): Promise<(returnPostedDataType extends true ? Data | Data[] : void) | null>;
|
|
82
80
|
delete(tableName: string, where?: number | string | (number | string)[] | Criteria, _id?: string | string[]): Promise<string | string[] | null>;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { unlink, rename, readFile, writeFile, mkdir, readdir, } from "node:fs/promises";
|
|
2
2
|
import { join, parse } from "node:path";
|
|
3
3
|
import { scryptSync } from "node:crypto";
|
|
4
|
-
import File from "./file";
|
|
5
|
-
import Utils from "./utils";
|
|
4
|
+
import File from "./file.js";
|
|
5
|
+
import Utils from "./utils.js";
|
|
6
|
+
import UtilsServer from "./utils.server.js";
|
|
6
7
|
export default class Inibase {
|
|
7
8
|
folder;
|
|
8
9
|
database;
|
|
@@ -50,12 +51,12 @@ export default class Inibase {
|
|
|
50
51
|
if (field.children && Utils.isArrayOfObjects(field.children))
|
|
51
52
|
field.children = decodeIdFromSchema(field.children);
|
|
52
53
|
if (!Utils.isNumber(field.id))
|
|
53
|
-
field.id =
|
|
54
|
+
field.id = UtilsServer.decodeID(field.id, this.salt);
|
|
54
55
|
return field;
|
|
55
56
|
});
|
|
56
57
|
// remove id from schema
|
|
57
58
|
schema = schema.filter(({ key }) => !["id", "createdAt", "updatedAt"].includes(key));
|
|
58
|
-
schema =
|
|
59
|
+
schema = UtilsServer.addIdToSchema(schema, UtilsServer.findLastIdNumber(schema, this.salt), this.salt);
|
|
59
60
|
const TablePath = join(this.folder, this.database, tableName), TableSchemaPath = join(TablePath, "schema.json");
|
|
60
61
|
if (!(await File.isExists(TablePath)))
|
|
61
62
|
await mkdir(TablePath, { recursive: true });
|
|
@@ -68,7 +69,7 @@ export default class Inibase {
|
|
|
68
69
|
Utils.deepMerge(RETURN, schemaToIdsPath(field.children, (prefix ?? "") + field.key + "."));
|
|
69
70
|
}
|
|
70
71
|
else if (Utils.isValidID(field.id))
|
|
71
|
-
RETURN[
|
|
72
|
+
RETURN[UtilsServer.decodeID(field.id, this.salt)] =
|
|
72
73
|
(prefix ?? "") + field.key + ".inib";
|
|
73
74
|
return RETURN;
|
|
74
75
|
}, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath(await this.getTableSchema(tableName)), schemaToIdsPath(schema));
|
|
@@ -87,23 +88,23 @@ export default class Inibase {
|
|
|
87
88
|
this.cache.set(TableSchemaPath, await readFile(TableSchemaPath, "utf8"));
|
|
88
89
|
if (!this.cache.get(TableSchemaPath))
|
|
89
90
|
return undefined;
|
|
90
|
-
const schema = JSON.parse(this.cache.get(TableSchemaPath)), lastIdNumber =
|
|
91
|
+
const schema = JSON.parse(this.cache.get(TableSchemaPath)), lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
91
92
|
return [
|
|
92
93
|
{
|
|
93
|
-
id:
|
|
94
|
+
id: UtilsServer.encodeID(0, this.salt),
|
|
94
95
|
key: "id",
|
|
95
96
|
type: "id",
|
|
96
97
|
required: true,
|
|
97
98
|
},
|
|
98
|
-
...
|
|
99
|
+
...UtilsServer.addIdToSchema(schema, lastIdNumber, this.salt),
|
|
99
100
|
{
|
|
100
|
-
id:
|
|
101
|
+
id: UtilsServer.encodeID(lastIdNumber + 1, this.salt),
|
|
101
102
|
key: "createdAt",
|
|
102
103
|
type: "date",
|
|
103
104
|
required: true,
|
|
104
105
|
},
|
|
105
106
|
{
|
|
106
|
-
id:
|
|
107
|
+
id: UtilsServer.encodeID(lastIdNumber + 2, this.salt),
|
|
107
108
|
key: "updatedAt",
|
|
108
109
|
type: "date",
|
|
109
110
|
required: false,
|
|
@@ -173,16 +174,16 @@ export default class Inibase {
|
|
|
173
174
|
(Utils.isValidID(item.id) || Utils.isNumber(item.id))))
|
|
174
175
|
value.map((item) => Utils.isNumber(item.id)
|
|
175
176
|
? Number(item.id)
|
|
176
|
-
:
|
|
177
|
+
: UtilsServer.decodeID(item.id, this.salt));
|
|
177
178
|
}
|
|
178
179
|
else if (value.every(Utils.isValidID) ||
|
|
179
180
|
value.every(Utils.isNumber))
|
|
180
181
|
return value.map((item) => Utils.isNumber(item)
|
|
181
182
|
? Number(item)
|
|
182
|
-
:
|
|
183
|
+
: UtilsServer.decodeID(item, this.salt));
|
|
183
184
|
}
|
|
184
185
|
else if (Utils.isValidID(value))
|
|
185
|
-
return [
|
|
186
|
+
return [UtilsServer.decodeID(value, this.salt)];
|
|
186
187
|
else if (Utils.isNumber(value))
|
|
187
188
|
return [Number(value)];
|
|
188
189
|
}
|
|
@@ -207,19 +208,19 @@ export default class Inibase {
|
|
|
207
208
|
Utils.isNumber(value.id)))
|
|
208
209
|
return Utils.isNumber(value.id)
|
|
209
210
|
? Number(value.id)
|
|
210
|
-
:
|
|
211
|
+
: UtilsServer.decodeID(value.id, this.salt);
|
|
211
212
|
}
|
|
212
213
|
else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
213
214
|
return Utils.isNumber(value)
|
|
214
215
|
? Number(value)
|
|
215
|
-
:
|
|
216
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
216
217
|
break;
|
|
217
218
|
case "password":
|
|
218
219
|
if (Array.isArray(value))
|
|
219
220
|
value = value[0];
|
|
220
221
|
return typeof value === "string" && value.length === 161
|
|
221
222
|
? value
|
|
222
|
-
:
|
|
223
|
+
: UtilsServer.hashPassword(String(value));
|
|
223
224
|
case "number":
|
|
224
225
|
if (Array.isArray(value))
|
|
225
226
|
value = value[0];
|
|
@@ -229,7 +230,7 @@ export default class Inibase {
|
|
|
229
230
|
value = value[0];
|
|
230
231
|
return Utils.isNumber(value)
|
|
231
232
|
? value
|
|
232
|
-
:
|
|
233
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
233
234
|
default:
|
|
234
235
|
return value;
|
|
235
236
|
}
|
|
@@ -282,46 +283,13 @@ export default class Inibase {
|
|
|
282
283
|
return null;
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
else {
|
|
290
|
-
return Object.fromEntries(Object.entries(Utils.objectToDotNotation(data)).map(([key, value]) => [
|
|
286
|
+
joinPathesContents(mainPath, data) {
|
|
287
|
+
return Utils.isArrayOfObjects(data)
|
|
288
|
+
? Utils.combineObjects(data.map((single_data) => this.joinPathesContents(mainPath, single_data)))
|
|
289
|
+
: Object.fromEntries(Object.entries(Utils.objectToDotNotation(data)).map(([key, value]) => [
|
|
291
290
|
join(mainPath, key + ".inib"),
|
|
292
|
-
|
|
291
|
+
File.encode(value, this.salt),
|
|
293
292
|
]));
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
joinPathesContents(mainPath, data, startWith = 1) {
|
|
297
|
-
const CombineData = (_data, prefix) => {
|
|
298
|
-
let RETURN = {};
|
|
299
|
-
const combineObjectsToArray = (input) => input.reduce((r, c) => (Object.keys(c).map((k) => (r[k] = [...(r[k] || []), c[k]])), r), {});
|
|
300
|
-
if (Utils.isArrayOfObjects(_data))
|
|
301
|
-
RETURN = combineObjectsToArray(_data.map((single_data) => CombineData(single_data)));
|
|
302
|
-
else {
|
|
303
|
-
for (const [key, value] of Object.entries(_data)) {
|
|
304
|
-
if (Utils.isObject(value))
|
|
305
|
-
Object.assign(RETURN, CombineData(value, `${key}.`));
|
|
306
|
-
else if (Utils.isArrayOfObjects(value)) {
|
|
307
|
-
Object.assign(RETURN, CombineData(combineObjectsToArray(value), (prefix ?? "") + key + "."));
|
|
308
|
-
}
|
|
309
|
-
else if (Utils.isArrayOfArrays(value) &&
|
|
310
|
-
value.every(Utils.isArrayOfObjects))
|
|
311
|
-
Object.assign(RETURN, CombineData(combineObjectsToArray(value.map(combineObjectsToArray)), (prefix ?? "") + key + "."));
|
|
312
|
-
else
|
|
313
|
-
RETURN[(prefix ?? "") + key] = File.encode(value);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return RETURN;
|
|
317
|
-
};
|
|
318
|
-
const addPathToKeys = (obj, path) => {
|
|
319
|
-
const newObject = {};
|
|
320
|
-
for (const key in obj)
|
|
321
|
-
newObject[join(path, key + ".inib")] = obj[key];
|
|
322
|
-
return newObject;
|
|
323
|
-
};
|
|
324
|
-
return addPathToKeys(CombineData(data), mainPath);
|
|
325
293
|
}
|
|
326
294
|
async get(tableName, where, options = {
|
|
327
295
|
page: 1,
|
|
@@ -533,8 +501,8 @@ export default class Inibase {
|
|
|
533
501
|
let Ids = where;
|
|
534
502
|
if (!Array.isArray(Ids))
|
|
535
503
|
Ids = [Ids];
|
|
536
|
-
const [lineNumbers, countItems] = await File.search(idFilePath, "[]", Ids.map((id) => Utils.isNumber(id) ? Number(id) :
|
|
537
|
-
if (!lineNumbers
|
|
504
|
+
const [lineNumbers, countItems] = await File.search(idFilePath, "[]", Ids.map((id) => Utils.isNumber(id) ? Number(id) : UtilsServer.decodeID(id, this.salt)), undefined, "number", undefined, Ids.length, 0, false, this.salt);
|
|
505
|
+
if (!lineNumbers)
|
|
538
506
|
throw this.throwError("INVALID_ID", where);
|
|
539
507
|
if (onlyLinesNumbers)
|
|
540
508
|
return Object.keys(lineNumbers).map(Number);
|
|
@@ -709,7 +677,7 @@ export default class Inibase {
|
|
|
709
677
|
total_pages: Math.ceil(greatestTotalItems / options.per_page),
|
|
710
678
|
total: greatestTotalItems,
|
|
711
679
|
};
|
|
712
|
-
return onlyOne ? RETURN[0] : RETURN;
|
|
680
|
+
return onlyOne && Array.isArray(RETURN) ? RETURN[0] : RETURN;
|
|
713
681
|
}
|
|
714
682
|
async post(tableName, data, options = {
|
|
715
683
|
page: 1,
|
|
@@ -721,7 +689,7 @@ export default class Inibase {
|
|
|
721
689
|
throw this.throwError("NO_SCHEMA", tableName);
|
|
722
690
|
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
723
691
|
let [last_line_number, last_id] = (await File.isExists(idFilePath))
|
|
724
|
-
? Object.entries((await File.get(idFilePath, -1, "number", undefined, this.salt))[0])[0] ?? [0, 0]
|
|
692
|
+
? Object.entries((await File.get(idFilePath, -1, "number", undefined, this.salt))[0])[0]?.map(Number) ?? [0, 0]
|
|
725
693
|
: [0, 0];
|
|
726
694
|
if (Utils.isArrayOfObjects(data))
|
|
727
695
|
RETURN = data.map(({ id, updatedAt, createdAt, ...rest }) => ({
|
|
@@ -738,9 +706,10 @@ export default class Inibase {
|
|
|
738
706
|
if (!RETURN)
|
|
739
707
|
throw this.throwError("NO_DATA");
|
|
740
708
|
RETURN = this.formatData(RETURN, schema);
|
|
741
|
-
const pathesContents = this.
|
|
709
|
+
const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), RETURN);
|
|
710
|
+
last_line_number += 1;
|
|
742
711
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
743
|
-
await File.
|
|
712
|
+
await File.append(path, content, last_line_number);
|
|
744
713
|
if (returnPostedData)
|
|
745
714
|
return this.get(tableName, Utils.isArrayOfObjects(RETURN)
|
|
746
715
|
? RETURN.map((data) => data.id)
|
|
@@ -767,7 +736,7 @@ export default class Inibase {
|
|
|
767
736
|
else if (data.hasOwnProperty("id")) {
|
|
768
737
|
if (!Utils.isValidID(data.id))
|
|
769
738
|
throw this.throwError("INVALID_ID", data.id);
|
|
770
|
-
return this.put(tableName, data,
|
|
739
|
+
return this.put(tableName, data, UtilsServer.decodeID(data.id, this.salt));
|
|
771
740
|
}
|
|
772
741
|
else {
|
|
773
742
|
const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), Utils.isArrayOfObjects(data)
|
|
@@ -780,7 +749,7 @@ export default class Inibase {
|
|
|
780
749
|
updatedAt: new Date(),
|
|
781
750
|
});
|
|
782
751
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
783
|
-
await File.replace(path, content
|
|
752
|
+
await File.replace(path, content);
|
|
784
753
|
if (returnPostedData)
|
|
785
754
|
return this.get(tableName, where, options);
|
|
786
755
|
}
|
|
@@ -802,15 +771,15 @@ export default class Inibase {
|
|
|
802
771
|
...item,
|
|
803
772
|
updatedAt: new Date(),
|
|
804
773
|
}))
|
|
805
|
-
: { ...data, updatedAt: new Date() })).map(([
|
|
806
|
-
|
|
807
|
-
[...(Array.isArray(where) ? where : [where])].reduce((obj,
|
|
774
|
+
: { ...data, updatedAt: new Date() })).map(([path, content]) => [
|
|
775
|
+
path,
|
|
776
|
+
[...(Array.isArray(where) ? where : [where])].reduce((obj, lineNum, index) => ({
|
|
808
777
|
...obj,
|
|
809
|
-
[
|
|
778
|
+
[lineNum]: Array.isArray(content) ? content[index] : content,
|
|
810
779
|
}), {}),
|
|
811
780
|
]));
|
|
812
781
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
813
|
-
await File.replace(path, content
|
|
782
|
+
await File.replace(path, content);
|
|
814
783
|
if (returnPostedData)
|
|
815
784
|
return this.get(tableName, where, options, !Array.isArray(where));
|
|
816
785
|
}
|
|
@@ -854,7 +823,7 @@ export default class Inibase {
|
|
|
854
823
|
const files = await readdir(join(this.folder, this.database, tableName));
|
|
855
824
|
if (files.length) {
|
|
856
825
|
if (!_id)
|
|
857
|
-
_id = Object.values((await File.get(join(this.folder, this.database, tableName, "id.inib"), where, "number", undefined, this.salt))[0]).map((id) =>
|
|
826
|
+
_id = Object.values((await File.get(join(this.folder, this.database, tableName, "id.inib"), where, "number", undefined, this.salt))[0]).map((id) => UtilsServer.encodeID(Number(id), this.salt));
|
|
858
827
|
for (const file of files.filter((fileName) => fileName.endsWith(".inib")))
|
|
859
828
|
await File.remove(join(this.folder, this.database, tableName, file), where);
|
|
860
829
|
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { FieldType, Schema } from ".";
|
|
1
|
+
import { type FieldType } from "./index.js";
|
|
3
2
|
export declare const isArrayOfObjects: (input: any) => input is Record<any, any>[];
|
|
4
3
|
export declare const isArrayOfArrays: (input: any) => input is any[][];
|
|
5
4
|
export declare const isObject: (obj: any) => boolean;
|
|
@@ -18,12 +17,6 @@ export declare const isValidID: (input: any) => input is string;
|
|
|
18
17
|
export declare const findChangedProperties: (obj1: Record<string, string>, obj2: Record<string, string>) => Record<string, string> | null;
|
|
19
18
|
export declare const detectFieldType: (input: any, availableTypes: FieldType[]) => FieldType | undefined;
|
|
20
19
|
export declare const validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => boolean;
|
|
21
|
-
export declare const hashPassword: (password: string) => string;
|
|
22
|
-
export declare const comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
|
|
23
|
-
export declare const encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
|
|
24
|
-
export declare const decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
25
|
-
export declare const findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
|
|
26
|
-
export declare const addIdToSchema: (schema: Schema, oldIndex: number, secretKeyOrSalt: string | number | Buffer) => import(".").Field[];
|
|
27
20
|
export declare const objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
|
|
28
21
|
export default class Utils {
|
|
29
22
|
static isNumber: (input: any) => input is number;
|
|
@@ -44,11 +37,5 @@ export default class Utils {
|
|
|
44
37
|
static isHTML: (input: any) => boolean;
|
|
45
38
|
static isIP: (input: any) => boolean;
|
|
46
39
|
static validateFieldType: (value: any, fieldType: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[]) => boolean;
|
|
47
|
-
static encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
|
|
48
|
-
static decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
49
|
-
static hashPassword: (password: string) => string;
|
|
50
|
-
static comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
|
|
51
|
-
static findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
|
|
52
|
-
static addIdToSchema: (schema: Schema, oldIndex: number, secretKeyOrSalt: string | number | Buffer) => import(".").Field[];
|
|
53
40
|
static objectToDotNotation: (input: Record<string, any>) => Record<string, string | number | (string | number)[]>;
|
|
54
41
|
}
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, randomBytes, scryptSync, createHash, } from "node:crypto";
|
|
2
1
|
export const isArrayOfObjects = (input) => Array.isArray(input) && (input.length === 0 || input.every(isObject));
|
|
3
2
|
export const isArrayOfArrays = (input) => Array.isArray(input) && (input.length === 0 || input.every(Array.isArray));
|
|
4
3
|
export const isObject = (obj) => obj != null &&
|
|
@@ -25,13 +24,20 @@ export const combineObjects = (arr) => {
|
|
|
25
24
|
if (typeof existingValue === "object" &&
|
|
26
25
|
typeof newValue === "object" &&
|
|
27
26
|
existingValue !== null &&
|
|
28
|
-
|
|
27
|
+
existingValue !== undefined &&
|
|
28
|
+
newValue !== null &&
|
|
29
|
+
newValue !== undefined) {
|
|
29
30
|
// If both values are objects, recursively combine them
|
|
30
31
|
result[key] = combineObjects([existingValue, newValue]);
|
|
31
32
|
}
|
|
32
33
|
else {
|
|
33
34
|
// If one or both values are not objects, overwrite the existing value
|
|
34
|
-
result[key] =
|
|
35
|
+
result[key] =
|
|
36
|
+
existingValue !== null && existingValue !== undefined
|
|
37
|
+
? Array.isArray(existingValue)
|
|
38
|
+
? [...existingValue, newValue]
|
|
39
|
+
: [existingValue, newValue]
|
|
40
|
+
: newValue;
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
}
|
|
@@ -174,73 +180,6 @@ export const validateFieldType = (value, fieldType, fieldChildrenType) => {
|
|
|
174
180
|
return false;
|
|
175
181
|
}
|
|
176
182
|
};
|
|
177
|
-
export const hashPassword = (password) => {
|
|
178
|
-
const salt = randomBytes(16).toString("hex");
|
|
179
|
-
const hash = createHash("sha256")
|
|
180
|
-
.update(password + salt)
|
|
181
|
-
.digest("hex");
|
|
182
|
-
return `${salt}:${hash}`;
|
|
183
|
-
};
|
|
184
|
-
export const comparePassword = (hashedPassword, inputPassword) => {
|
|
185
|
-
const [salt, originalHash] = hashedPassword.split(":");
|
|
186
|
-
const inputHash = createHash("sha256")
|
|
187
|
-
.update(inputPassword + salt)
|
|
188
|
-
.digest("hex");
|
|
189
|
-
return inputHash === originalHash;
|
|
190
|
-
};
|
|
191
|
-
export const encodeID = (id, secretKeyOrSalt) => {
|
|
192
|
-
let cipher, ret;
|
|
193
|
-
if (Buffer.isBuffer(secretKeyOrSalt))
|
|
194
|
-
cipher = createCipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
|
|
195
|
-
else {
|
|
196
|
-
const salt = scryptSync(secretKeyOrSalt.toString(), (process.env.INIBASE_SECRET ?? "inibase") + "_salt", 32);
|
|
197
|
-
cipher = createCipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
|
|
198
|
-
}
|
|
199
|
-
return cipher.update(id.toString(), "utf8", "hex") + cipher.final("hex");
|
|
200
|
-
};
|
|
201
|
-
export const decodeID = (input, secretKeyOrSalt) => {
|
|
202
|
-
let decipher;
|
|
203
|
-
if (Buffer.isBuffer(secretKeyOrSalt))
|
|
204
|
-
decipher = createDecipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
|
|
205
|
-
else {
|
|
206
|
-
const salt = scryptSync(secretKeyOrSalt.toString(), (process.env.INIBASE_SECRET ?? "inibase") + "_salt", 32);
|
|
207
|
-
decipher = createDecipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
|
|
208
|
-
}
|
|
209
|
-
return Number(decipher.update(input, "hex", "utf8") + decipher.final("utf8"));
|
|
210
|
-
};
|
|
211
|
-
export const findLastIdNumber = (schema, secretKeyOrSalt) => {
|
|
212
|
-
const lastField = schema[schema.length - 1];
|
|
213
|
-
if (lastField) {
|
|
214
|
-
if ((lastField.type === "array" || lastField.type === "object") &&
|
|
215
|
-
isArrayOfObjects(lastField.children))
|
|
216
|
-
return findLastIdNumber(lastField.children, secretKeyOrSalt);
|
|
217
|
-
else if (lastField.id)
|
|
218
|
-
return isValidID(lastField.id)
|
|
219
|
-
? decodeID(lastField.id, secretKeyOrSalt)
|
|
220
|
-
: lastField.id;
|
|
221
|
-
}
|
|
222
|
-
return 0;
|
|
223
|
-
};
|
|
224
|
-
export const addIdToSchema = (schema, oldIndex = 0, secretKeyOrSalt) => schema.map((field) => {
|
|
225
|
-
if (!field.id) {
|
|
226
|
-
oldIndex++;
|
|
227
|
-
field.id = encodeID(oldIndex, secretKeyOrSalt);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
if (!isNumber(field.id))
|
|
231
|
-
oldIndex = decodeID(field.id, secretKeyOrSalt);
|
|
232
|
-
else {
|
|
233
|
-
oldIndex = field.id;
|
|
234
|
-
field.id = encodeID(field.id, secretKeyOrSalt);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
if ((field.type === "array" || field.type === "object") &&
|
|
238
|
-
isArrayOfObjects(field.children)) {
|
|
239
|
-
field.children = addIdToSchema(field.children, oldIndex, secretKeyOrSalt);
|
|
240
|
-
oldIndex += field.children.length;
|
|
241
|
-
}
|
|
242
|
-
return field;
|
|
243
|
-
});
|
|
244
183
|
export const objectToDotNotation = (input) => {
|
|
245
184
|
const result = {};
|
|
246
185
|
const stack = [
|
|
@@ -291,11 +230,5 @@ export default class Utils {
|
|
|
291
230
|
static isHTML = isHTML;
|
|
292
231
|
static isIP = isIP;
|
|
293
232
|
static validateFieldType = validateFieldType;
|
|
294
|
-
static encodeID = encodeID;
|
|
295
|
-
static decodeID = decodeID;
|
|
296
|
-
static hashPassword = hashPassword;
|
|
297
|
-
static comparePassword = comparePassword;
|
|
298
|
-
static findLastIdNumber = findLastIdNumber;
|
|
299
|
-
static addIdToSchema = addIdToSchema;
|
|
300
233
|
static objectToDotNotation = objectToDotNotation;
|
|
301
234
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { type Schema } from "./index.js";
|
|
3
|
+
export declare const hashPassword: (password: string) => string;
|
|
4
|
+
export declare const comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
|
|
5
|
+
export declare const encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
|
|
6
|
+
export declare const decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
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[];
|
|
9
|
+
export default class UtilsServer {
|
|
10
|
+
static encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
|
|
11
|
+
static decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
|
|
12
|
+
static hashPassword: (password: string) => string;
|
|
13
|
+
static comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
|
|
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[];
|
|
16
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes, scryptSync, createHash, } from "node:crypto";
|
|
2
|
+
import Utils from "./utils.js";
|
|
3
|
+
export const hashPassword = (password) => {
|
|
4
|
+
const salt = randomBytes(16).toString("hex");
|
|
5
|
+
const hash = createHash("sha256")
|
|
6
|
+
.update(password + salt)
|
|
7
|
+
.digest("hex");
|
|
8
|
+
return `${salt}:${hash}`;
|
|
9
|
+
};
|
|
10
|
+
export const comparePassword = (hashedPassword, inputPassword) => {
|
|
11
|
+
const [salt, originalHash] = hashedPassword.split(":");
|
|
12
|
+
const inputHash = createHash("sha256")
|
|
13
|
+
.update(inputPassword + salt)
|
|
14
|
+
.digest("hex");
|
|
15
|
+
return inputHash === originalHash;
|
|
16
|
+
};
|
|
17
|
+
export const encodeID = (id, secretKeyOrSalt) => {
|
|
18
|
+
let cipher;
|
|
19
|
+
if (Buffer.isBuffer(secretKeyOrSalt))
|
|
20
|
+
cipher = createCipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
|
|
21
|
+
else {
|
|
22
|
+
const salt = scryptSync(secretKeyOrSalt.toString(), (process.env.INIBASE_SECRET ?? "inibase") + "_salt", 32);
|
|
23
|
+
cipher = createCipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
|
|
24
|
+
}
|
|
25
|
+
return cipher.update(id.toString(), "utf8", "hex") + cipher.final("hex");
|
|
26
|
+
};
|
|
27
|
+
export const decodeID = (input, secretKeyOrSalt) => {
|
|
28
|
+
let decipher;
|
|
29
|
+
if (Buffer.isBuffer(secretKeyOrSalt))
|
|
30
|
+
decipher = createDecipheriv("aes-256-cbc", secretKeyOrSalt, secretKeyOrSalt.subarray(0, 16));
|
|
31
|
+
else {
|
|
32
|
+
const salt = scryptSync(secretKeyOrSalt.toString(), (process.env.INIBASE_SECRET ?? "inibase") + "_salt", 32);
|
|
33
|
+
decipher = createDecipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
|
|
34
|
+
}
|
|
35
|
+
return Number(decipher.update(input, "hex", "utf8") + decipher.final("utf8"));
|
|
36
|
+
};
|
|
37
|
+
export const findLastIdNumber = (schema, secretKeyOrSalt) => {
|
|
38
|
+
const lastField = schema[schema.length - 1];
|
|
39
|
+
if (lastField) {
|
|
40
|
+
if ((lastField.type === "array" || lastField.type === "object") &&
|
|
41
|
+
Utils.isArrayOfObjects(lastField.children))
|
|
42
|
+
return findLastIdNumber(lastField.children, secretKeyOrSalt);
|
|
43
|
+
else if (lastField.id)
|
|
44
|
+
return Utils.isValidID(lastField.id)
|
|
45
|
+
? decodeID(lastField.id, secretKeyOrSalt)
|
|
46
|
+
: lastField.id;
|
|
47
|
+
}
|
|
48
|
+
return 0;
|
|
49
|
+
};
|
|
50
|
+
export const addIdToSchema = (schema, oldIndex = 0, secretKeyOrSalt) => schema.map((field) => {
|
|
51
|
+
if (!field.id) {
|
|
52
|
+
oldIndex++;
|
|
53
|
+
field.id = encodeID(oldIndex, secretKeyOrSalt);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
if (!Utils.isNumber(field.id))
|
|
57
|
+
oldIndex = decodeID(field.id, secretKeyOrSalt);
|
|
58
|
+
else {
|
|
59
|
+
oldIndex = field.id;
|
|
60
|
+
field.id = encodeID(field.id, secretKeyOrSalt);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if ((field.type === "array" || field.type === "object") &&
|
|
64
|
+
Utils.isArrayOfObjects(field.children)) {
|
|
65
|
+
field.children = addIdToSchema(field.children, oldIndex, secretKeyOrSalt);
|
|
66
|
+
oldIndex += field.children.length;
|
|
67
|
+
}
|
|
68
|
+
return field;
|
|
69
|
+
});
|
|
70
|
+
export default class UtilsServer {
|
|
71
|
+
static encodeID = encodeID;
|
|
72
|
+
static decodeID = decodeID;
|
|
73
|
+
static hashPassword = hashPassword;
|
|
74
|
+
static comparePassword = comparePassword;
|
|
75
|
+
static findLastIdNumber = findLastIdNumber;
|
|
76
|
+
static addIdToSchema = addIdToSchema;
|
|
77
|
+
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inibase",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.16",
|
|
4
4
|
"description": "File-based Relational Database for large data",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist",
|
|
5
7
|
"files": [
|
|
6
|
-
"dist"
|
|
8
|
+
"/dist"
|
|
7
9
|
],
|
|
8
|
-
"types": "./dist",
|
|
9
10
|
"type": "module",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "npx tsc",
|
|
12
|
-
"test": "npx tsx watch ./index.test",
|
|
13
|
-
"benchmark": "npx tsx watch ./benchmark.ts"
|
|
14
|
-
},
|
|
15
11
|
"repository": "inicontent/inibase",
|
|
16
12
|
"keywords": [
|
|
17
13
|
"db",
|
|
@@ -40,10 +36,34 @@
|
|
|
40
36
|
},
|
|
41
37
|
"homepage": "https://github.com/inicontent/inibase#readme",
|
|
42
38
|
"devDependencies": {
|
|
43
|
-
"@types/node": "^20.
|
|
39
|
+
"@types/node": "^20.10.0",
|
|
44
40
|
"typescript": "^5.3.2"
|
|
45
41
|
},
|
|
42
|
+
"exports": {
|
|
43
|
+
".": "./dist/index.js",
|
|
44
|
+
"./file": "./dist/file.js",
|
|
45
|
+
"./utils": "./dist/utils.js",
|
|
46
|
+
"./utils.server": "./dist/utils.server.js"
|
|
47
|
+
},
|
|
48
|
+
"typesVersions": {
|
|
49
|
+
"*": {
|
|
50
|
+
"file": [
|
|
51
|
+
"./dist/file.d.ts"
|
|
52
|
+
],
|
|
53
|
+
"utils": [
|
|
54
|
+
"./dist/utils.d.ts"
|
|
55
|
+
],
|
|
56
|
+
"utils.server": [
|
|
57
|
+
"./dist/utils.server.d.ts"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
46
61
|
"engines": {
|
|
47
62
|
"node": ">=16"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "npx tsc",
|
|
66
|
+
"test": "npx tsx watch ./index.test",
|
|
67
|
+
"benchmark": "npx tsx watch ./benchmark.ts"
|
|
48
68
|
}
|
|
49
|
-
}
|
|
69
|
+
}
|