inibase 1.0.0-rc.20 → 1.0.0-rc.21
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 +13 -0
- package/dist/file.js +268 -223
- package/dist/index.d.ts +6 -3
- package/dist/index.js +17 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,19 @@ Become a sponsor and have your company logo here 👉 [GitHub Sponsors](https://
|
|
|
57
57
|
|
|
58
58
|
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
59
|
|
|
60
|
+
## Benchmark
|
|
61
|
+
```js
|
|
62
|
+
Bulk
|
|
63
|
+
┌─────────┬─────────┬─────────┐
|
|
64
|
+
│ 10 │ 100 │ 1000 │
|
|
65
|
+
┌─────────┼─────────┼─────────┼─────────┤
|
|
66
|
+
│ POST │ '23 ms' │ '20 ms' │ '83 ms' │
|
|
67
|
+
│ GET │ '12 ms' │ '16 ms' │ '45 ms' │
|
|
68
|
+
│ PUT │ '6 ms' │ '4 ms' │ '11 ms' │
|
|
69
|
+
│ DELETE │ '18 ms' │ '21 ms' │ '27 ms' │
|
|
70
|
+
└─────────┴─────────┴─────────┴─────────┘
|
|
71
|
+
```
|
|
72
|
+
|
|
60
73
|
## Examples
|
|
61
74
|
|
|
62
75
|
<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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
writeStream.write(
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
writeStream.write(
|
|
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
|
-
|
|
239
|
+
finally {
|
|
240
|
+
await fileHandle?.close();
|
|
241
|
+
}
|
|
224
242
|
};
|
|
225
243
|
export const remove = async (filePath, linesToDelete) => {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
writeStream.
|
|
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
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
((
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
|
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
|
|
91
|
-
|
|
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
|
|
@@ -516,7 +516,7 @@ export default class Inibase {
|
|
|
516
516
|
if (allTrue === undefined)
|
|
517
517
|
allTrue = true;
|
|
518
518
|
let index = -1;
|
|
519
|
-
for (const [key, value] of Object.entries(criteria)) {
|
|
519
|
+
for await (const [key, value] of Object.entries(criteria)) {
|
|
520
520
|
const field = this.getField(key, schema);
|
|
521
521
|
index++;
|
|
522
522
|
let searchOperator = undefined, searchComparedAtValue = undefined, searchLogicalOperator = undefined;
|
|
@@ -696,13 +696,13 @@ export default class Inibase {
|
|
|
696
696
|
RETURN = data.map(({ id, updatedAt, createdAt, ...rest }) => ({
|
|
697
697
|
id: ++last_id,
|
|
698
698
|
...rest,
|
|
699
|
-
createdAt:
|
|
699
|
+
createdAt: Date.now(),
|
|
700
700
|
}));
|
|
701
701
|
else
|
|
702
702
|
RETURN = (({ id, updatedAt, createdAt, ...rest }) => ({
|
|
703
703
|
id: ++last_id,
|
|
704
704
|
...rest,
|
|
705
|
-
createdAt:
|
|
705
|
+
createdAt: Date.now(),
|
|
706
706
|
}))(data);
|
|
707
707
|
if (!RETURN)
|
|
708
708
|
throw this.throwError("NO_DATA");
|
|
@@ -743,11 +743,11 @@ export default class Inibase {
|
|
|
743
743
|
const pathesContents = this.joinPathesContents(join(this.folder, this.database, tableName), Utils.isArrayOfObjects(data)
|
|
744
744
|
? data.map((item) => ({
|
|
745
745
|
...(({ id, ...restOfData }) => restOfData)(item),
|
|
746
|
-
updatedAt:
|
|
746
|
+
updatedAt: Date.now(),
|
|
747
747
|
}))
|
|
748
748
|
: {
|
|
749
749
|
...(({ id, ...restOfData }) => restOfData)(data),
|
|
750
|
-
updatedAt:
|
|
750
|
+
updatedAt: Date.now(),
|
|
751
751
|
});
|
|
752
752
|
for await (const [path, content] of Object.entries(pathesContents))
|
|
753
753
|
await File.replace(path, content);
|
|
@@ -770,9 +770,9 @@ export default class Inibase {
|
|
|
770
770
|
const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(join(this.folder, this.database, tableName), Utils.isArrayOfObjects(data)
|
|
771
771
|
? data.map((item) => ({
|
|
772
772
|
...item,
|
|
773
|
-
updatedAt:
|
|
773
|
+
updatedAt: Date.now(),
|
|
774
774
|
}))
|
|
775
|
-
: { ...data, updatedAt:
|
|
775
|
+
: { ...data, updatedAt: Date.now() })).map(([path, content]) => [
|
|
776
776
|
path,
|
|
777
777
|
[...(Array.isArray(where) ? where : [where])].reduce((obj, lineNum, index) => ({
|
|
778
778
|
...obj,
|
|
@@ -802,11 +802,10 @@ export default class Inibase {
|
|
|
802
802
|
if (!(await File.isExists(idFilePath)))
|
|
803
803
|
throw this.throwError("NO_ITEMS", tableName);
|
|
804
804
|
if (!where) {
|
|
805
|
-
const files = await readdir(join(this.folder, this.database, tableName));
|
|
806
|
-
if (files.length)
|
|
807
|
-
for (const file
|
|
805
|
+
const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
|
|
806
|
+
if (files.length)
|
|
807
|
+
for await (const file of files)
|
|
808
808
|
await unlink(join(this.folder, this.database, tableName, file));
|
|
809
|
-
}
|
|
810
809
|
return "*";
|
|
811
810
|
}
|
|
812
811
|
else if ((Array.isArray(where) &&
|
|
@@ -821,13 +820,13 @@ export default class Inibase {
|
|
|
821
820
|
else if ((Array.isArray(where) && where.every(Utils.isNumber)) ||
|
|
822
821
|
Utils.isNumber(where)) {
|
|
823
822
|
// "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));
|
|
823
|
+
const files = (await readdir(join(this.folder, this.database, tableName)))?.filter((fileName) => fileName.endsWith(".inib"));
|
|
825
824
|
if (files.length) {
|
|
826
825
|
if (!_id)
|
|
827
826
|
_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
827
|
if (!_id.length)
|
|
829
828
|
throw this.throwError("NO_ITEMS", tableName);
|
|
830
|
-
for (const file of files
|
|
829
|
+
for await (const file of files)
|
|
831
830
|
await File.remove(join(this.folder, this.database, tableName, file), where);
|
|
832
831
|
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|
|
833
832
|
}
|