inibase 1.0.0-rc.20 → 1.0.0-rc.22

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 CHANGED
@@ -40,13 +40,6 @@ const users = await db.get("user", { favoriteFoods: "![]Pizza" });
40
40
 
41
41
  If you like Inibase, please sponsor: [GitHub Sponsors](https://github.com/sponsors/inicontent) || [Paypal](https://paypal.me/KarimAmahtil).
42
42
 
43
- ## Sponsors
44
-
45
- <br>
46
- <br>
47
-
48
- Become a sponsor and have your company logo here 👉 [GitHub Sponsors](https://github.com/sponsors/inicontent) || [paypal](https://paypal.me/KarimAmahtil).
49
-
50
43
  ## Install
51
44
 
52
45
  ```js
@@ -57,6 +50,15 @@ Become a sponsor and have your company logo here 👉 [GitHub Sponsors](https://
57
50
 
58
51
  To semplify the idea, each database has tables, each table has columns, each column will be stored in a seperated file. When POSTing new data, it will be appended to each columns file as new line. When GETing data, the file will be readed line-by-line so it can handle large data (without consuming a lot of resources)
59
52
 
53
+ ## Benchmark
54
+
55
+ | | 10 | 100 | 1000 |
56
+ |--------|-------|-------|-------|
57
+ | POST | 23 ms | 20 ms | 83 ms |
58
+ | GET | 12 ms | 16 ms | 45 ms |
59
+ | PUT | 6 ms | 4 ms | 11 ms |
60
+ | DELETE | 18 ms | 21 ms | 27 ms |
61
+
60
62
  ## Examples
61
63
 
62
64
  <details>
package/dist/file.js CHANGED
@@ -118,73 +118,85 @@ export const decode = (input, fieldType, fieldChildrenType, secretKey) => {
118
118
  : input, fieldType, fieldChildrenType, secretKey);
119
119
  };
120
120
  export const get = async (filePath, lineNumbers, fieldType, fieldChildrenType, secretKey) => {
121
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
122
- ? fileHandle.readLines({ autoClose: false })
123
- : createInterface({
124
- input: fileHandle.createReadStream({ autoClose: false }),
125
- crlfDelay: Infinity,
126
- });
127
- let lines = new Map(), lineCount = 0;
128
- if (!lineNumbers) {
129
- for await (const line of rl)
130
- lineCount++,
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;
131
149
  lines.set(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.set(lineCount, decode(lastLine, fieldType, fieldChildrenType, secretKey));
139
- }
140
- else {
141
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
142
- for await (const line of rl) {
143
- lineCount++;
144
- if (!lineNumbersArray.has(lineCount))
145
- continue;
146
- lines.set(lineCount, decode(line, fieldType, fieldChildrenType, secretKey));
147
- lineNumbersArray.delete(lineCount);
148
- if (!lineNumbersArray.size)
149
- break;
150
+ lineNumbersArray.delete(lineCount);
151
+ if (!lineNumbersArray.size)
152
+ break;
153
+ }
150
154
  }
155
+ return [lines.size ? Object.fromEntries(lines) : null, lineCount];
156
+ }
157
+ finally {
158
+ await fileHandle?.close();
151
159
  }
152
- await fileHandle.close();
153
- return [lines.size ? Object.fromEntries(lines) : null, lineCount];
154
160
  };
155
161
  export const replace = async (filePath, replacements) => {
156
162
  if (await isExists(filePath)) {
157
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
158
- ? fileHandle.readLines({ autoClose: false })
159
- : createInterface({
160
- input: fileHandle.createReadStream({ autoClose: false }),
161
- crlfDelay: Infinity,
162
- }), fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`, fileTempHandle = await open(fileTempPath, "w+"), writeStream = fileTempHandle.createWriteStream({ autoClose: false });
163
- if (typeof replacements === "object" && !Array.isArray(replacements)) {
164
- if (!(replacements instanceof Map))
165
- replacements = new Map(Object.entries(replacements));
166
- let lineCount = 0;
167
- for await (const line of rl) {
168
- lineCount++;
169
- writeStream.write((replacements.has(lineCount.toString())
170
- ? replacements.get(lineCount.toString())
171
- : line) + "\n");
172
- }
173
- const newLinesNumbers = new Set([...replacements.keys()].filter((num) => num > lineCount));
174
- if (newLinesNumbers.size) {
175
- if (Math.min(...newLinesNumbers) - lineCount - 1 > 1)
176
- writeStream.write("\n".repeat(Math.min(...newLinesNumbers) - lineCount - 1));
177
- for (const newLineNumber of newLinesNumbers)
178
- writeStream.write(replacements.get(newLineNumber.toString()) + "\n");
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
+ }
179
190
  }
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();
180
199
  }
181
- else
182
- for await (const _line of rl)
183
- writeStream.write(replacements + "\n");
184
- // writeStream.end(async () => await rename(fileTempPath, filePath));
185
- await fileHandle.close();
186
- await fileTempHandle.close();
187
- await rename(fileTempPath, filePath);
188
200
  }
189
201
  else if (typeof replacements === "object" && !Array.isArray(replacements)) {
190
202
  if (!(replacements instanceof Map))
@@ -197,61 +209,78 @@ export const replace = async (filePath, replacements) => {
197
209
  }
198
210
  };
199
211
  export const append = async (filePath, data, startsAt = 1) => {
200
- const doesFileExists = await isExists(filePath);
201
- const fileHandle = await open(filePath, "a"), writeStream = fileHandle.createWriteStream({ autoClose: false });
202
- if (doesFileExists) {
203
- const currentNumberOfLines = await count(filePath);
204
- if (startsAt - currentNumberOfLines - 1 > 0)
205
- writeStream.write("\n".repeat(startsAt - currentNumberOfLines - 1));
206
- if (Array.isArray(data)) {
207
- for (const input of data)
208
- writeStream.write(input + "\n");
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");
209
227
  }
210
- else
211
- writeStream.write(data + "\n");
212
- }
213
- else {
214
- if (startsAt - 1 > 0)
215
- writeStream.write("\n".repeat(startsAt - 1));
216
- if (Array.isArray(data)) {
217
- for (const input of data)
218
- writeStream.write(input + "\n");
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");
219
237
  }
220
- else
221
- writeStream.write(data + "\n");
222
238
  }
223
- await fileHandle.close();
239
+ finally {
240
+ await fileHandle?.close();
241
+ }
224
242
  };
225
243
  export const remove = async (filePath, linesToDelete) => {
226
- let lineCount = 0;
227
- const linesToDeleteArray = new Set(Array.isArray(linesToDelete) ? linesToDelete : [linesToDelete]), fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
228
- ? fileHandle.readLines({ autoClose: false })
229
- : createInterface({
230
- input: fileHandle.createReadStream({ autoClose: false }),
231
- crlfDelay: Infinity,
232
- }), fileTempPath = `${filePath.replace(".inib", "")}-${Date.now()}.tmp`, fileTempHandle = await open(fileTempPath, "w+"), writeStream = fileTempHandle.createWriteStream({ autoClose: false });
233
- for await (const line of rl) {
234
- lineCount++;
235
- if (!linesToDeleteArray.has(lineCount))
236
- writeStream.write(`${line}\n`);
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();
237
265
  }
238
- // writeStream.end(async () => await rename(fileTempPath, filePath));
239
- await fileHandle.close();
240
- await fileTempHandle.close();
241
- await rename(fileTempPath, filePath);
242
266
  };
243
267
  export const count = async (filePath) => {
244
- let lineCount = 0;
245
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
246
- ? fileHandle.readLines({ autoClose: false })
247
- : createInterface({
248
- input: fileHandle.createReadStream({ autoClose: false }),
249
- crlfDelay: Infinity,
250
- });
251
- for await (const line of rl)
252
- lineCount++;
253
- await fileHandle.close();
254
- return lineCount;
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
+ }
255
284
  };
256
285
  const handleComparisonOperator = (operator, originalValue, comparedAtValue, fieldType, fieldChildrenType) => {
257
286
  if (Array.isArray(fieldType))
@@ -305,139 +334,155 @@ const handleComparisonOperator = (operator, originalValue, comparedAtValue, fiel
305
334
  }
306
335
  };
307
336
  export const search = async (filePath, operator, comparedAtValue, logicalOperator, fieldType, fieldChildrenType, limit, offset, readWholeFile, secretKey) => {
308
- let RETURN = new Map(), lineCount = 0, foundItems = 0;
309
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
310
- ? fileHandle.readLines({ autoClose: false })
311
- : createInterface({
312
- input: fileHandle.createReadStream({ autoClose: false }),
313
- crlfDelay: Infinity,
314
- });
315
- for await (const line of rl) {
316
- lineCount++;
317
- const decodedLine = decode(line, fieldType, fieldChildrenType, secretKey);
318
- if ((Array.isArray(operator) &&
319
- Array.isArray(comparedAtValue) &&
320
- ((logicalOperator &&
321
- logicalOperator === "or" &&
322
- operator.some((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType))) ||
323
- operator.every((single_operator, index) => handleComparisonOperator(single_operator, decodedLine, comparedAtValue[index], fieldType)))) ||
324
- (!Array.isArray(operator) &&
325
- handleComparisonOperator(operator, decodedLine, comparedAtValue, fieldType))) {
326
- foundItems++;
327
- if (offset && foundItems < offset)
328
- continue;
329
- if (limit && foundItems > limit)
330
- if (readWholeFile)
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)
331
359
  continue;
332
- else
333
- break;
334
- RETURN.set(lineCount, decodedLine);
360
+ if (limit && foundItems > limit)
361
+ if (readWholeFile)
362
+ continue;
363
+ else
364
+ break;
365
+ RETURN.set(lineCount, decodedLine);
366
+ }
335
367
  }
368
+ return foundItems
369
+ ? [
370
+ Object.fromEntries(RETURN),
371
+ readWholeFile ? foundItems : foundItems - 1,
372
+ ]
373
+ : [null, 0];
374
+ }
375
+ finally {
376
+ await fileHandle?.close();
336
377
  }
337
- await fileHandle.close();
338
- return foundItems
339
- ? [Object.fromEntries(RETURN), readWholeFile ? foundItems : foundItems - 1]
340
- : [null, 0];
341
378
  };
342
379
  export const sum = async (filePath, lineNumbers) => {
343
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
344
- ? fileHandle.readLines({ autoClose: false })
345
- : createInterface({
346
- input: fileHandle.createReadStream({ autoClose: false }),
347
- crlfDelay: Infinity,
348
- });
349
- let sum = 0;
350
- if (lineNumbers) {
351
- let lineCount = 0;
352
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
353
- for await (const line of rl) {
354
- lineCount++;
355
- if (!lineNumbersArray.has(lineCount))
356
- continue;
357
- sum += +decode(line, "number");
358
- lineNumbersArray.delete(lineCount);
359
- if (!lineNumbersArray.size)
360
- break;
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
+ }
361
401
  }
402
+ else
403
+ for await (const line of rl)
404
+ sum += +decode(line, "number");
405
+ return sum;
406
+ }
407
+ finally {
408
+ await fileHandle?.close();
362
409
  }
363
- else
364
- for await (const line of rl)
365
- sum += +decode(line, "number");
366
- return sum;
367
410
  };
368
411
  export const max = async (filePath, lineNumbers) => {
369
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
370
- ? fileHandle.readLines({ autoClose: false })
371
- : createInterface({
372
- input: fileHandle.createReadStream({ autoClose: false }),
373
- crlfDelay: Infinity,
374
- });
375
- let max = 0;
376
- if (lineNumbers) {
377
- let lineCount = 0;
378
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
379
- for await (const line of rl) {
380
- lineCount++;
381
- if (!lineNumbersArray.has(lineCount))
382
- continue;
383
- const lineContentNum = +decode(line, "number");
384
- if (lineContentNum > max)
385
- max = lineContentNum;
386
- lineNumbersArray.delete(lineCount);
387
- if (!lineNumbersArray.size)
388
- break;
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
+ }
389
435
  }
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();
390
446
  }
391
- else
392
- for await (const line of rl) {
393
- const lineContentNum = +decode(line, "number");
394
- if (lineContentNum > max)
395
- max = lineContentNum;
396
- }
397
- return max;
398
447
  };
399
448
  export const min = async (filePath, lineNumbers) => {
400
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
401
- ? fileHandle.readLines({ autoClose: false })
402
- : createInterface({
403
- input: fileHandle.createReadStream({ autoClose: false }),
404
- crlfDelay: Infinity,
405
- });
406
- let min = 0;
407
- if (lineNumbers) {
408
- let lineCount = 0;
409
- let lineNumbersArray = new Set(Array.isArray(lineNumbers) ? lineNumbers : [lineNumbers]);
410
- for await (const line of rl) {
411
- lineCount++;
412
- if (!lineNumbersArray.has(lineCount))
413
- continue;
414
- const lineContentNum = +decode(line, "number");
415
- if (lineContentNum < min)
416
- min = lineContentNum;
417
- lineNumbersArray.delete(lineCount);
418
- if (!lineNumbersArray.size)
419
- break;
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
+ }
420
472
  }
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();
421
483
  }
422
- else
423
- for await (const line of rl) {
424
- const lineContentNum = +decode(line, "number");
425
- if (lineContentNum < min)
426
- min = lineContentNum;
427
- }
428
- return min;
429
- };
430
- export const sort = async (filePath, sortDirection, lineNumbers, _lineNumbersPerChunk = 100000) => {
431
- const fileHandle = await open(filePath, "r"), rl = doesSupportReadLines()
432
- ? fileHandle.readLines({ autoClose: false })
433
- : createInterface({
434
- input: fileHandle.createReadStream({ autoClose: false }),
435
- crlfDelay: Infinity,
436
- });
437
- let lineCount = 0;
438
- for await (const line of rl)
439
- lineCount++;
440
484
  };
485
+ export const sort = async (filePath, sortDirection, lineNumbers, _lineNumbersPerChunk = 100000) => { };
441
486
  export default class File {
442
487
  static get = get;
443
488
  static remove = remove;
package/dist/index.d.ts CHANGED
@@ -84,10 +84,13 @@ export default class Inibase {
84
84
  put(tableName: string, data: Data | Data[], where?: number | string | (number | string)[] | Criteria | undefined, options?: Options | undefined, returnPostedData?: false): Promise<void | null>;
85
85
  put(tableName: string, data: Data, where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnPostedData: true): Promise<Data | null>;
86
86
  put(tableName: string, data: Data[], where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnPostedData: true): Promise<Data[] | null>;
87
- delete(tableName: string, where?: number | string | (number | string)[] | Criteria, _id?: string | string[]): Promise<string | string[] | null>;
87
+ delete(tableName: string, where?: number | string, _id?: string | string[]): Promise<string | null>;
88
+ delete(tableName: string, where?: (number | string)[], _id?: string | string[]): Promise<string[] | null>;
88
89
  sum(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
89
90
  sum(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
90
- max(tableName: string, columns: string | string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
91
- min(tableName: string, columns: string | string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
91
+ max(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
92
+ max(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
93
+ min(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
94
+ min(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
92
95
  }
93
96
  export {};
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ export default class Inibase {
74
74
  return RETURN;
75
75
  }, replaceOldPathes = Utils.findChangedProperties(schemaToIdsPath(await this.getTableSchema(tableName)), schemaToIdsPath(schema));
76
76
  if (replaceOldPathes)
77
- for (const [oldPath, newPath] of Object.entries(replaceOldPathes))
77
+ for await (const [oldPath, newPath] of Object.entries(replaceOldPathes))
78
78
  if (await File.isExists(join(TablePath, oldPath)))
79
79
  await rename(join(TablePath, oldPath), join(TablePath, newPath));
80
80
  }
@@ -294,7 +294,7 @@ export default class Inibase {
294
294
  async getItemsFromSchema(tableName, schema, linesNumber, options, prefix) {
295
295
  const path = join(this.folder, this.database, tableName);
296
296
  let RETURN = {};
297
- for (const field of schema) {
297
+ for await (const field of schema) {
298
298
  if ((field.type === "array" ||
299
299
  (Array.isArray(field.type) &&
300
300
  field.type.includes("array"))) &&
@@ -382,7 +382,7 @@ export default class Inibase {
382
382
  .map((column) => column.replace(`${field.key}.`, ""));
383
383
  const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, field.type, field.children, this.salt);
384
384
  this.totalItems[tableName + "-" + field.key] = total_lines;
385
- for (const [index, item] of Object.entries(items)) {
385
+ for await (const [index, item] of Object.entries(items)) {
386
386
  if (!RETURN[index])
387
387
  RETURN[index] = {};
388
388
  RETURN[index][field.key] = item
@@ -401,7 +401,7 @@ export default class Inibase {
401
401
  }
402
402
  }
403
403
  else if (field.type === "object") {
404
- for (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, (prefix ?? "") + field.key + ".")) ?? {})) {
404
+ for await (const [index, item] of Object.entries((await this.getItemsFromSchema(tableName, field.children, linesNumber, options, (prefix ?? "") + field.key + ".")) ?? {})) {
405
405
  if (!RETURN[index])
406
406
  RETURN[index] = {};
407
407
  if (Utils.isObject(item)) {
@@ -424,7 +424,7 @@ export default class Inibase {
424
424
  .map((column) => column.replace(`${field.key}.`, ""));
425
425
  const [items, total_lines] = await File.get(join(path, (prefix ?? "") + field.key + ".inib"), linesNumber, "number", undefined, this.salt);
426
426
  this.totalItems[tableName + "-" + field.key] = total_lines;
427
- for (const [index, item] of Object.entries(items)) {
427
+ for await (const [index, item] of Object.entries(items)) {
428
428
  if (!RETURN[index])
429
429
  RETURN[index] = {};
430
430
  RETURN[index][field.key] = item
@@ -449,8 +449,7 @@ export default class Inibase {
449
449
  switch (value[0]) {
450
450
  case ">":
451
451
  case "<":
452
- case "[":
453
- return ["=", "]", "*"].includes(value[1])
452
+ return value[1] === "="
454
453
  ? [
455
454
  value.slice(0, 2),
456
455
  value.slice(2),
@@ -459,6 +458,13 @@ export default class Inibase {
459
458
  value.slice(0, 1),
460
459
  value.slice(1),
461
460
  ];
461
+ case "[":
462
+ return value[1] === "]"
463
+ ? [
464
+ value.slice(0, 2),
465
+ value.slice(2).toString().split(","),
466
+ ]
467
+ : ["[]", value.slice(1)];
462
468
  case "!":
463
469
  return ["=", "*"].includes(value[1])
464
470
  ? [
@@ -516,7 +522,7 @@ export default class Inibase {
516
522
  if (allTrue === undefined)
517
523
  allTrue = true;
518
524
  let index = -1;
519
- for (const [key, value] of Object.entries(criteria)) {
525
+ for await (const [key, value] of Object.entries(criteria)) {
520
526
  const field = this.getField(key, schema);
521
527
  index++;
522
528
  let searchOperator = undefined, searchComparedAtValue = undefined, searchLogicalOperator = undefined;
@@ -696,13 +702,13 @@ export default class Inibase {
696
702
  RETURN = data.map(({ id, updatedAt, createdAt, ...rest }) => ({
697
703
  id: ++last_id,
698
704
  ...rest,
699
- createdAt: new Date().getTime(),
705
+ createdAt: Date.now(),
700
706
  }));
701
707
  else
702
708
  RETURN = (({ id, updatedAt, createdAt, ...rest }) => ({
703
709
  id: ++last_id,
704
710
  ...rest,
705
- createdAt: new Date().getTime(),
711
+ createdAt: Date.now(),
706
712
  }))(data);
707
713
  if (!RETURN)
708
714
  throw this.throwError("NO_DATA");
@@ -743,11 +749,11 @@ export default class Inibase {
743
749
  const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), Utils.isArrayOfObjects(data)
744
750
  ? data.map((item) => ({
745
751
  ...(({ id, ...restOfData }) => restOfData)(item),
746
- updatedAt: new Date().getTime(),
752
+ updatedAt: Date.now(),
747
753
  }))
748
754
  : {
749
755
  ...(({ id, ...restOfData }) => restOfData)(data),
750
- updatedAt: new Date().getTime(),
756
+ updatedAt: Date.now(),
751
757
  });
752
758
  for await (const [path, content] of Object.entries(pathesContents))
753
759
  await File.replace(path, content);
@@ -770,9 +776,9 @@ export default class Inibase {
770
776
  const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(join(this.folder, this.database, tableName), Utils.isArrayOfObjects(data)
771
777
  ? data.map((item) => ({
772
778
  ...item,
773
- updatedAt: new Date().getTime(),
779
+ updatedAt: Date.now(),
774
780
  }))
775
- : { ...data, updatedAt: new Date().getTime() })).map(([path, content]) => [
781
+ : { ...data, updatedAt: Date.now() })).map(([path, content]) => [
776
782
  path,
777
783
  [...(Array.isArray(where) ? where : [where])].reduce((obj, lineNum, index) => ({
778
784
  ...obj,
@@ -802,11 +808,10 @@ export default class Inibase {
802
808
  if (!(await File.isExists(idFilePath)))
803
809
  throw this.throwError("NO_ITEMS", tableName);
804
810
  if (!where) {
805
- const files = await readdir(join(this.folder, this.database, tableName));
806
- if (files.length) {
807
- for (const file in files.filter((fileName) => fileName !== "schema.json"))
811
+ const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
812
+ if (files.length)
813
+ for await (const file of files)
808
814
  await unlink(join(this.folder, this.database, tableName, file));
809
- }
810
815
  return "*";
811
816
  }
812
817
  else if ((Array.isArray(where) &&
@@ -821,13 +826,13 @@ export default class Inibase {
821
826
  else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
822
827
  Utils.isNumber(where)) {
823
828
  // "where" in this case, is the line(s) number(s) and not id(s)
824
- const files = await readdir(join(this.folder, this.database, tableName));
829
+ const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
825
830
  if (files.length) {
826
831
  if (!_id)
827
832
  _id = Object.values((await File.get(join(this.folder, this.database, tableName, "id.inib"), where, "number", undefined, this.salt))[0] ?? {}).map((id) => UtilsServer.encodeID(Number(id), this.salt));
828
833
  if (!_id.length)
829
834
  throw this.throwError("NO_ITEMS", tableName);
830
- for (const file of files.filter((fileName) => fileName.endsWith(".inib")))
835
+ for await (const file of files)
831
836
  await File.remove(join(this.folder, this.database, tableName, file), where);
832
837
  return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
833
838
  }
package/dist/utils.js CHANGED
@@ -7,7 +7,7 @@ export const isObject = (obj) => obj != null &&
7
7
  export const deepMerge = (target, source) => {
8
8
  for (const key in source) {
9
9
  if (source.hasOwnProperty(key)) {
10
- if (source[key] instanceof Object && target[key] instanceof Object)
10
+ if (isObject(source[key]) && isObject(target[key]))
11
11
  target[key] = deepMerge(target[key], source[key]);
12
12
  else
13
13
  target[key] = source[key];
@@ -2,12 +2,12 @@
2
2
  import { type Schema } from "./index.js";
3
3
  export declare const hashPassword: (password: string) => string;
4
4
  export declare const comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
5
- export declare const encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
5
+ export declare const encodeID: (id: number | string, secretKeyOrSalt: string | number | Buffer) => string;
6
6
  export declare const decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
7
7
  export declare const findLastIdNumber: (schema: Schema, secretKeyOrSalt: string | number | Buffer) => number;
8
8
  export declare const addIdToSchema: (schema: Schema, oldIndex: number, secretKeyOrSalt: string | number | Buffer) => import("./index.js").Field[];
9
9
  export default class UtilsServer {
10
- static encodeID: (id: number, secretKeyOrSalt: string | number | Buffer) => string;
10
+ static encodeID: (id: string | number, secretKeyOrSalt: string | number | Buffer) => string;
11
11
  static decodeID: (input: string, secretKeyOrSalt: string | number | Buffer) => number;
12
12
  static hashPassword: (password: string) => string;
13
13
  static comparePassword: (hashedPassword: string, inputPassword: string) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inibase",
3
- "version": "1.0.0-rc.20",
3
+ "version": "1.0.0-rc.22",
4
4
  "description": "File-based Relational Database for large data",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist",