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/README.md +16 -6
- package/file.ts +240 -85
- package/index.test.ts +248 -0
- package/index.ts +726 -436
- package/package.json +3 -2
- package/tsconfig.json +2 -1
- package/utils.ts +99 -44
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-

|
|
1
|
+
[](https://github.com/inicontent/inibase)
|
|
2
2
|
|
|
3
3
|
# Inibase :pencil:
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.org/package/inibase) [](https://www.npmjs.org/package/inibase) [](./LICENSE) [](https://github.com/inicontent/inibase/pulse) [](https://github.com/inicontent/inibase)
|
|
6
6
|
|
|
7
7
|
> File-based relational database, simple to use and can handle large data :fire:
|
|
8
8
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
```js
|
|
23
23
|
import Inibase from "inibase";
|
|
24
|
-
const db = new Inibase("
|
|
24
|
+
const db = new Inibase("database_name");
|
|
25
25
|
|
|
26
26
|
// Get all items from "user" table
|
|
27
27
|
const users = await db.get("user");
|
|
@@ -30,12 +30,12 @@ const users = await db.get("user");
|
|
|
30
30
|
const users = await db.get("user", undefined, { page: 2, per_page: 15 });
|
|
31
31
|
|
|
32
32
|
// Get only required columns to improve speed
|
|
33
|
-
const users = await
|
|
33
|
+
const users = await db.get("user", undefined, {
|
|
34
34
|
columns: ["username", "address.street", "hobbies.*.name"],
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
// Get items from "user" table where "favoriteFoods" does not includes "Pizza"
|
|
38
|
-
const users = await
|
|
38
|
+
const users = await db.get("user", { favoriteFoods: "![]Pizza" });
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
If you like Inibase, please sponsor: [GitHub Sponsors](https://github.com/sponsors/inicontent) || [Paypal](https://paypal.me/KarimAmahtil).
|
|
@@ -342,6 +342,11 @@ const users = await db.get("user", { favoriteFoods: "[]Pizza" });
|
|
|
342
342
|
// },
|
|
343
343
|
// ...
|
|
344
344
|
// ]
|
|
345
|
+
|
|
346
|
+
// Get all "user" columns except "username" & "address.street"
|
|
347
|
+
const users = await db.get("user", undefined, {
|
|
348
|
+
columns: ["!username", "!address.street"],
|
|
349
|
+
});
|
|
345
350
|
```
|
|
346
351
|
|
|
347
352
|
</details>
|
|
@@ -445,7 +450,7 @@ type Data = {
|
|
|
445
450
|
- [x] Pagination
|
|
446
451
|
- [x] Criteria
|
|
447
452
|
- [x] Columns
|
|
448
|
-
- [ ] Order
|
|
453
|
+
- [ ] Order By
|
|
449
454
|
- [x] POST
|
|
450
455
|
- [x] PUT
|
|
451
456
|
- [x] DELETE
|
|
@@ -461,6 +466,11 @@ type Data = {
|
|
|
461
466
|
- [x] Array
|
|
462
467
|
- [x] Password
|
|
463
468
|
- [ ] IP
|
|
469
|
+
- [ ] HTML
|
|
470
|
+
- [ ] Markdown
|
|
471
|
+
- [ ] TO-DO:
|
|
472
|
+
- [ ] Improve caching
|
|
473
|
+
- [ ] Commenting the code
|
|
464
474
|
- [ ] Features:
|
|
465
475
|
- [ ] Encryption
|
|
466
476
|
- [ ] Compress data
|
package/file.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createWriteStream,
|
|
3
|
+
unlinkSync,
|
|
4
|
+
renameSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
createReadStream,
|
|
7
|
+
WriteStream,
|
|
8
|
+
} from "fs";
|
|
2
9
|
import { open } from "fs/promises";
|
|
10
|
+
import { Interface, createInterface } from "readline";
|
|
3
11
|
import { parse } from "path";
|
|
4
12
|
import { ComparisonOperator, FieldType } from ".";
|
|
5
13
|
import Utils from "./utils";
|
|
6
14
|
|
|
15
|
+
const doesSupportReadLines = () => {
|
|
16
|
+
const [major, minor, patch] = process.versions.node.split(".").map(Number);
|
|
17
|
+
return major >= 18 && minor >= 11;
|
|
18
|
+
};
|
|
19
|
+
|
|
7
20
|
export const encodeFileName = (fileName: string, extension?: string) => {
|
|
8
21
|
return (
|
|
9
22
|
fileName.replaceAll("%", "%25").replaceAll("*", "%") +
|
|
@@ -15,12 +28,99 @@ export const decodeFileName = (fileName: string) => {
|
|
|
15
28
|
return fileName.replaceAll("%", "*").replaceAll("*25", "%");
|
|
16
29
|
};
|
|
17
30
|
|
|
31
|
+
export const encode = (
|
|
32
|
+
input: string | number | boolean | null | (string | number | boolean | null)[]
|
|
33
|
+
) => {
|
|
34
|
+
const secureString = (input: string | number | boolean | null) => {
|
|
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("\n", "\\n")
|
|
43
|
+
.replaceAll("\r", "\\r")
|
|
44
|
+
: input;
|
|
45
|
+
};
|
|
46
|
+
return Array.isArray(input)
|
|
47
|
+
? Utils.isArrayOfArrays(input)
|
|
48
|
+
? (input as any[])
|
|
49
|
+
.map((_input) => _input.map(secureString).join(","))
|
|
50
|
+
.join("|")
|
|
51
|
+
: input.map(secureString).join(",")
|
|
52
|
+
: secureString(input);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const decode = (
|
|
56
|
+
input: string | null | number,
|
|
57
|
+
fieldType?: FieldType | FieldType[],
|
|
58
|
+
fieldChildrenType?: FieldType | FieldType[]
|
|
59
|
+
): string | number | boolean | null | (string | number | null | boolean)[] => {
|
|
60
|
+
if (!fieldType) return null;
|
|
61
|
+
const unSecureString = (input: string) =>
|
|
62
|
+
decodeURIComponent(input)
|
|
63
|
+
.replaceAll("<", "<")
|
|
64
|
+
.replaceAll(">", ">")
|
|
65
|
+
.replaceAll("%2C", ",")
|
|
66
|
+
.replaceAll("%7C", "|")
|
|
67
|
+
.replaceAll("\\n", "\n")
|
|
68
|
+
.replaceAll("\\r", "\r") || null;
|
|
69
|
+
if (input === null || input === "") return null;
|
|
70
|
+
if (Array.isArray(fieldType))
|
|
71
|
+
fieldType = Utils.detectFieldType(String(input), fieldType);
|
|
72
|
+
const decodeHelper = (value: string | number | any[]) => {
|
|
73
|
+
if (Array.isArray(value) && fieldType !== "array")
|
|
74
|
+
return value.map(decodeHelper);
|
|
75
|
+
switch (fieldType as FieldType) {
|
|
76
|
+
case "table":
|
|
77
|
+
case "number":
|
|
78
|
+
return isNaN(Number(value)) ? null : Number(value);
|
|
79
|
+
case "boolean":
|
|
80
|
+
return typeof value === "string" ? value === "true" : Boolean(value);
|
|
81
|
+
case "array":
|
|
82
|
+
if (!Array.isArray(value)) return null;
|
|
83
|
+
if (fieldChildrenType)
|
|
84
|
+
return value.map(
|
|
85
|
+
(v) =>
|
|
86
|
+
decode(
|
|
87
|
+
v,
|
|
88
|
+
Array.isArray(fieldChildrenType)
|
|
89
|
+
? Utils.detectFieldType(v, fieldChildrenType)
|
|
90
|
+
: fieldChildrenType
|
|
91
|
+
) as string | number | boolean | null
|
|
92
|
+
);
|
|
93
|
+
else return value;
|
|
94
|
+
default:
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
return decodeHelper(
|
|
99
|
+
typeof input === "string"
|
|
100
|
+
? input.includes(",")
|
|
101
|
+
? input.includes("|")
|
|
102
|
+
? input
|
|
103
|
+
.split("|")
|
|
104
|
+
.map((_input) => _input.split(",").map(unSecureString))
|
|
105
|
+
: input.split(",").map(unSecureString)
|
|
106
|
+
: unSecureString(input)
|
|
107
|
+
: input
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
18
111
|
export const get = async (
|
|
19
112
|
filePath: string,
|
|
20
|
-
|
|
21
|
-
|
|
113
|
+
lineNumbers?: number | number[],
|
|
114
|
+
fieldType?: FieldType | FieldType[],
|
|
115
|
+
fieldChildrenType?: FieldType | FieldType[]
|
|
22
116
|
) => {
|
|
23
|
-
|
|
117
|
+
let rl: Interface;
|
|
118
|
+
if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
|
|
119
|
+
else
|
|
120
|
+
rl = createInterface({
|
|
121
|
+
input: createReadStream(filePath),
|
|
122
|
+
crlfDelay: Infinity,
|
|
123
|
+
});
|
|
24
124
|
let lines: Record<
|
|
25
125
|
number,
|
|
26
126
|
| string
|
|
@@ -32,21 +132,23 @@ export const get = async (
|
|
|
32
132
|
lineCount = 0;
|
|
33
133
|
|
|
34
134
|
if (!lineNumbers) {
|
|
35
|
-
for await (const line of
|
|
36
|
-
lineCount++,
|
|
135
|
+
for await (const line of rl)
|
|
136
|
+
lineCount++,
|
|
137
|
+
(lines[lineCount] = decode(line, fieldType, fieldChildrenType));
|
|
37
138
|
} else if (lineNumbers === -1) {
|
|
38
|
-
let lastLine;
|
|
39
|
-
for await (const line of
|
|
40
|
-
if (lastLine)
|
|
139
|
+
let lastLine: string;
|
|
140
|
+
for await (const line of rl) lineCount++, (lastLine = line);
|
|
141
|
+
if (lastLine)
|
|
142
|
+
lines = { [lineCount]: decode(lastLine, fieldType, fieldChildrenType) };
|
|
41
143
|
} else {
|
|
42
144
|
let lineNumbersArray = [
|
|
43
145
|
...(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]),
|
|
44
146
|
];
|
|
45
|
-
for await (const line of
|
|
147
|
+
for await (const line of rl) {
|
|
46
148
|
lineCount++;
|
|
47
149
|
if (!lineNumbersArray.includes(lineCount)) continue;
|
|
48
150
|
const indexOfLineCount = lineNumbersArray.indexOf(lineCount);
|
|
49
|
-
lines[lineCount] =
|
|
151
|
+
lines[lineCount] = decode(line, fieldType, fieldChildrenType);
|
|
50
152
|
lineNumbersArray[indexOfLineCount] = 0;
|
|
51
153
|
if (!lineNumbersArray.filter((lineN) => lineN !== 0).length) break;
|
|
52
154
|
}
|
|
@@ -69,33 +171,43 @@ export const replace = async (
|
|
|
69
171
|
>
|
|
70
172
|
) => {
|
|
71
173
|
if (existsSync(filePath)) {
|
|
72
|
-
|
|
174
|
+
let rl: Interface, writeStream: WriteStream;
|
|
175
|
+
if (doesSupportReadLines()) {
|
|
176
|
+
const file = await open(filePath, "w+");
|
|
177
|
+
rl = file.readLines();
|
|
73
178
|
writeStream = file.createWriteStream();
|
|
179
|
+
} else {
|
|
180
|
+
rl = createInterface({
|
|
181
|
+
input: createReadStream(filePath),
|
|
182
|
+
crlfDelay: Infinity,
|
|
183
|
+
});
|
|
184
|
+
writeStream = createWriteStream(filePath);
|
|
185
|
+
}
|
|
74
186
|
if (typeof replacements === "object" && !Array.isArray(replacements)) {
|
|
75
187
|
let lineCount = 0;
|
|
76
|
-
for await (const line of
|
|
188
|
+
for await (const line of rl) {
|
|
77
189
|
lineCount++;
|
|
78
190
|
writeStream.write(
|
|
79
|
-
(lineCount in replacements
|
|
80
|
-
|
|
81
|
-
: line) + "\n"
|
|
191
|
+
(lineCount in replacements ? encode(replacements[lineCount]) : line) +
|
|
192
|
+
"\n"
|
|
82
193
|
);
|
|
83
194
|
}
|
|
84
195
|
} else
|
|
85
|
-
for await (const _line of
|
|
86
|
-
writeStream.write(
|
|
196
|
+
for await (const _line of rl)
|
|
197
|
+
writeStream.write(encode(replacements) + "\n");
|
|
87
198
|
|
|
88
199
|
writeStream.end();
|
|
89
200
|
} else if (typeof replacements === "object" && !Array.isArray(replacements)) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
201
|
+
let writeStream: WriteStream;
|
|
202
|
+
if (doesSupportReadLines())
|
|
203
|
+
writeStream = (await open(filePath, "w")).createWriteStream();
|
|
204
|
+
else writeStream = createWriteStream(filePath);
|
|
205
|
+
const largestLinesNumbers =
|
|
206
|
+
Math.max(...Object.keys(replacements).map(Number)) + 1;
|
|
94
207
|
for (let lineCount = 1; lineCount < largestLinesNumbers; lineCount++) {
|
|
95
208
|
writeStream.write(
|
|
96
|
-
(lineCount in replacements
|
|
97
|
-
|
|
98
|
-
: "") + "\n"
|
|
209
|
+
(lineCount in replacements ? encode(replacements[lineCount]) : "") +
|
|
210
|
+
"\n"
|
|
99
211
|
);
|
|
100
212
|
}
|
|
101
213
|
writeStream.end();
|
|
@@ -111,11 +223,21 @@ export const remove = async (
|
|
|
111
223
|
const tempFilePath = `${filePath}.tmp`,
|
|
112
224
|
linesToDeleteArray = [
|
|
113
225
|
...(Array.isArray(linesToDelete) ? linesToDelete : [linesToDelete]),
|
|
114
|
-
]
|
|
115
|
-
|
|
116
|
-
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
let rl: Interface, writeStream: WriteStream;
|
|
229
|
+
if (doesSupportReadLines()) {
|
|
230
|
+
rl = (await open(filePath)).readLines();
|
|
231
|
+
writeStream = (await open(tempFilePath, "w+")).createWriteStream();
|
|
232
|
+
} else {
|
|
233
|
+
rl = createInterface({
|
|
234
|
+
input: createReadStream(filePath),
|
|
235
|
+
crlfDelay: Infinity,
|
|
236
|
+
});
|
|
237
|
+
writeStream = createWriteStream(tempFilePath);
|
|
238
|
+
}
|
|
117
239
|
|
|
118
|
-
for await (const line of
|
|
240
|
+
for await (const line of rl) {
|
|
119
241
|
lineCount++;
|
|
120
242
|
if (!linesToDeleteArray.includes(lineCount)) {
|
|
121
243
|
writeStream.write(`${line}\n`);
|
|
@@ -129,18 +251,22 @@ export const remove = async (
|
|
|
129
251
|
};
|
|
130
252
|
|
|
131
253
|
export const count = async (filePath: string): Promise<number> => {
|
|
132
|
-
let lineCount = 0
|
|
133
|
-
|
|
134
|
-
|
|
254
|
+
let lineCount = 0,
|
|
255
|
+
rl: Interface;
|
|
256
|
+
if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
|
|
257
|
+
else
|
|
258
|
+
rl = createInterface({
|
|
259
|
+
input: createReadStream(filePath),
|
|
260
|
+
crlfDelay: Infinity,
|
|
261
|
+
});
|
|
135
262
|
|
|
136
|
-
for await (const line of
|
|
263
|
+
for await (const line of rl) lineCount++;
|
|
137
264
|
|
|
138
265
|
return lineCount;
|
|
139
266
|
};
|
|
140
267
|
|
|
141
268
|
export const search = async (
|
|
142
269
|
filePath: string,
|
|
143
|
-
fieldType: FieldType,
|
|
144
270
|
operator: ComparisonOperator | ComparisonOperator[],
|
|
145
271
|
comparedAtValue:
|
|
146
272
|
| string
|
|
@@ -149,6 +275,8 @@ export const search = async (
|
|
|
149
275
|
| null
|
|
150
276
|
| (string | number | boolean | null)[],
|
|
151
277
|
logicalOperator?: "and" | "or",
|
|
278
|
+
fieldType?: FieldType | FieldType[],
|
|
279
|
+
fieldChildrenType?: FieldType | FieldType[],
|
|
152
280
|
limit?: number,
|
|
153
281
|
offset?: number,
|
|
154
282
|
readWholeFile?: boolean
|
|
@@ -166,7 +294,7 @@ export const search = async (
|
|
|
166
294
|
> => {
|
|
167
295
|
const handleComparisonOperator = (
|
|
168
296
|
operator: ComparisonOperator,
|
|
169
|
-
|
|
297
|
+
originalValue:
|
|
170
298
|
| string
|
|
171
299
|
| number
|
|
172
300
|
| boolean
|
|
@@ -178,71 +306,91 @@ export const search = async (
|
|
|
178
306
|
| boolean
|
|
179
307
|
| null
|
|
180
308
|
| (string | number | boolean | null)[],
|
|
181
|
-
fieldType
|
|
309
|
+
fieldType?: FieldType | FieldType[],
|
|
310
|
+
fieldChildrenType?: FieldType | FieldType[]
|
|
182
311
|
): boolean => {
|
|
183
|
-
|
|
312
|
+
if (Array.isArray(fieldType))
|
|
313
|
+
fieldType = Utils.detectFieldType(String(originalValue), fieldType);
|
|
314
|
+
// check if not array or object // it can't be array or object!
|
|
184
315
|
switch (operator) {
|
|
185
316
|
case "=":
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
317
|
+
switch (fieldType) {
|
|
318
|
+
case "password":
|
|
319
|
+
return typeof originalValue === "string" &&
|
|
320
|
+
typeof comparedAtValue === "string"
|
|
321
|
+
? Utils.comparePassword(originalValue, comparedAtValue)
|
|
322
|
+
: false;
|
|
323
|
+
case "boolean":
|
|
324
|
+
return Number(originalValue) - Number(comparedAtValue) === 0;
|
|
325
|
+
default:
|
|
326
|
+
return Array.isArray(comparedAtValue)
|
|
327
|
+
? comparedAtValue.some((value) => originalValue === value)
|
|
328
|
+
: originalValue === comparedAtValue;
|
|
329
|
+
}
|
|
191
330
|
case "!=":
|
|
192
331
|
return !handleComparisonOperator(
|
|
193
332
|
"=",
|
|
194
|
-
|
|
333
|
+
originalValue,
|
|
195
334
|
comparedAtValue,
|
|
196
335
|
fieldType
|
|
197
336
|
);
|
|
198
337
|
case ">":
|
|
199
|
-
return (
|
|
200
|
-
|
|
201
|
-
|
|
338
|
+
return Array.isArray(comparedAtValue)
|
|
339
|
+
? comparedAtValue.some((value) => originalValue > value)
|
|
340
|
+
: originalValue > comparedAtValue;
|
|
202
341
|
case "<":
|
|
203
|
-
return (
|
|
204
|
-
|
|
205
|
-
|
|
342
|
+
return Array.isArray(comparedAtValue)
|
|
343
|
+
? comparedAtValue.some((value) => originalValue < value)
|
|
344
|
+
: originalValue < comparedAtValue;
|
|
206
345
|
case ">=":
|
|
207
|
-
return (
|
|
208
|
-
|
|
209
|
-
|
|
346
|
+
return Array.isArray(comparedAtValue)
|
|
347
|
+
? comparedAtValue.some((value) => originalValue >= value)
|
|
348
|
+
: originalValue >= comparedAtValue;
|
|
210
349
|
case "<=":
|
|
211
|
-
return (
|
|
212
|
-
|
|
213
|
-
|
|
350
|
+
return Array.isArray(comparedAtValue)
|
|
351
|
+
? comparedAtValue.some((value) => originalValue <= value)
|
|
352
|
+
: originalValue <= comparedAtValue;
|
|
214
353
|
case "[]":
|
|
215
354
|
return (
|
|
216
|
-
(Array.isArray(
|
|
355
|
+
(Array.isArray(originalValue) &&
|
|
217
356
|
Array.isArray(comparedAtValue) &&
|
|
218
|
-
|
|
219
|
-
(Array.isArray(
|
|
357
|
+
originalValue.some(comparedAtValue.includes)) ||
|
|
358
|
+
(Array.isArray(originalValue) &&
|
|
220
359
|
!Array.isArray(comparedAtValue) &&
|
|
221
|
-
|
|
222
|
-
(!Array.isArray(
|
|
360
|
+
originalValue.includes(comparedAtValue)) ||
|
|
361
|
+
(!Array.isArray(originalValue) &&
|
|
223
362
|
Array.isArray(comparedAtValue) &&
|
|
224
|
-
comparedAtValue.includes(
|
|
363
|
+
comparedAtValue.includes(originalValue))
|
|
225
364
|
);
|
|
226
365
|
case "![]":
|
|
227
366
|
return !handleComparisonOperator(
|
|
228
367
|
"[]",
|
|
229
|
-
|
|
368
|
+
originalValue,
|
|
230
369
|
comparedAtValue,
|
|
231
370
|
fieldType
|
|
232
371
|
);
|
|
233
372
|
case "*":
|
|
234
|
-
return (
|
|
235
|
-
value
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
373
|
+
return Array.isArray(comparedAtValue)
|
|
374
|
+
? comparedAtValue.some((value) =>
|
|
375
|
+
new RegExp(
|
|
376
|
+
`^${(String(value).includes("%")
|
|
377
|
+
? String(value)
|
|
378
|
+
: "%" + String(value) + "%"
|
|
379
|
+
).replace(/%/g, ".*")}$`,
|
|
380
|
+
"i"
|
|
381
|
+
).test(String(originalValue))
|
|
382
|
+
)
|
|
383
|
+
: new RegExp(
|
|
384
|
+
`^${(String(comparedAtValue).includes("%")
|
|
385
|
+
? String(comparedAtValue)
|
|
386
|
+
: "%" + String(comparedAtValue) + "%"
|
|
387
|
+
).replace(/%/g, ".*")}$`,
|
|
388
|
+
"i"
|
|
389
|
+
).test(String(originalValue));
|
|
242
390
|
case "!*":
|
|
243
391
|
return !handleComparisonOperator(
|
|
244
392
|
"*",
|
|
245
|
-
|
|
393
|
+
originalValue,
|
|
246
394
|
comparedAtValue,
|
|
247
395
|
fieldType
|
|
248
396
|
);
|
|
@@ -260,16 +408,21 @@ export const search = async (
|
|
|
260
408
|
> = {},
|
|
261
409
|
lineCount = 0,
|
|
262
410
|
foundItems = 0;
|
|
411
|
+
let rl: Interface;
|
|
412
|
+
if (doesSupportReadLines()) rl = (await open(filePath)).readLines();
|
|
413
|
+
else
|
|
414
|
+
rl = createInterface({
|
|
415
|
+
input: createReadStream(filePath),
|
|
416
|
+
crlfDelay: Infinity,
|
|
417
|
+
});
|
|
263
418
|
|
|
264
|
-
const
|
|
265
|
-
columnName = decodeFileName(parse(filePath).name);
|
|
419
|
+
const columnName = decodeFileName(parse(filePath).name);
|
|
266
420
|
|
|
267
|
-
for await (const line of
|
|
421
|
+
for await (const line of rl) {
|
|
268
422
|
lineCount++;
|
|
269
|
-
const decodedLine =
|
|
423
|
+
const decodedLine = decode(line, fieldType, fieldChildrenType);
|
|
270
424
|
if (
|
|
271
|
-
|
|
272
|
-
((Array.isArray(operator) &&
|
|
425
|
+
(Array.isArray(operator) &&
|
|
273
426
|
Array.isArray(comparedAtValue) &&
|
|
274
427
|
((logicalOperator &&
|
|
275
428
|
logicalOperator === "or" &&
|
|
@@ -289,13 +442,13 @@ export const search = async (
|
|
|
289
442
|
fieldType
|
|
290
443
|
)
|
|
291
444
|
))) ||
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
445
|
+
(!Array.isArray(operator) &&
|
|
446
|
+
handleComparisonOperator(
|
|
447
|
+
operator,
|
|
448
|
+
decodedLine,
|
|
449
|
+
comparedAtValue,
|
|
450
|
+
fieldType
|
|
451
|
+
))
|
|
299
452
|
) {
|
|
300
453
|
foundItems++;
|
|
301
454
|
if (offset && foundItems < offset) continue;
|
|
@@ -313,10 +466,12 @@ export const search = async (
|
|
|
313
466
|
|
|
314
467
|
export default class File {
|
|
315
468
|
static get = get;
|
|
316
|
-
static count = count;
|
|
317
469
|
static remove = remove;
|
|
318
470
|
static search = search;
|
|
319
471
|
static replace = replace;
|
|
472
|
+
static count = count;
|
|
473
|
+
static encode = encode;
|
|
474
|
+
static decode = decode;
|
|
320
475
|
static encodeFileName = encodeFileName;
|
|
321
476
|
static decodeFileName = decodeFileName;
|
|
322
477
|
}
|