inibase 1.0.0-rc.4 → 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 +15 -5
- package/file.ts +225 -75
- package/index.test.ts +248 -0
- package/index.ts +594 -333
- package/package.json +3 -2
- package/tsconfig.json +2 -1
- package/utils.ts +99 -44
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
|
|
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
|
+
});
|
|
133
262
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
for await (const line of file.readLines()) lineCount++;
|
|
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,77 +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
317
|
switch (fieldType) {
|
|
187
318
|
case "password":
|
|
188
|
-
return typeof
|
|
319
|
+
return typeof originalValue === "string" &&
|
|
189
320
|
typeof comparedAtValue === "string"
|
|
190
|
-
? Utils.comparePassword(
|
|
321
|
+
? Utils.comparePassword(originalValue, comparedAtValue)
|
|
191
322
|
: false;
|
|
192
323
|
case "boolean":
|
|
193
|
-
return Number(
|
|
324
|
+
return Number(originalValue) - Number(comparedAtValue) === 0;
|
|
194
325
|
default:
|
|
195
|
-
return
|
|
326
|
+
return Array.isArray(comparedAtValue)
|
|
327
|
+
? comparedAtValue.some((value) => originalValue === value)
|
|
328
|
+
: originalValue === comparedAtValue;
|
|
196
329
|
}
|
|
197
330
|
case "!=":
|
|
198
331
|
return !handleComparisonOperator(
|
|
199
332
|
"=",
|
|
200
|
-
|
|
333
|
+
originalValue,
|
|
201
334
|
comparedAtValue,
|
|
202
335
|
fieldType
|
|
203
336
|
);
|
|
204
337
|
case ">":
|
|
205
|
-
return (
|
|
206
|
-
|
|
207
|
-
|
|
338
|
+
return Array.isArray(comparedAtValue)
|
|
339
|
+
? comparedAtValue.some((value) => originalValue > value)
|
|
340
|
+
: originalValue > comparedAtValue;
|
|
208
341
|
case "<":
|
|
209
|
-
return (
|
|
210
|
-
|
|
211
|
-
|
|
342
|
+
return Array.isArray(comparedAtValue)
|
|
343
|
+
? comparedAtValue.some((value) => originalValue < value)
|
|
344
|
+
: originalValue < comparedAtValue;
|
|
212
345
|
case ">=":
|
|
213
|
-
return (
|
|
214
|
-
|
|
215
|
-
|
|
346
|
+
return Array.isArray(comparedAtValue)
|
|
347
|
+
? comparedAtValue.some((value) => originalValue >= value)
|
|
348
|
+
: originalValue >= comparedAtValue;
|
|
216
349
|
case "<=":
|
|
217
|
-
return (
|
|
218
|
-
|
|
219
|
-
|
|
350
|
+
return Array.isArray(comparedAtValue)
|
|
351
|
+
? comparedAtValue.some((value) => originalValue <= value)
|
|
352
|
+
: originalValue <= comparedAtValue;
|
|
220
353
|
case "[]":
|
|
221
354
|
return (
|
|
222
|
-
(Array.isArray(
|
|
355
|
+
(Array.isArray(originalValue) &&
|
|
223
356
|
Array.isArray(comparedAtValue) &&
|
|
224
|
-
|
|
225
|
-
(Array.isArray(
|
|
357
|
+
originalValue.some(comparedAtValue.includes)) ||
|
|
358
|
+
(Array.isArray(originalValue) &&
|
|
226
359
|
!Array.isArray(comparedAtValue) &&
|
|
227
|
-
|
|
228
|
-
(!Array.isArray(
|
|
360
|
+
originalValue.includes(comparedAtValue)) ||
|
|
361
|
+
(!Array.isArray(originalValue) &&
|
|
229
362
|
Array.isArray(comparedAtValue) &&
|
|
230
|
-
comparedAtValue.includes(
|
|
363
|
+
comparedAtValue.includes(originalValue))
|
|
231
364
|
);
|
|
232
365
|
case "![]":
|
|
233
366
|
return !handleComparisonOperator(
|
|
234
367
|
"[]",
|
|
235
|
-
|
|
368
|
+
originalValue,
|
|
236
369
|
comparedAtValue,
|
|
237
370
|
fieldType
|
|
238
371
|
);
|
|
239
372
|
case "*":
|
|
240
|
-
return (
|
|
241
|
-
value
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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));
|
|
248
390
|
case "!*":
|
|
249
391
|
return !handleComparisonOperator(
|
|
250
392
|
"*",
|
|
251
|
-
|
|
393
|
+
originalValue,
|
|
252
394
|
comparedAtValue,
|
|
253
395
|
fieldType
|
|
254
396
|
);
|
|
@@ -266,13 +408,19 @@ export const search = async (
|
|
|
266
408
|
> = {},
|
|
267
409
|
lineCount = 0,
|
|
268
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
|
+
});
|
|
269
418
|
|
|
270
|
-
const
|
|
271
|
-
columnName = decodeFileName(parse(filePath).name);
|
|
419
|
+
const columnName = decodeFileName(parse(filePath).name);
|
|
272
420
|
|
|
273
|
-
for await (const line of
|
|
421
|
+
for await (const line of rl) {
|
|
274
422
|
lineCount++;
|
|
275
|
-
const decodedLine =
|
|
423
|
+
const decodedLine = decode(line, fieldType, fieldChildrenType);
|
|
276
424
|
if (
|
|
277
425
|
(Array.isArray(operator) &&
|
|
278
426
|
Array.isArray(comparedAtValue) &&
|
|
@@ -318,10 +466,12 @@ export const search = async (
|
|
|
318
466
|
|
|
319
467
|
export default class File {
|
|
320
468
|
static get = get;
|
|
321
|
-
static count = count;
|
|
322
469
|
static remove = remove;
|
|
323
470
|
static search = search;
|
|
324
471
|
static replace = replace;
|
|
472
|
+
static count = count;
|
|
473
|
+
static encode = encode;
|
|
474
|
+
static decode = decode;
|
|
325
475
|
static encodeFileName = encodeFileName;
|
|
326
476
|
static decodeFileName = decodeFileName;
|
|
327
477
|
}
|