inibase 1.0.0-rc.23 → 1.0.0-rc.25

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import { ComparisonOperator, FieldType } from "./index.js";
3
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;
4
+ export declare const encode: (input: string | number | boolean | null | (string | number | boolean | null)[], secretKey?: string | Buffer) => string | number | boolean | null;
5
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
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,
7
+ Record<number, string | number | boolean | null | (string | number | boolean | (string | number | boolean)[] | null)[]> | null,
8
8
  number
9
9
  ]>;
10
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)[]> | Map<number, string | number | boolean | (string | number | boolean)[]>) => Promise<void>;
@@ -20,16 +20,16 @@ export declare const max: (filePath: string, lineNumbers?: number | number[]) =>
20
20
  export declare const min: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
21
21
  export declare const sort: (filePath: string, sortDirection: 1 | -1 | "asc" | "desc", lineNumbers?: number | number[], _lineNumbersPerChunk?: number) => Promise<void>;
22
22
  export default class File {
23
- 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 get: (filePath: string, lineNumbers?: number | number[] | undefined, fieldType?: FieldType | FieldType[] | undefined, fieldChildrenType?: FieldType | FieldType[] | undefined, secretKey?: string | Buffer | undefined) => Promise<[Record<number, string | number | boolean | (string | number | boolean | (string | number | boolean)[] | null)[] | null> | null, number]>;
24
24
  static remove: (filePath: string, linesToDelete: number | number[]) => Promise<void>;
25
- 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, string | number | boolean | (string | number | boolean)[]>, number]>;
26
- static replace: (filePath: string, replacements: string | number | boolean | (string | number | boolean)[] | Record<number, string | number | boolean | (string | number | boolean)[]> | Map<number, string | number | boolean | (string | number | boolean)[]>) => Promise<void>;
25
+ static search: (filePath: string, operator: ComparisonOperator | ComparisonOperator[], comparedAtValue: string | number | boolean | (string | number | boolean | null)[] | null, logicalOperator?: "and" | "or" | undefined, fieldType?: FieldType | FieldType[] | undefined, fieldChildrenType?: FieldType | FieldType[] | undefined, limit?: number | undefined, offset?: number | undefined, readWholeFile?: boolean | undefined, secretKey?: string | Buffer | undefined) => Promise<[Record<number, string | number | boolean | (string | number | boolean | null)[] | null> | null, number]>;
26
+ static replace: (filePath: string, replacements: string | number | boolean | (string | number | boolean | null)[] | Record<number, string | number | boolean | (string | number | boolean | null)[] | null> | Map<number, string | number | boolean | (string | number | boolean)[]> | null) => Promise<void>;
27
27
  static count: (filePath: string) => Promise<number>;
28
- static encode: (input: string | number | boolean | (string | number | boolean)[], secretKey?: string | Buffer) => string | number | boolean;
29
- static decode: (input: string | number, fieldType?: FieldType | FieldType[], fieldChildrenType?: FieldType | FieldType[], secretKey?: string | Buffer) => string | number | boolean | (string | number | boolean)[];
28
+ static encode: (input: string | number | boolean | (string | number | boolean | null)[] | null, secretKey?: string | Buffer | undefined) => string | number | boolean | null;
29
+ static decode: (input: string | number | null, fieldType?: FieldType | FieldType[] | undefined, fieldChildrenType?: FieldType | FieldType[] | undefined, secretKey?: string | Buffer | undefined) => string | number | boolean | (string | number | boolean | null)[] | null;
30
30
  static isExists: (path: string) => Promise<boolean>;
31
- static sum: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
32
- static min: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
33
- static max: (filePath: string, lineNumbers?: number | number[]) => Promise<number>;
31
+ static sum: (filePath: string, lineNumbers?: number | number[] | undefined) => Promise<number>;
32
+ static min: (filePath: string, lineNumbers?: number | number[] | undefined) => Promise<number>;
33
+ static max: (filePath: string, lineNumbers?: number | number[] | undefined) => Promise<number>;
34
34
  static append: (filePath: string, data: string | number | (string | number)[], startsAt?: number) => Promise<void>;
35
35
  }
package/dist/file.js CHANGED
@@ -1,10 +1,12 @@
1
- import { open, rename, stat, writeFile } from "node:fs/promises";
1
+ import { open, rename, stat, writeFile, appendFile, } from "node:fs/promises";
2
2
  import { createInterface } from "node:readline";
3
- import { detectFieldType, isArrayOfArrays, isNumber } from "./utils.js";
3
+ import { detectFieldType, isArrayOfArrays, isNumber, isObject, } from "./utils.js";
4
4
  import { encodeID, comparePassword } from "./utils.server.js";
5
- const doesSupportReadLines = () => {
6
- const [major, minor, patch] = process.versions.node.split(".").map(Number);
7
- return major > 18 || (major === 18 && minor >= 11);
5
+ const readLineInternface = (fileHandle) => {
6
+ return createInterface({
7
+ input: fileHandle.createReadStream(),
8
+ crlfDelay: Infinity,
9
+ });
8
10
  };
9
11
  export const isExists = async (path) => {
10
12
  try {
@@ -15,12 +17,12 @@ export const isExists = async (path) => {
15
17
  return false;
16
18
  }
17
19
  };
18
- const delimiters = [",", "|", "&", "$", "#", "@", "^", "%", ":", "!", ";"];
20
+ const delimiters = [",", "|", "&", "$", "#", "@", "^", ":", "!", ";"];
19
21
  const secureString = (input) => {
20
22
  if (["true", "false"].includes(String(input)))
21
23
  return input ? 1 : 0;
22
24
  return typeof input === "string"
23
- ? decodeURIComponent(input)
25
+ ? decodeURIComponent(input.replace(/%(?![0-9][0-9a-fA-F]+)/g, ""))
24
26
  .replaceAll("<", "&lt;")
25
27
  .replaceAll(">", "&gt;")
26
28
  .replaceAll(",", "%2C")
@@ -30,7 +32,6 @@ const secureString = (input) => {
30
32
  .replaceAll("#", "%23")
31
33
  .replaceAll("@", "%40")
32
34
  .replaceAll("^", "%5E")
33
- .replaceAll("%", "%25")
34
35
  .replaceAll(":", "%3A")
35
36
  .replaceAll("!", "%21")
36
37
  .replaceAll(";", "%3B")
@@ -61,7 +62,6 @@ const unSecureString = (input) => input
61
62
  .replaceAll("%23", "#")
62
63
  .replaceAll("%40", "@")
63
64
  .replaceAll("%5E", "^")
64
- .replaceAll("%25", "%")
65
65
  .replaceAll("%3A", ":")
66
66
  .replaceAll("%21", "!")
67
67
  .replaceAll("%3B", ";")
@@ -99,7 +99,9 @@ const decodeHelper = (value, fieldType, fieldChildrenType, secretKey) => {
99
99
  : fieldChildrenType, undefined, secretKey))
100
100
  : value;
101
101
  case "id":
102
- return isNumber(value) ? encodeID(value, secretKey) : value;
102
+ return isNumber(value) && secretKey
103
+ ? encodeID(value, secretKey)
104
+ : value;
103
105
  default:
104
106
  return value;
105
107
  }
@@ -118,169 +120,108 @@ export const decode = (input, fieldType, fieldChildrenType, secretKey) => {
118
120
  : input, fieldType, fieldChildrenType, secretKey);
119
121
  };
120
122
  export const get = async (filePath, lineNumbers, fieldType, fieldChildrenType, secretKey) => {
121
- let fileHandle;
122
- try {
123
- fileHandle = await open(filePath, "r");
124
- const rl = doesSupportReadLines()
125
- ? fileHandle.readLines()
126
- : createInterface({
127
- input: fileHandle.createReadStream(),
128
- crlfDelay: Infinity,
129
- });
130
- let lines = new Map(), lineCount = 0;
131
- if (!lineNumbers) {
132
- for await (const line of rl)
133
- lineCount++,
134
- lines.set(lineCount, decode(line, fieldType, fieldChildrenType, secretKey));
135
- }
136
- else if (lineNumbers === -1) {
137
- let lastLine;
138
- for await (const line of rl)
139
- lineCount++, (lastLine = line);
140
- if (lastLine)
141
- lines.set(lineCount, decode(lastLine, fieldType, fieldChildrenType, secretKey));
142
- }
143
- else {
144
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
145
- for await (const line of rl) {
146
- lineCount++;
147
- if (!lineNumbersArray.has(lineCount))
148
- continue;
123
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
124
+ let lines = new Map(), lineCount = 0;
125
+ if (!lineNumbers) {
126
+ for await (const line of rl)
127
+ lineCount++,
149
128
  lines.set(lineCount, decode(line, fieldType, fieldChildrenType, secretKey));
150
- lineNumbersArray.delete(lineCount);
151
- if (!lineNumbersArray.size)
152
- break;
153
- }
154
- }
155
- return [lines.size ? Object.fromEntries(lines) : null, lineCount];
156
129
  }
157
- finally {
158
- await fileHandle?.close();
130
+ else if (lineNumbers === -1) {
131
+ let lastLine = null;
132
+ for await (const line of rl)
133
+ lineCount++, (lastLine = line);
134
+ if (lastLine)
135
+ lines.set(lineCount, decode(lastLine, fieldType, fieldChildrenType, secretKey));
136
+ }
137
+ else {
138
+ let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
139
+ for await (const line of rl) {
140
+ lineCount++;
141
+ if (!lineNumbersArray.has(lineCount))
142
+ continue;
143
+ lines.set(lineCount, decode(line, fieldType, fieldChildrenType, secretKey));
144
+ lineNumbersArray.delete(lineCount);
145
+ if (!lineNumbersArray.size)
146
+ break;
147
+ }
159
148
  }
149
+ await fileHandle.close();
150
+ return [lines.size ? Object.fromEntries(lines) : null, lineCount];
160
151
  };
161
152
  export const replace = async (filePath, replacements) => {
162
153
  if (await isExists(filePath)) {
163
- const fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`;
164
- let fileHandle, fileTempHandle, lineCount = 0;
165
- try {
166
- fileHandle = await open(filePath, "r");
167
- fileTempHandle = await open(fileTempPath, "w+");
168
- const rl = doesSupportReadLines()
169
- ? fileHandle.readLines()
170
- : createInterface({
171
- input: fileHandle.createReadStream(),
172
- crlfDelay: Infinity,
173
- }), writeStream = fileTempHandle.createWriteStream();
174
- if (typeof replacements === "object" && !Array.isArray(replacements)) {
175
- if (!(replacements instanceof Map))
176
- replacements = new Map(Object.entries(replacements));
177
- for await (const line of rl) {
178
- lineCount++;
179
- writeStream.write((replacements.has(lineCount.toString())
180
- ? replacements.get(lineCount.toString())
181
- : line) + "\n");
182
- }
183
- const newLinesNumbers = new Set([...replacements.keys()].filter((num) => num > lineCount));
184
- if (newLinesNumbers.size) {
185
- if (Math.min(...newLinesNumbers) - lineCount - 1 > 1)
186
- writeStream.write("\n".repeat(Math.min(...newLinesNumbers) - lineCount - 1));
187
- for (const newLineNumber of newLinesNumbers)
188
- writeStream.write(replacements.get(newLineNumber.toString()) + "\n");
189
- }
154
+ let lineCount = 0;
155
+ const fileHandle = await open(filePath, "r"), fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`, fileTempHandle = await open(fileTempPath, "w"), rl = readLineInternface(fileHandle), writeStream = fileTempHandle.createWriteStream();
156
+ if (isObject(replacements)) {
157
+ if (!(replacements instanceof Map))
158
+ replacements = new Map(Object.entries(replacements));
159
+ for await (const line of rl) {
160
+ lineCount++;
161
+ writeStream.write((replacements.has(lineCount.toString())
162
+ ? replacements.get(lineCount.toString())
163
+ : line) + "\n");
164
+ }
165
+ const newLinesNumbers = new Set([...replacements.keys()].filter((num) => num > lineCount));
166
+ if (newLinesNumbers.size) {
167
+ if (Math.min(...newLinesNumbers) - lineCount - 1 > 1)
168
+ writeStream.write("\n".repeat(Math.min(...newLinesNumbers) - lineCount - 1));
169
+ for await (const newLineNumber of newLinesNumbers)
170
+ writeStream.write(replacements.get(newLineNumber.toString()) + "\n");
190
171
  }
191
- else
192
- for await (const _line of rl)
193
- writeStream.write(replacements + "\n");
194
- await rename(fileTempPath, filePath);
195
- }
196
- finally {
197
- await fileHandle?.close();
198
- await fileTempHandle?.close();
199
172
  }
173
+ else
174
+ for await (const _line of rl)
175
+ writeStream.write(replacements + "\n");
176
+ await fileHandle.close();
177
+ await fileTempHandle.close();
178
+ await rename(fileTempPath, filePath);
200
179
  }
201
- else if (typeof replacements === "object" && !Array.isArray(replacements)) {
180
+ else if (isObject(replacements)) {
202
181
  if (!(replacements instanceof Map))
203
- replacements = new Map(Object.entries(replacements));
182
+ replacements = new Map(Object.entries(replacements).map(([key, value]) => [Number(key), value]));
204
183
  await writeFile(filePath, (Math.min(...replacements.keys()) - 1 > 1
205
184
  ? "\n".repeat(Math.min(...replacements.keys()) - 1)
206
185
  : "") +
207
- [...new Map([...replacements].sort(([a], [b]) => a - b)).values()].join("\n") +
186
+ Array.from(new Map([...replacements.entries()].sort(([keyA], [keyB]) => keyA - keyB)).values()).join("\n") +
208
187
  "\n");
209
188
  }
210
189
  };
211
190
  export const append = async (filePath, data, startsAt = 1) => {
212
- let fileHandle;
213
- try {
214
- fileHandle = await open(filePath, "a");
215
- const doesFileExists = await isExists(filePath);
216
- const writeStream = fileHandle.createWriteStream();
217
- if (doesFileExists) {
218
- const currentNumberOfLines = await count(filePath);
219
- if (startsAt - currentNumberOfLines - 1 > 0)
220
- writeStream.write("\n".repeat(startsAt - currentNumberOfLines - 1));
221
- if (Array.isArray(data)) {
222
- for (const input of data)
223
- writeStream.write(input + "\n");
224
- }
225
- else
226
- writeStream.write(data + "\n");
227
- }
228
- else {
229
- if (startsAt - 1 > 0)
230
- writeStream.write("\n".repeat(startsAt - 1));
231
- if (Array.isArray(data)) {
232
- for (const input of data)
233
- writeStream.write(input + "\n");
234
- }
235
- else
236
- writeStream.write(data + "\n");
237
- }
238
- }
239
- finally {
240
- await fileHandle?.close();
241
- }
191
+ let currentNumberOfLines = 0;
192
+ const doesFileExists = await isExists(filePath);
193
+ if (doesFileExists)
194
+ currentNumberOfLines = await count(filePath);
195
+ await appendFile(filePath, (currentNumberOfLines > 0
196
+ ? startsAt - currentNumberOfLines - 1 > 0
197
+ ? "\n".repeat(startsAt - currentNumberOfLines - 1)
198
+ : ""
199
+ : "") +
200
+ (Array.isArray(data) ? data.join("\n") : data) +
201
+ "\n");
242
202
  };
243
203
  export const remove = async (filePath, linesToDelete) => {
244
- const fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`;
245
- let fileHandle, fileTempHandle, lineCount = 0;
246
- try {
247
- fileHandle = await open(filePath, "r");
248
- fileTempHandle = await open(fileTempPath, "w+");
249
- const linesToDeleteArray = new Set(Array.isArray(linesToDelete) ? linesToDelete : [linesToDelete]), rl = doesSupportReadLines()
250
- ? fileHandle.readLines()
251
- : createInterface({
252
- input: fileHandle.createReadStream(),
253
- crlfDelay: Infinity,
254
- }), writeStream = fileTempHandle.createWriteStream();
255
- for await (const line of rl) {
256
- lineCount++;
257
- if (!linesToDeleteArray.has(lineCount))
258
- writeStream.write(`${line}\n`);
259
- }
260
- await rename(fileTempPath, filePath);
261
- }
262
- finally {
263
- await fileTempHandle?.close();
264
- await fileHandle?.close();
204
+ let lineCount = 0;
205
+ const fileHandle = await open(filePath, "r"), fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`, fileTempHandle = await open(fileTempPath, "w"), linesToDeleteArray = new Set(Array.isArray(linesToDelete)
206
+ ? linesToDelete.map(Number)
207
+ : [Number(linesToDelete)]), rl = readLineInternface(fileHandle), writeStream = fileTempHandle.createWriteStream();
208
+ for await (const line of rl) {
209
+ lineCount++;
210
+ if (!linesToDeleteArray.has(lineCount))
211
+ writeStream.write(`${line}\n`);
265
212
  }
213
+ await rename(fileTempPath, filePath);
214
+ await fileTempHandle.close();
215
+ await fileHandle.close();
266
216
  };
267
217
  export const count = async (filePath) => {
268
- let fileHandle, lineCount = 0;
269
- try {
270
- fileHandle = await open(filePath, "r");
271
- const rl = doesSupportReadLines()
272
- ? fileHandle.readLines()
273
- : createInterface({
274
- input: fileHandle.createReadStream(),
275
- crlfDelay: Infinity,
276
- });
277
- for await (const line of rl)
278
- lineCount++;
279
- return lineCount;
280
- }
281
- finally {
282
- await fileHandle.close();
283
- }
218
+ // return Number((await exec(`wc -l < ${filePath}`)).stdout.trim());
219
+ let lineCount = 0;
220
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
221
+ for await (const line of rl)
222
+ lineCount++;
223
+ await fileHandle.close();
224
+ return lineCount;
284
225
  };
285
226
  const handleComparisonOperator = (operator, originalValue, comparedAtValue, fieldType, fieldChildrenType) => {
286
227
  if (Array.isArray(fieldType))
@@ -304,13 +245,21 @@ const handleComparisonOperator = (operator, originalValue, comparedAtValue, fiel
304
245
  case "!=":
305
246
  return !handleComparisonOperator("=", originalValue, comparedAtValue, fieldType);
306
247
  case ">":
307
- return originalValue > comparedAtValue;
248
+ return (originalValue !== null &&
249
+ comparedAtValue !== null &&
250
+ originalValue > comparedAtValue);
308
251
  case "<":
309
- return originalValue < comparedAtValue;
252
+ return (originalValue !== null &&
253
+ comparedAtValue !== null &&
254
+ originalValue < comparedAtValue);
310
255
  case ">=":
311
- return originalValue >= comparedAtValue;
256
+ return (originalValue !== null &&
257
+ comparedAtValue !== null &&
258
+ originalValue >= comparedAtValue);
312
259
  case "<=":
313
- return originalValue <= comparedAtValue;
260
+ return (originalValue !== null &&
261
+ comparedAtValue !== null &&
262
+ originalValue <= comparedAtValue);
314
263
  case "[]":
315
264
  return ((Array.isArray(originalValue) &&
316
265
  Array.isArray(comparedAtValue) &&
@@ -334,153 +283,110 @@ const handleComparisonOperator = (operator, originalValue, comparedAtValue, fiel
334
283
  }
335
284
  };
336
285
  export const search = async (filePath, operator, comparedAtValue, logicalOperator, fieldType, fieldChildrenType, limit, offset, readWholeFile, secretKey) => {
337
- let fileHandle, RETURN = new Map(), lineCount = 0, foundItems = 0;
338
- try {
339
- fileHandle = await open(filePath, "r");
340
- const rl = doesSupportReadLines()
341
- ? fileHandle.readLines()
342
- : createInterface({
343
- input: fileHandle.createReadStream(),
344
- crlfDelay: Infinity,
345
- });
346
- for await (const line of rl) {
347
- lineCount++;
348
- const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
349
- if ((Array.isArray(operator) &&
350
- Array.isArray(comparedAtValue) &&
351
- ((logicalOperator &&
352
- logicalOperator === "or" &&
353
- operator.some((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType))) ||
354
- operator.every((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType)))) ||
355
- (!Array.isArray(operator) &&
356
- handleComparisonOperator(operator, decodedLine, comparedAtValue, fieldType))) {
357
- foundItems++;
358
- if (offset && foundItems < offset)
286
+ let RETURN = new Map(), lineCount = 0, foundItems = 0;
287
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
288
+ for await (const line of rl) {
289
+ lineCount++;
290
+ const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
291
+ if ((Array.isArray(operator) &&
292
+ Array.isArray(comparedAtValue) &&
293
+ ((logicalOperator &&
294
+ logicalOperator === "or" &&
295
+ operator.some((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType))) ||
296
+ operator.every((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType)))) ||
297
+ (!Array.isArray(operator) &&
298
+ handleComparisonOperator(operator, decodedLine, comparedAtValue, fieldType))) {
299
+ foundItems++;
300
+ if (offset && foundItems < offset)
301
+ continue;
302
+ if (limit && foundItems > limit)
303
+ if (readWholeFile)
359
304
  continue;
360
- if (limit && foundItems > limit)
361
- if (readWholeFile)
362
- continue;
363
- else
364
- break;
365
- RETURN.set(lineCount, decodedLine);
366
- }
305
+ else
306
+ break;
307
+ RETURN.set(lineCount, decodedLine);
367
308
  }
368
- return foundItems
369
- ? [
370
- Object.fromEntries(RETURN),
371
- readWholeFile ? foundItems : foundItems - 1,
372
- ]
373
- : [null, 0];
374
- }
375
- finally {
376
- await fileHandle?.close();
377
309
  }
310
+ await fileHandle.close();
311
+ return foundItems
312
+ ? [Object.fromEntries(RETURN), readWholeFile ? foundItems : foundItems - 1]
313
+ : [null, 0];
378
314
  };
379
315
  export const sum = async (filePath, lineNumbers) => {
380
- let fileHandle, sum = 0;
381
- try {
382
- fileHandle = await open(filePath, "r");
383
- const rl = doesSupportReadLines()
384
- ? fileHandle.readLines()
385
- : createInterface({
386
- input: fileHandle.createReadStream(),
387
- crlfDelay: Infinity,
388
- });
389
- if (lineNumbers) {
390
- let lineCount = 0;
391
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
392
- for await (const line of rl) {
393
- lineCount++;
394
- if (!lineNumbersArray.has(lineCount))
395
- continue;
396
- sum += +decode(line, "number");
397
- lineNumbersArray.delete(lineCount);
398
- if (!lineNumbersArray.size)
399
- break;
400
- }
316
+ let sum = 0;
317
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
318
+ if (lineNumbers) {
319
+ let lineCount = 0;
320
+ let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
321
+ for await (const line of rl) {
322
+ lineCount++;
323
+ if (!lineNumbersArray.has(lineCount))
324
+ continue;
325
+ sum += +(decode(line, "number") ?? 0);
326
+ lineNumbersArray.delete(lineCount);
327
+ if (!lineNumbersArray.size)
328
+ break;
401
329
  }
402
- else
403
- for await (const line of rl)
404
- sum += +decode(line, "number");
405
- return sum;
406
- }
407
- finally {
408
- await fileHandle?.close();
409
330
  }
331
+ else
332
+ for await (const line of rl)
333
+ sum += +(decode(line, "number") ?? 0);
334
+ await fileHandle.close();
335
+ return sum;
410
336
  };
411
337
  export const max = async (filePath, lineNumbers) => {
412
- let fileHandle, max = 0;
413
- try {
414
- fileHandle = await open(filePath, "r");
415
- const rl = doesSupportReadLines()
416
- ? fileHandle.readLines()
417
- : createInterface({
418
- input: fileHandle.createReadStream(),
419
- crlfDelay: Infinity,
420
- });
421
- if (lineNumbers) {
422
- let lineCount = 0;
423
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
424
- for await (const line of rl) {
425
- lineCount++;
426
- if (!lineNumbersArray.has(lineCount))
427
- continue;
428
- const lineContentNum = +decode(line, "number");
429
- if (lineContentNum > max)
430
- max = lineContentNum;
431
- lineNumbersArray.delete(lineCount);
432
- if (!lineNumbersArray.size)
433
- break;
434
- }
338
+ let max = 0;
339
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
340
+ if (lineNumbers) {
341
+ let lineCount = 0;
342
+ let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
343
+ for await (const line of rl) {
344
+ lineCount++;
345
+ if (!lineNumbersArray.has(lineCount))
346
+ continue;
347
+ const lineContentNum = +(decode(line, "number") ?? 0);
348
+ if (lineContentNum > max)
349
+ max = lineContentNum;
350
+ lineNumbersArray.delete(lineCount);
351
+ if (!lineNumbersArray.size)
352
+ break;
435
353
  }
436
- else
437
- for await (const line of rl) {
438
- const lineContentNum = +decode(line, "number");
439
- if (lineContentNum > max)
440
- max = lineContentNum;
441
- }
442
- return max;
443
- }
444
- finally {
445
- await fileHandle?.close();
446
354
  }
355
+ else
356
+ for await (const line of rl) {
357
+ const lineContentNum = +(decode(line, "number") ?? 0);
358
+ if (lineContentNum > max)
359
+ max = lineContentNum;
360
+ }
361
+ await fileHandle.close();
362
+ return max;
447
363
  };
448
364
  export const min = async (filePath, lineNumbers) => {
449
- let fileHandle, min = 0;
450
- try {
451
- fileHandle = await open(filePath, "r");
452
- const rl = doesSupportReadLines()
453
- ? fileHandle.readLines()
454
- : createInterface({
455
- input: fileHandle.createReadStream(),
456
- crlfDelay: Infinity,
457
- });
458
- if (lineNumbers) {
459
- let lineCount = 0;
460
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
461
- for await (const line of rl) {
462
- lineCount++;
463
- if (!lineNumbersArray.has(lineCount))
464
- continue;
465
- const lineContentNum = +decode(line, "number");
466
- if (lineContentNum < min)
467
- min = lineContentNum;
468
- lineNumbersArray.delete(lineCount);
469
- if (!lineNumbersArray.size)
470
- break;
471
- }
365
+ let min = 0;
366
+ const fileHandle = await open(filePath, "r"), rl = readLineInternface(fileHandle);
367
+ if (lineNumbers) {
368
+ let lineCount = 0;
369
+ let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
370
+ for await (const line of rl) {
371
+ lineCount++;
372
+ if (!lineNumbersArray.has(lineCount))
373
+ continue;
374
+ const lineContentNum = +(decode(line, "number") ?? 0);
375
+ if (lineContentNum < min)
376
+ min = lineContentNum;
377
+ lineNumbersArray.delete(lineCount);
378
+ if (!lineNumbersArray.size)
379
+ break;
472
380
  }
473
- else
474
- for await (const line of rl) {
475
- const lineContentNum = +decode(line, "number");
476
- if (lineContentNum < min)
477
- min = lineContentNum;
478
- }
479
- return min;
480
- }
481
- finally {
482
- await fileHandle?.close();
483
381
  }
382
+ else
383
+ for await (const line of rl) {
384
+ const lineContentNum = +(decode(line, "number") ?? 0);
385
+ if (lineContentNum < min)
386
+ min = lineContentNum;
387
+ }
388
+ await fileHandle.close();
389
+ return min;
484
390
  };
485
391
  export const sort = async (filePath, sortDirection, lineNumbers, _lineNumbersPerChunk = 100000) => { };
486
392
  export default class File {