inibase 1.0.0-rc.12 → 1.0.0-rc.15

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/file.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /// <reference types="node" />
2
+ import { ComparisonOperator, FieldType } from ".";
3
+ export declare const isExists: (path: string) => Promise<boolean>;
4
+ export declare const encode: (input: string | number | boolean | null | (string | number | boolean | null)[], secretKey?: string | Buffer) => string | number | boolean;
5
+ export declare const decode: (input: string | null | number, fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], secretKey?: string | Buffer) => string | number | boolean | null | (string | number | null | boolean)[];
6
+ export declare const get: (filePath: string, lineNumbers?: number | number[], fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], secretKey?: string | Buffer) => Promise<[
7
+ Record<number, string | number | boolean | (string | number | boolean | (string | number | boolean)[])[]> | null,
8
+ number
9
+ ]>;
10
+ export declare const replace: (filePath: string, replacements: string | number | boolean | null | (string | number | boolean | null)[] | Record<number, string | boolean | number | null | (string | boolean | number | null)[]>, secretKey?: string | Buffer) => Promise<void>;
11
+ export declare const remove: (filePath: string, linesToDelete: number | number[]) => Promise<void>;
12
+ export declare const count: (filePath: string) => Promise<number>;
13
+ export declare const search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | null | (string | number | boolean | null)[], logicalOperator?: "and" | "or", fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], limit?: number, offset?: number, readWholeFile?: boolean, secretKey?: string | Buffer) => Promise<[
14
+ Record<number, Record<string, string | number | boolean | (string | number | boolean | null)[] | null>> | null,
15
+ number
16
+ ]>;
17
+ export declare const sum: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
18
+ export declare const max: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
19
+ export declare const min: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
20
+ export declare const sort: (filePath: string, sortDirection: 1 | -1 | "asc" | "desc", lineNumbers?: number | number[], _lineNumbersPerChunk?: number) => Promise<void>;
21
+ export default class File {
22
+ static get: (filePath: string, lineNumbers?: number | number[], fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], secretKey?: string | Buffer) => Promise<[Record<number, string | number | boolean | (string | number | boolean | (string | number | boolean)[])[]>, number]>;
23
+ static remove: (filePath: string, linesToDelete: number | number[]) => Promise<void>;
24
+ static search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | (string | number | boolean)[], logicalOperator?: "and" | "or", fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], limit?: number, offset?: number, readWholeFile?: boolean, secretKey?: string | Buffer) => Promise<[Record<number, Record<string, string | number | boolean | (string | number | boolean)[]>>, number]>;
25
+ static replace: (filePath: string, replacements: string | number | boolean | (string | number | boolean)[] | Record<number, string | number | boolean | (string | number | boolean)[]>, secretKey?: string | Buffer) => Promise<void>;
26
+ static count: (filePath: string) => Promise<number>;
27
+ static encode: (input: string | number | boolean | (string | number | boolean)[], secretKey?: string | Buffer) => string | number | boolean;
28
+ static decode: (input: string | number, fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], secretKey?: string | Buffer) => string | number | boolean | (string | number | boolean)[];
29
+ static isExists: (path: string) => Promise<boolean>;
30
+ static sum: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
31
+ static min: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
32
+ static max: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
33
+ }
package/dist/file.js ADDED
@@ -0,0 +1,501 @@
1
+ import { open, rename, stat, writeFile, } from "node:fs/promises";
2
+ import { createInterface } from "node:readline";
3
+ import { parse } from "node:path";
4
+ import { detectFieldType, isArrayOfArrays, isNumber, encodeID, comparePassword, } from "./utils";
5
+ const doesSupportReadLines = () => {
6
+ const [major, minor, patch] = process.versions.node.split(".").map(Number);
7
+ return major > 18 || (major === 18 && minor >= 11);
8
+ };
9
+ export const isExists = async (path) => {
10
+ try {
11
+ await stat(path);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ };
18
+ const delimiters = [",", "|", "&", "$", "#", "@", "^", "%", ":", "!", ";"];
19
+ export const encode = (input, secretKey) => {
20
+ const secureString = (input) => {
21
+ if (["true", "false"].includes(String(input)))
22
+ return input ? 1 : 0;
23
+ return typeof input === "string"
24
+ ? decodeURIComponent(input)
25
+ .replaceAll("<", "&lt;")
26
+ .replaceAll(">", "&gt;")
27
+ .replaceAll(",", "%2C")
28
+ .replaceAll("|", "%7C")
29
+ .replaceAll("&", "%26")
30
+ .replaceAll("$", "%24")
31
+ .replaceAll("#", "%23")
32
+ .replaceAll("@", "%40")
33
+ .replaceAll("^", "%5E")
34
+ .replaceAll("%", "%25")
35
+ .replaceAll(":", "%3A")
36
+ .replaceAll("!", "%21")
37
+ .replaceAll(";", "%3B")
38
+ .replaceAll("\n", "\\n")
39
+ .replaceAll("\r", "\\r")
40
+ : input;
41
+ }, secureArray = (arr_str) => Array.isArray(arr_str) ? arr_str.map(secureArray) : secureString(arr_str), joinMultidimensionalArray = (arr, delimiter_index = 0) => {
42
+ delimiter_index++;
43
+ if (isArrayOfArrays(arr))
44
+ arr = arr.map((ar) => joinMultidimensionalArray(ar, delimiter_index));
45
+ delimiter_index--;
46
+ return arr.join(delimiters[delimiter_index]);
47
+ };
48
+ return Array.isArray(input)
49
+ ? joinMultidimensionalArray(secureArray(input))
50
+ : secureString(input);
51
+ };
52
+ export const decode = (input, fieldType, fieldChildrenType, secretKey) => {
53
+ if (!fieldType)
54
+ return null;
55
+ const unSecureString = (input) => decodeURIComponent(input)
56
+ .replaceAll("&lt;", "<")
57
+ .replaceAll("&gt;", ">")
58
+ .replaceAll("%2C", ",")
59
+ .replaceAll("%7C", "|")
60
+ .replaceAll("%26", "&")
61
+ .replaceAll("%24", "$")
62
+ .replaceAll("%23", "#")
63
+ .replaceAll("%40", "@")
64
+ .replaceAll("%5E", "^")
65
+ .replaceAll("%25", "%")
66
+ .replaceAll("%3A", ":")
67
+ .replaceAll("%21", "!")
68
+ .replaceAll("%3B", ";")
69
+ .replaceAll("\\n", "\n")
70
+ .replaceAll("\\r", "\r") || null, unSecureArray = (arr_str) => Array.isArray(arr_str)
71
+ ? arr_str.map(unSecureArray)
72
+ : unSecureString(arr_str), reverseJoinMultidimensionalArray = (joinedString) => {
73
+ const reverseJoinMultidimensionalArrayHelper = (arr, delimiter) => Array.isArray(arr)
74
+ ? arr.map((ar) => reverseJoinMultidimensionalArrayHelper(ar, delimiter))
75
+ : arr.split(delimiter);
76
+ const availableDelimiters = delimiters.filter((delimiter) => joinedString.includes(delimiter));
77
+ for (const delimiter of availableDelimiters) {
78
+ joinedString = Array.isArray(joinedString)
79
+ ? reverseJoinMultidimensionalArrayHelper(joinedString, delimiter)
80
+ : joinedString.split(delimiter);
81
+ }
82
+ return joinedString;
83
+ }, decodeHelper = (value) => {
84
+ if (Array.isArray(value) && fieldType !== "array")
85
+ return value.map(decodeHelper);
86
+ switch (fieldType) {
87
+ case "table":
88
+ case "number":
89
+ return isNumber(value) ? Number(value) : null;
90
+ case "boolean":
91
+ return typeof value === "string" ? value === "true" : Boolean(value);
92
+ case "array":
93
+ if (!Array.isArray(value))
94
+ return [value];
95
+ if (fieldChildrenType)
96
+ return value.map((v) => decode(v, Array.isArray(fieldChildrenType)
97
+ ? detectFieldType(v, fieldChildrenType)
98
+ : fieldChildrenType, undefined, secretKey));
99
+ else
100
+ return value;
101
+ case "id":
102
+ return isNumber(value) ? encodeID(value, secretKey) : value;
103
+ default:
104
+ return value;
105
+ }
106
+ };
107
+ if (input === null || input === "")
108
+ return null;
109
+ if (Array.isArray(fieldType))
110
+ fieldType = detectFieldType(String(input), fieldType);
111
+ return decodeHelper(typeof input === "string"
112
+ ? input.includes(",")
113
+ ? unSecureArray(reverseJoinMultidimensionalArray(input))
114
+ : unSecureString(input)
115
+ : input);
116
+ };
117
+ export const get = async (filePath, lineNumbers, fieldType, fieldChildrenType, secretKey) => {
118
+ let fileHandle;
119
+ try {
120
+ fileHandle = await open(filePath, "r");
121
+ const rl = doesSupportReadLines()
122
+ ? fileHandle.readLines()
123
+ : createInterface({
124
+ input: fileHandle.createReadStream(),
125
+ crlfDelay: Infinity,
126
+ });
127
+ let lines = {}, lineCount = 0;
128
+ if (!lineNumbers) {
129
+ for await (const line of rl)
130
+ lineCount++,
131
+ (lines[lineCount] = decode(line, fieldType, fieldChildrenType, secretKey));
132
+ }
133
+ else if (lineNumbers === -1) {
134
+ let lastLine;
135
+ for await (const line of rl)
136
+ lineCount++, (lastLine = line);
137
+ if (lastLine)
138
+ lines = {
139
+ [lineCount]: decode(lastLine, fieldType, fieldChildrenType, secretKey),
140
+ };
141
+ }
142
+ else {
143
+ let lineNumbersArray = [
144
+ ...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
145
+ ];
146
+ for await (const line of rl) {
147
+ lineCount++;
148
+ if (!lineNumbersArray.includes(lineCount))
149
+ continue;
150
+ lines[lineCount] = decode(line, fieldType, fieldChildrenType, secretKey);
151
+ lineNumbersArray[lineNumbersArray.indexOf(lineCount)] = 0;
152
+ if (!lineNumbersArray.filter((lineN) => lineN !== 0).length)
153
+ break;
154
+ }
155
+ }
156
+ return [lines ?? null, lineCount];
157
+ }
158
+ finally {
159
+ await fileHandle?.close();
160
+ }
161
+ };
162
+ export const replace = async (filePath, replacements, secretKey) => {
163
+ if (await isExists(filePath)) {
164
+ const tempFilePath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`;
165
+ let fileHandle, tempFileHandle;
166
+ try {
167
+ fileHandle = await open(filePath, "r");
168
+ tempFileHandle = await open(tempFilePath, "w");
169
+ const rl = doesSupportReadLines()
170
+ ? fileHandle.readLines()
171
+ : createInterface({
172
+ input: fileHandle.createReadStream(),
173
+ crlfDelay: Infinity,
174
+ }), writeStream = tempFileHandle.createWriteStream();
175
+ if (typeof replacements === "object" && !Array.isArray(replacements)) {
176
+ let lineCount = 0;
177
+ for await (const line of rl) {
178
+ lineCount++;
179
+ writeStream.write((lineCount in replacements
180
+ ? encode(replacements[lineCount], secretKey)
181
+ : line) + "\n");
182
+ }
183
+ const newLinesNumber = Object.keys(replacements)
184
+ .map(Number)
185
+ .filter((num) => num > lineCount);
186
+ if (newLinesNumber.length) {
187
+ if (Math.min(...newLinesNumber) - lineCount - 1 > 1)
188
+ writeStream.write("\n".repeat(Math.min(...newLinesNumber) - lineCount - 1));
189
+ for (var i = 0, n = newLinesNumber.length; i < n; ++i)
190
+ writeStream.write(encode(replacements[i], secretKey) + "\n");
191
+ }
192
+ }
193
+ else
194
+ for await (const _line of rl)
195
+ writeStream.write(encode(replacements, secretKey) + "\n");
196
+ writeStream.end(async () => await rename(tempFilePath, filePath)); // Rename the temp file to the original file name
197
+ }
198
+ finally {
199
+ await fileHandle?.close();
200
+ await tempFileHandle?.close();
201
+ }
202
+ }
203
+ else if (typeof replacements === "object" && !Array.isArray(replacements)) {
204
+ await writeFile(filePath, Object.keys(replacements)
205
+ .map(Number)
206
+ .sort((a, b) => a - b)
207
+ .map((num) => replacements[num])
208
+ .join("\n") + "\n");
209
+ }
210
+ };
211
+ export const remove = async (filePath, linesToDelete) => {
212
+ let lineCount = 0;
213
+ const tempFilePath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`, linesToDeleteArray = [
214
+ ...(Array.isArray(linesToDelete) ? linesToDelete : [linesToDelete]),
215
+ ];
216
+ let fileHandle, tempFileHandle;
217
+ try {
218
+ fileHandle = await open(filePath, "r");
219
+ tempFileHandle = await open(tempFilePath, "w");
220
+ const rl = doesSupportReadLines()
221
+ ? fileHandle.readLines()
222
+ : createInterface({
223
+ input: fileHandle.createReadStream(),
224
+ crlfDelay: Infinity,
225
+ }), writeStream = tempFileHandle.createWriteStream();
226
+ for await (const line of rl) {
227
+ lineCount++;
228
+ if (!linesToDeleteArray.includes(lineCount)) {
229
+ writeStream.write(`${line}\n`);
230
+ }
231
+ }
232
+ writeStream.end(async () => await rename(tempFilePath, filePath)); // Rename the temp file to the original file name
233
+ }
234
+ finally {
235
+ await fileHandle?.close();
236
+ await tempFileHandle?.close();
237
+ }
238
+ };
239
+ export const count = async (filePath) => {
240
+ let lineCount = 0;
241
+ let fileHandle;
242
+ try {
243
+ fileHandle = await open(filePath, "r");
244
+ const rl = doesSupportReadLines()
245
+ ? fileHandle.readLines()
246
+ : createInterface({
247
+ input: fileHandle.createReadStream(),
248
+ crlfDelay: Infinity,
249
+ });
250
+ for await (const line of rl)
251
+ lineCount++;
252
+ return lineCount;
253
+ }
254
+ finally {
255
+ await fileHandle?.close();
256
+ }
257
+ };
258
+ export const search = async (filePath, operator, comparedAtValue, logicalOperator, fieldType, fieldChildrenType, limit, offset, readWholeFile, secretKey) => {
259
+ const handleComparisonOperator = (operator, originalValue, comparedAtValue, fieldType, fieldChildrenType) => {
260
+ if (Array.isArray(fieldType))
261
+ fieldType = detectFieldType(String(originalValue), fieldType);
262
+ if (Array.isArray(comparedAtValue) && !["[]", "![]"].includes(operator))
263
+ return comparedAtValue.some((comparedAtValueSingle) => handleComparisonOperator(operator, originalValue, comparedAtValueSingle, fieldType));
264
+ // check if not array or object // it can't be array or object!
265
+ switch (operator) {
266
+ case "=":
267
+ switch (fieldType) {
268
+ case "password":
269
+ return typeof originalValue === "string" &&
270
+ typeof comparedAtValue === "string"
271
+ ? comparePassword(originalValue, comparedAtValue)
272
+ : false;
273
+ case "boolean":
274
+ return Number(originalValue) - Number(comparedAtValue) === 0;
275
+ default:
276
+ return originalValue === comparedAtValue;
277
+ }
278
+ case "!=":
279
+ return !handleComparisonOperator("=", originalValue, comparedAtValue, fieldType);
280
+ case ">":
281
+ return originalValue > comparedAtValue;
282
+ case "<":
283
+ return originalValue < comparedAtValue;
284
+ case ">=":
285
+ return originalValue >= comparedAtValue;
286
+ case "<=":
287
+ return originalValue <= comparedAtValue;
288
+ case "[]":
289
+ return ((Array.isArray(originalValue) &&
290
+ Array.isArray(comparedAtValue) &&
291
+ originalValue.some(comparedAtValue.includes)) ||
292
+ (Array.isArray(originalValue) &&
293
+ !Array.isArray(comparedAtValue) &&
294
+ originalValue.includes(comparedAtValue)) ||
295
+ (!Array.isArray(originalValue) &&
296
+ Array.isArray(comparedAtValue) &&
297
+ comparedAtValue.includes(originalValue)));
298
+ case "![]":
299
+ return !handleComparisonOperator("[]", originalValue, comparedAtValue, fieldType);
300
+ case "*":
301
+ return new RegExp(`^${(String(comparedAtValue).includes("%")
302
+ ? String(comparedAtValue)
303
+ : "%" + String(comparedAtValue) + "%").replace(/%/g, ".*")}$`, "i").test(String(originalValue));
304
+ case "!*":
305
+ return !handleComparisonOperator("*", originalValue, comparedAtValue, fieldType);
306
+ default:
307
+ throw new Error(operator);
308
+ }
309
+ };
310
+ let RETURN = {}, lineCount = 0, foundItems = 0;
311
+ let fileHandle;
312
+ try {
313
+ fileHandle = await open(filePath, "r");
314
+ const rl = doesSupportReadLines()
315
+ ? fileHandle.readLines()
316
+ : createInterface({
317
+ input: fileHandle.createReadStream(),
318
+ crlfDelay: Infinity,
319
+ });
320
+ const columnName = parse(filePath).name;
321
+ for await (const line of rl) {
322
+ lineCount++;
323
+ const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
324
+ if ((Array.isArray(operator) &&
325
+ Array.isArray(comparedAtValue) &&
326
+ ((logicalOperator &&
327
+ logicalOperator === "or" &&
328
+ operator.some((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType))) ||
329
+ operator.every((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType)))) ||
330
+ (!Array.isArray(operator) &&
331
+ handleComparisonOperator(operator, decodedLine, comparedAtValue, fieldType))) {
332
+ foundItems++;
333
+ if (offset && foundItems < offset)
334
+ continue;
335
+ if (limit && foundItems > limit)
336
+ if (readWholeFile)
337
+ continue;
338
+ else
339
+ break;
340
+ if (!RETURN[lineCount])
341
+ RETURN[lineCount] = {};
342
+ RETURN[lineCount][columnName] = decodedLine;
343
+ }
344
+ }
345
+ if (foundItems) {
346
+ return [RETURN, readWholeFile ? foundItems : foundItems - 1];
347
+ }
348
+ else
349
+ return [null, 0];
350
+ }
351
+ finally {
352
+ await fileHandle?.close();
353
+ }
354
+ };
355
+ export const sum = async (filePath, lineNumbers) => {
356
+ let fileHandle;
357
+ try {
358
+ fileHandle = await open(filePath, "r");
359
+ const rl = doesSupportReadLines()
360
+ ? fileHandle.readLines()
361
+ : createInterface({
362
+ input: fileHandle.createReadStream(),
363
+ crlfDelay: Infinity,
364
+ });
365
+ let sum = 0;
366
+ if (lineNumbers) {
367
+ let lineCount = 0;
368
+ let lineNumbersArray = [
369
+ ...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
370
+ ];
371
+ for await (const line of rl) {
372
+ lineCount++;
373
+ if (!lineNumbersArray.includes(lineCount))
374
+ continue;
375
+ sum += +decode(line, "number");
376
+ lineNumbersArray[lineNumbersArray.indexOf(lineCount)] = 0;
377
+ if (!lineNumbersArray.filter((lineN) => lineN !== 0).length)
378
+ break;
379
+ }
380
+ }
381
+ else
382
+ for await (const line of rl)
383
+ sum += +decode(line, "number");
384
+ return sum;
385
+ }
386
+ finally {
387
+ await fileHandle?.close();
388
+ }
389
+ };
390
+ export const max = async (filePath, lineNumbers) => {
391
+ let fileHandle;
392
+ try {
393
+ fileHandle = await open(filePath, "r");
394
+ const rl = doesSupportReadLines()
395
+ ? fileHandle.readLines()
396
+ : createInterface({
397
+ input: fileHandle.createReadStream(),
398
+ crlfDelay: Infinity,
399
+ });
400
+ let max = 0;
401
+ if (lineNumbers) {
402
+ let lineCount = 0;
403
+ let lineNumbersArray = [
404
+ ...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
405
+ ];
406
+ for await (const line of rl) {
407
+ lineCount++;
408
+ if (!lineNumbersArray.includes(lineCount))
409
+ continue;
410
+ const lineContentNum = +decode(line, "number");
411
+ if (lineContentNum > max)
412
+ max = lineContentNum;
413
+ lineNumbersArray[lineNumbersArray.indexOf(lineCount)] = 0;
414
+ if (!lineNumbersArray.filter((lineN) => lineN !== 0).length)
415
+ break;
416
+ }
417
+ }
418
+ else
419
+ for await (const line of rl) {
420
+ const lineContentNum = +decode(line, "number");
421
+ if (lineContentNum > max)
422
+ max = lineContentNum;
423
+ }
424
+ return max;
425
+ }
426
+ finally {
427
+ await fileHandle?.close();
428
+ }
429
+ };
430
+ export const min = async (filePath, lineNumbers) => {
431
+ let fileHandle;
432
+ try {
433
+ fileHandle = await open(filePath, "r");
434
+ const rl = doesSupportReadLines()
435
+ ? fileHandle.readLines()
436
+ : createInterface({
437
+ input: fileHandle.createReadStream(),
438
+ crlfDelay: Infinity,
439
+ });
440
+ let min = 0;
441
+ if (lineNumbers) {
442
+ let lineCount = 0;
443
+ let lineNumbersArray = [
444
+ ...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
445
+ ];
446
+ for await (const line of rl) {
447
+ lineCount++;
448
+ if (!lineNumbersArray.includes(lineCount))
449
+ continue;
450
+ const lineContentNum = +decode(line, "number");
451
+ if (lineContentNum < min)
452
+ min = lineContentNum;
453
+ lineNumbersArray[lineNumbersArray.indexOf(lineCount)] = 0;
454
+ if (!lineNumbersArray.filter((lineN) => lineN !== 0).length)
455
+ break;
456
+ }
457
+ }
458
+ else
459
+ for await (const line of rl) {
460
+ const lineContentNum = +decode(line, "number");
461
+ if (lineContentNum < min)
462
+ min = lineContentNum;
463
+ }
464
+ return min;
465
+ }
466
+ finally {
467
+ await fileHandle?.close();
468
+ }
469
+ };
470
+ export const sort = async (filePath, sortDirection, lineNumbers, _lineNumbersPerChunk = 100000) => {
471
+ let fileHandle;
472
+ try {
473
+ fileHandle = await open(filePath, "r");
474
+ const rl = doesSupportReadLines()
475
+ ? fileHandle.readLines()
476
+ : createInterface({
477
+ input: fileHandle.createReadStream(),
478
+ crlfDelay: Infinity,
479
+ });
480
+ let lineCount = 0;
481
+ for await (const line of rl) {
482
+ lineCount++;
483
+ }
484
+ }
485
+ finally {
486
+ await fileHandle?.close();
487
+ }
488
+ };
489
+ export default class File {
490
+ static get = get;
491
+ static remove = remove;
492
+ static search = search;
493
+ static replace = replace;
494
+ static count = count;
495
+ static encode = encode;
496
+ static decode = decode;
497
+ static isExists = isExists;
498
+ static sum = sum;
499
+ static min = min;
500
+ static max = max;
501
+ }
@@ -0,0 +1,88 @@
1
+ /// <reference types="node" />
2
+ export interface Data {
3
+ id?: number | string;
4
+ [key: string]: any;
5
+ createdAt?: Date;
6
+ updatedAt?: Date;
7
+ }
8
+ export type FieldType = "string" | "number" | "boolean" | "date" | "email" | "url" | "table" | "object" | "array" | "password" | "html" | "ip" | "id";
9
+ type FieldDefault = {
10
+ id?: string | number | null | undefined;
11
+ key: string;
12
+ required?: boolean;
13
+ children?: any;
14
+ };
15
+ type FieldStringType = {
16
+ type: Exclude<FieldType, "array" | "object">;
17
+ };
18
+ type FieldStringArrayType = {
19
+ type: Exclude<FieldType, "array" | "object">[];
20
+ };
21
+ type FieldArrayType = {
22
+ type: "array";
23
+ children: FieldType | FieldType[] | Schema;
24
+ };
25
+ type FieldArrayArrayType = {
26
+ type: ["array", ...FieldType[]];
27
+ children: FieldType | FieldType[];
28
+ };
29
+ type FieldObjectType = {
30
+ type: "object";
31
+ children: Schema;
32
+ };
33
+ export type Field = FieldDefault & (FieldStringType | FieldStringArrayType | FieldObjectType | FieldArrayType | FieldArrayArrayType);
34
+ export type Schema = Field[];
35
+ export interface Options {
36
+ page?: number;
37
+ per_page?: number;
38
+ columns?: string[] | string;
39
+ order?: Record<string, "asc" | "desc">;
40
+ }
41
+ export type ComparisonOperator = "=" | "!=" | ">" | "<" | ">=" | "<=" | "*" | "!*" | "[]" | "![]";
42
+ type pageInfo = {
43
+ total?: number;
44
+ total_pages?: number;
45
+ } & Options;
46
+ export type Criteria = ({
47
+ [logic in "and" | "or"]?: Criteria | (string | number | boolean | null)[];
48
+ } & {
49
+ [key: string]: string | number | boolean | Criteria;
50
+ }) | null;
51
+ declare global {
52
+ type Entries<T> = {
53
+ [K in keyof T]: [K, T[K]];
54
+ }[keyof T][];
55
+ interface ObjectConstructor {
56
+ entries<T extends object>(o: T): Entries<T>;
57
+ }
58
+ }
59
+ export default class Inibase {
60
+ folder: string;
61
+ database: string;
62
+ table: string;
63
+ pageInfo: pageInfo;
64
+ private cache;
65
+ private totalItems;
66
+ salt: Buffer;
67
+ constructor(database: string, mainFolder?: string);
68
+ private throwError;
69
+ setTableSchema(tableName: string, schema: Schema): Promise<void>;
70
+ getTableSchema(tableName: string): Promise<Schema | undefined>;
71
+ getField<Property extends keyof Field | "children">(keyPath: string, schema: Schema | Field, property?: Property): any;
72
+ validateData(data: Data | Data[], schema: Schema, skipRequiredField?: boolean): void;
73
+ formatData<dataType extends Data | Data[]>(data: dataType, schema: Schema, formatOnlyAvailiableKeys?: boolean): dataType extends Data ? Data : Data[];
74
+ private getDefaultValue;
75
+ private joinPathesContentsReplacement;
76
+ joinPathesContents(mainPath: string, data: Data | Data[], startWith?: number): {
77
+ [key: string]: string[];
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>;
80
+ post<DataType extends Data | Data[]>(tableName: string, data: DataType, options?: Options, returnPostedData?: boolean): Promise<DataType extends Data ? Data | null | void : Data[] | null | void>;
81
+ 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
+ delete(tableName: string, where?: number | string | (number | string)[] | Criteria, _id?: string | string[]): Promise<string | string[] | null>;
83
+ sum(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
84
+ sum(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
85
+ max(tableName: string, columns: string | string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
86
+ min(tableName: string, columns: string | string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
87
+ }
88
+ export {};