inibase 1.0.0-rc.3 → 1.0.0-rc.5

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/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.5",
4
4
  "description": "File-based Relational Database for large data",
5
5
  "main": "index.ts",
6
+ "type": "module",
6
7
  "repository": {
7
8
  "type": "git",
8
9
  "url": "git+https://github.com/inicontent/inibase.git"
@@ -32,6 +33,6 @@
32
33
  "@types/node": "^20.6.0"
33
34
  },
34
35
  "scripts": {
35
- "test": "echo \"Error: no test specified\" && exit 1"
36
+ "test": "npx tsx watch ./index.test.ts"
36
37
  }
37
38
  }
package/tsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2021",
3
+ "module": "ES2022",
4
+ "target": "ES2022",
4
5
  "moduleResolution": "node"
5
6
  }
6
7
  }
package/utils.ts CHANGED
@@ -1,49 +1,18 @@
1
+ import {
2
+ scryptSync,
3
+ randomBytes,
4
+ timingSafeEqual,
5
+ createDecipheriv,
6
+ createCipheriv,
7
+ } from "crypto";
1
8
  import { FieldType } from ".";
2
- import { scryptSync, randomBytes, timingSafeEqual } from "crypto";
3
-
4
- export const encode = (
5
- input: string | number | boolean | null | (string | number | boolean | null)[]
6
- ) => {
7
- const secureString = (input: string | number | boolean | null) => {
8
- if (["true", "false"].includes((input ?? "").toString()))
9
- return input ? 1 : 0;
10
- return typeof input === "string"
11
- ? decodeURIComponent(input)
12
- .replaceAll("<", "&lt;")
13
- .replaceAll(">", "&gt;")
14
- .replaceAll(",", "%2C")
15
- .replaceAll("\n", "\\n")
16
- .replaceAll("\r", "\\r")
17
- : input;
18
- };
19
- return Array.isArray(input)
20
- ? input.map(secureString).join(",")
21
- : secureString(input);
22
- };
23
-
24
- export const decode = (
25
- input: string | null | number,
26
- fieldType?: FieldType
27
- ): string | number | boolean | null | (string | number | null | boolean)[] => {
28
- const unSecureString = (input: string) =>
29
- decodeURIComponent(input)
30
- .replaceAll("&lt;", "<")
31
- .replaceAll("&gt;", ">")
32
- .replaceAll("%2C", ",")
33
- .replaceAll("\\n", "\n")
34
- .replaceAll("\\r", "\r") || null;
35
-
36
- if (input === null || input === "") return null;
37
- if (!isNaN(Number(input)) && isFinite(Number(input)))
38
- return fieldType === "boolean" ? Boolean(Number(input)) : Number(input);
39
- return (input as string).includes(",")
40
- ? (input as string).split(",").map(unSecureString)
41
- : unSecureString(input as string);
42
- };
43
9
 
44
10
  export const isArrayOfObjects = (arr: any) => {
45
11
  return Array.isArray(arr) && (arr.length === 0 || arr.every(isObject));
46
12
  };
13
+ export const isArrayOfArrays = (arr: any) => {
14
+ return Array.isArray(arr) && (arr.length === 0 || arr.every(Array.isArray));
15
+ };
47
16
 
48
17
  export const isObject = (obj: any) =>
49
18
  obj != null &&
@@ -76,6 +45,20 @@ export const isNumber = (input: any): boolean =>
76
45
  ? input.every(isNumber)
77
46
  : !isNaN(parseFloat(input)) && !isNaN(input - 0);
78
47
 
48
+ export const isEmail = (input: any) =>
49
+ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(input));
50
+
51
+ export const isURL = (input: any) =>
52
+ input[0] === "#" ||
53
+ /^((https?|www):\/\/)?[a-z0-9-]+(\.[a-z0-9-]+)*\.[a-z]+(\/[^\s]*)?$/.test(
54
+ input
55
+ );
56
+
57
+ export const isPassword = (input: any) => input.length === 161;
58
+
59
+ export const isDate = (input: any) =>
60
+ !isNaN(Date.parse(String(input))) && Date.parse(String(input)) >= 0;
61
+
79
62
  export const hashPassword = (password: string) => {
80
63
  const salt = randomBytes(16).toString("hex");
81
64
  const buf = scryptSync(password, salt, 64);
@@ -97,14 +80,86 @@ export const comparePassword = (
97
80
  return timingSafeEqual(hashedPasswordBuf, suppliedPasswordBuf);
98
81
  };
99
82
 
83
+ export const encodeID = (id: number, secretKey: string | number): string => {
84
+ const salt = scryptSync(secretKey.toString(), "salt", 32),
85
+ cipher = createCipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
86
+
87
+ return cipher.update(id.toString(), "utf8", "hex") + cipher.final("hex");
88
+ };
89
+
90
+ export const decodeID = (input: string, secretKey: string | number): number => {
91
+ const salt = scryptSync(secretKey.toString(), "salt", 32),
92
+ decipher = createDecipheriv("aes-256-cbc", salt, salt.subarray(0, 16));
93
+ return Number(
94
+ decipher.update(input as string, "hex", "utf8") + decipher.final("utf8")
95
+ );
96
+ };
97
+
98
+ export const isValidID = (input: any): boolean => {
99
+ return Array.isArray(input)
100
+ ? input.every(isValidID)
101
+ : typeof input === "string" && input.length === 32;
102
+ };
103
+
104
+ export const findChangedProperties = (
105
+ obj1: Record<string, string>,
106
+ obj2: Record<string, string>
107
+ ): Record<string, string> | null => {
108
+ const result: Record<string, string> = {};
109
+
110
+ for (const key1 in obj1)
111
+ if (obj2.hasOwnProperty(key1) && obj1[key1] !== obj2[key1])
112
+ result[obj1[key1]] = obj2[key1];
113
+
114
+ return Object.keys(result).length ? result : null;
115
+ };
116
+
117
+ export const detectFieldType = (
118
+ input: any,
119
+ availableTypes: FieldType[]
120
+ ): FieldType | undefined => {
121
+ if (
122
+ (input === "0" || input === "1" || input === "true" || input === "false") &&
123
+ availableTypes.includes("boolean")
124
+ )
125
+ return "boolean";
126
+ else if (Utils.isNumber(input)) {
127
+ if (availableTypes.includes("table")) return "table";
128
+ else if (availableTypes.includes("number")) return "number";
129
+ else if (availableTypes.includes("date")) return "date";
130
+ } else if (
131
+ (Array.isArray(input) || input.includes(",")) &&
132
+ availableTypes.includes("array")
133
+ )
134
+ return "array";
135
+ else if (Utils.isEmail(input) && availableTypes.includes("email"))
136
+ return "email";
137
+ else if (Utils.isURL(input) && availableTypes.includes("url")) return "url";
138
+ else if (Utils.isPassword(input) && availableTypes.includes("password"))
139
+ return "password";
140
+ else if (Utils.isDate(input) && availableTypes.includes("date"))
141
+ return "date";
142
+ else if (!Utils.isNumber(input) && availableTypes.includes("string"))
143
+ return "string";
144
+ else return undefined;
145
+ };
146
+
100
147
  export default class Utils {
101
- static encode = encode;
102
- static decode = decode;
148
+ static encodeID = encodeID;
149
+ static decodeID = decodeID;
103
150
  static isNumber = isNumber;
104
151
  static isObject = isObject;
105
- static deepMerge = deepMerge;
152
+ static isEmail = isEmail;
153
+ static isDate = isDate;
154
+ static isURL = isURL;
155
+ static isValidID = isValidID;
156
+ static isPassword = isPassword;
106
157
  static hashPassword = hashPassword;
158
+ static deepMerge = deepMerge;
107
159
  static combineObjects = combineObjects;
108
160
  static comparePassword = comparePassword;
109
161
  static isArrayOfObjects = isArrayOfObjects;
162
+ static findChangedProperties = findChangedProperties;
163
+ static detectFieldType = detectFieldType;
164
+ static isArrayOfArrays = isArrayOfArrays;
110
165
  }