inibase 1.0.0-rc.5 → 1.0.0-rc.7
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 +4 -62
- package/file.ts +114 -74
- package/index.test.ts +141 -179
- package/index.ts +295 -324
- package/package.json +2 -2
- package/utils.server.ts +79 -0
- package/utils.ts +124 -77
package/index.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "
|
|
11
|
-
import {
|
|
12
|
-
import Utils from "./utils";
|
|
2
|
+
unlink,
|
|
3
|
+
rename,
|
|
4
|
+
readFile,
|
|
5
|
+
writeFile,
|
|
6
|
+
appendFile,
|
|
7
|
+
mkdir,
|
|
8
|
+
readdir,
|
|
9
|
+
} from "node:fs/promises";
|
|
10
|
+
import { join, parse } from "node:path";
|
|
11
|
+
import { scryptSync } from "node:crypto";
|
|
13
12
|
import File from "./file";
|
|
13
|
+
import Utils from "./utils";
|
|
14
|
+
import UtilsServer from "./utils.server";
|
|
14
15
|
|
|
15
16
|
export type Data = {
|
|
16
17
|
id?: number | string;
|
|
@@ -29,11 +30,15 @@ export type FieldType =
|
|
|
29
30
|
| "table"
|
|
30
31
|
| "object"
|
|
31
32
|
| "array"
|
|
32
|
-
| "password"
|
|
33
|
+
| "password"
|
|
34
|
+
| "html"
|
|
35
|
+
| "ip"
|
|
36
|
+
| "id";
|
|
33
37
|
type FieldDefault = {
|
|
34
38
|
id?: string | number | null | undefined;
|
|
35
39
|
key: string;
|
|
36
40
|
required?: boolean;
|
|
41
|
+
children?: any;
|
|
37
42
|
};
|
|
38
43
|
type FieldStringType = {
|
|
39
44
|
type: Exclude<FieldType, "array" | "object">;
|
|
@@ -54,7 +59,7 @@ type FieldObjectType = {
|
|
|
54
59
|
children: Schema;
|
|
55
60
|
};
|
|
56
61
|
// if "type" is array, make "array" at first place, and "number" & "string" at last place of the array
|
|
57
|
-
type Field = FieldDefault &
|
|
62
|
+
export type Field = FieldDefault &
|
|
58
63
|
(
|
|
59
64
|
| FieldStringType
|
|
60
65
|
| FieldStringArrayType
|
|
@@ -84,7 +89,7 @@ export type ComparisonOperator =
|
|
|
84
89
|
| "![]";
|
|
85
90
|
|
|
86
91
|
type pageInfo = {
|
|
87
|
-
|
|
92
|
+
total?: number;
|
|
88
93
|
total_pages?: number;
|
|
89
94
|
} & Options;
|
|
90
95
|
|
|
@@ -108,18 +113,22 @@ declare global {
|
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
export default class Inibase {
|
|
116
|
+
public folder: string;
|
|
111
117
|
public database: string;
|
|
112
|
-
public
|
|
113
|
-
public cache: Map<string, string>;
|
|
114
|
-
public pageInfoArray: Record<string, Record<string, number>>;
|
|
118
|
+
public table: string;
|
|
115
119
|
public pageInfo: pageInfo;
|
|
120
|
+
private cache: Map<string, string>;
|
|
121
|
+
private totalItems: Record<string, number>;
|
|
122
|
+
private salt: Buffer;
|
|
116
123
|
|
|
117
|
-
constructor(
|
|
118
|
-
this.database =
|
|
119
|
-
this.
|
|
124
|
+
constructor(database: string, mainFolder: string = ".") {
|
|
125
|
+
this.database = database;
|
|
126
|
+
this.folder = mainFolder;
|
|
127
|
+
this.table = null;
|
|
120
128
|
this.cache = new Map<string, any>();
|
|
121
|
-
this.
|
|
129
|
+
this.totalItems = {};
|
|
122
130
|
this.pageInfo = { page: 1, per_page: 15 };
|
|
131
|
+
this.salt = scryptSync(database, "salt", 32);
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
private throwError(
|
|
@@ -168,7 +177,24 @@ export default class Inibase {
|
|
|
168
177
|
return new Error(errorMessage);
|
|
169
178
|
}
|
|
170
179
|
|
|
171
|
-
|
|
180
|
+
private findLastIdNumber(schema: Schema): number {
|
|
181
|
+
const lastField = schema[schema.length - 1];
|
|
182
|
+
if (lastField) {
|
|
183
|
+
if (
|
|
184
|
+
(lastField.type === "array" || lastField.type === "object") &&
|
|
185
|
+
Utils.isArrayOfObjects(lastField.children)
|
|
186
|
+
)
|
|
187
|
+
return this.findLastIdNumber(lastField.children as Schema);
|
|
188
|
+
else if (lastField.id && Utils.isValidID(lastField.id))
|
|
189
|
+
return UtilsServer.decodeID(lastField.id as string, this.salt);
|
|
190
|
+
}
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public async setTableSchema(
|
|
195
|
+
tableName: string,
|
|
196
|
+
schema: Schema
|
|
197
|
+
): Promise<void> {
|
|
172
198
|
const encodeSchema = (schema: Schema) => {
|
|
173
199
|
let RETURN: any[][] = [],
|
|
174
200
|
index = 0;
|
|
@@ -176,17 +202,17 @@ export default class Inibase {
|
|
|
176
202
|
if (!RETURN[index]) RETURN[index] = [];
|
|
177
203
|
RETURN[index].push(
|
|
178
204
|
field.id
|
|
179
|
-
?
|
|
205
|
+
? UtilsServer.decodeID(field.id as string, this.salt)
|
|
180
206
|
: null
|
|
181
207
|
);
|
|
182
208
|
RETURN[index].push(field.key ?? null);
|
|
183
209
|
RETURN[index].push(field.required ?? null);
|
|
184
210
|
RETURN[index].push(field.type ?? null);
|
|
185
211
|
RETURN[index].push(
|
|
186
|
-
(field
|
|
187
|
-
field.children
|
|
188
|
-
|
|
189
|
-
|
|
212
|
+
(field as any).children
|
|
213
|
+
? Utils.isArrayOfObjects((field as any).children)
|
|
214
|
+
? encodeSchema((field as any).children as Schema) ?? null
|
|
215
|
+
: (field as any).children
|
|
190
216
|
: null
|
|
191
217
|
);
|
|
192
218
|
index++;
|
|
@@ -203,44 +229,34 @@ export default class Inibase {
|
|
|
203
229
|
oldIndex++;
|
|
204
230
|
field = {
|
|
205
231
|
...field,
|
|
206
|
-
id:
|
|
232
|
+
id: UtilsServer.encodeID(oldIndex, this.salt),
|
|
207
233
|
};
|
|
208
234
|
} else
|
|
209
|
-
oldIndex =
|
|
235
|
+
oldIndex = UtilsServer.decodeID(field.id as string, this.salt);
|
|
210
236
|
field.children = addIdToSchema(field.children as Schema, oldIndex);
|
|
211
237
|
oldIndex += field.children.length;
|
|
212
238
|
} else if (field.id)
|
|
213
|
-
oldIndex =
|
|
239
|
+
oldIndex = UtilsServer.decodeID(field.id as string, this.salt);
|
|
214
240
|
else {
|
|
215
241
|
oldIndex++;
|
|
216
242
|
field = {
|
|
217
243
|
...field,
|
|
218
|
-
id:
|
|
244
|
+
id: UtilsServer.encodeID(oldIndex, this.salt),
|
|
219
245
|
};
|
|
220
246
|
}
|
|
221
247
|
return field;
|
|
222
|
-
})
|
|
223
|
-
findLastIdNumber = (schema: Schema): number => {
|
|
224
|
-
const lastField = schema[schema.length - 1];
|
|
225
|
-
if (lastField) {
|
|
226
|
-
if (
|
|
227
|
-
(lastField.type === "array" || lastField.type === "object") &&
|
|
228
|
-
Utils.isArrayOfObjects(lastField.children)
|
|
229
|
-
)
|
|
230
|
-
return findLastIdNumber(lastField.children as Schema);
|
|
231
|
-
else if (lastField.id && Utils.isValidID(lastField.id))
|
|
232
|
-
return Utils.decodeID(lastField.id as string, this.databasePath);
|
|
233
|
-
}
|
|
234
|
-
return 0;
|
|
235
|
-
};
|
|
248
|
+
});
|
|
236
249
|
|
|
237
250
|
// remove id from schema
|
|
238
|
-
schema = schema.filter(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
251
|
+
schema = schema.filter(
|
|
252
|
+
(field) => !["id", "created_at", "updated_at"].includes(field.key)
|
|
253
|
+
);
|
|
254
|
+
schema = addIdToSchema(schema, this.findLastIdNumber(schema));
|
|
255
|
+
const TablePath = join(this.folder, this.database, tableName),
|
|
256
|
+
TableSchemaPath = join(TablePath, "schema");
|
|
257
|
+
if (!(await File.isExists(TablePath)))
|
|
258
|
+
await mkdir(TablePath, { recursive: true });
|
|
259
|
+
if (await File.isExists(TableSchemaPath)) {
|
|
244
260
|
// update columns files names based on field id
|
|
245
261
|
const schemaToIdsPath = (schema: any, prefix = "") => {
|
|
246
262
|
let RETURN: any = {};
|
|
@@ -256,35 +272,35 @@ export default class Inibase {
|
|
|
256
272
|
)
|
|
257
273
|
);
|
|
258
274
|
} else if (Utils.isValidID(field.id))
|
|
259
|
-
RETURN[
|
|
275
|
+
RETURN[UtilsServer.decodeID(field.id, this.salt)] =
|
|
260
276
|
File.encodeFileName((prefix ?? "") + field.key, "inib");
|
|
261
277
|
|
|
262
278
|
return RETURN;
|
|
263
279
|
},
|
|
264
280
|
replaceOldPathes = Utils.findChangedProperties(
|
|
265
|
-
schemaToIdsPath(this.getTableSchema(tableName)),
|
|
281
|
+
schemaToIdsPath(await this.getTableSchema(tableName)),
|
|
266
282
|
schemaToIdsPath(schema)
|
|
267
283
|
);
|
|
268
284
|
if (replaceOldPathes)
|
|
269
285
|
for (const [oldPath, newPath] of Object.entries(replaceOldPathes))
|
|
270
|
-
if (
|
|
271
|
-
|
|
286
|
+
if (await File.isExists(join(TablePath, oldPath)))
|
|
287
|
+
await rename(join(TablePath, oldPath), join(TablePath, newPath));
|
|
272
288
|
}
|
|
273
289
|
|
|
274
|
-
|
|
275
|
-
join(TablePath, "schema
|
|
290
|
+
await writeFile(
|
|
291
|
+
join(TablePath, "schema"),
|
|
276
292
|
JSON.stringify(encodeSchema(schema))
|
|
277
293
|
);
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
public getTableSchema(tableName: string): Schema | undefined {
|
|
296
|
+
public async getTableSchema(tableName: string): Promise<Schema | undefined> {
|
|
281
297
|
const decodeSchema = (encodedSchema: any) => {
|
|
282
298
|
return encodedSchema.map((field: any) =>
|
|
283
299
|
Array.isArray(field[0])
|
|
284
300
|
? decodeSchema(field)
|
|
285
301
|
: Object.fromEntries(
|
|
286
302
|
Object.entries({
|
|
287
|
-
id:
|
|
303
|
+
id: UtilsServer.encodeID(field[0], this.salt),
|
|
288
304
|
key: field[1],
|
|
289
305
|
required: field[2],
|
|
290
306
|
type: field[3],
|
|
@@ -297,10 +313,12 @@ export default class Inibase {
|
|
|
297
313
|
)
|
|
298
314
|
);
|
|
299
315
|
},
|
|
300
|
-
TableSchemaPath = join(this.
|
|
301
|
-
if (!
|
|
316
|
+
TableSchemaPath = join(this.folder, this.database, tableName, "schema");
|
|
317
|
+
if (!(await File.isExists(TableSchemaPath))) return undefined;
|
|
302
318
|
if (!this.cache.has(TableSchemaPath)) {
|
|
303
|
-
const TableSchemaPathContent =
|
|
319
|
+
const TableSchemaPathContent = await readFile(TableSchemaPath, {
|
|
320
|
+
encoding: "utf8",
|
|
321
|
+
});
|
|
304
322
|
this.cache.set(
|
|
305
323
|
TableSchemaPath,
|
|
306
324
|
TableSchemaPathContent
|
|
@@ -308,14 +326,28 @@ export default class Inibase {
|
|
|
308
326
|
: ""
|
|
309
327
|
);
|
|
310
328
|
}
|
|
329
|
+
const schema = this.cache.get(TableSchemaPath) as unknown as Schema,
|
|
330
|
+
lastIdNumber = this.findLastIdNumber(schema);
|
|
311
331
|
return [
|
|
312
332
|
{
|
|
313
|
-
id:
|
|
333
|
+
id: UtilsServer.encodeID(0, this.salt),
|
|
314
334
|
key: "id",
|
|
315
|
-
type: "
|
|
335
|
+
type: "id",
|
|
316
336
|
required: true,
|
|
317
337
|
},
|
|
318
|
-
...
|
|
338
|
+
...schema,
|
|
339
|
+
{
|
|
340
|
+
id: UtilsServer.encodeID(lastIdNumber + 1, this.salt),
|
|
341
|
+
key: "created_at",
|
|
342
|
+
type: "date",
|
|
343
|
+
required: true,
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
id: UtilsServer.encodeID(lastIdNumber + 2, this.salt),
|
|
347
|
+
key: "updated_at",
|
|
348
|
+
type: "date",
|
|
349
|
+
required: false,
|
|
350
|
+
},
|
|
319
351
|
];
|
|
320
352
|
}
|
|
321
353
|
|
|
@@ -360,71 +392,6 @@ export default class Inibase {
|
|
|
360
392
|
schema: Schema,
|
|
361
393
|
skipRequiredField: boolean = false
|
|
362
394
|
): void {
|
|
363
|
-
const validateFieldType = (
|
|
364
|
-
value: any,
|
|
365
|
-
fieldType: FieldType | FieldType[],
|
|
366
|
-
fieldChildrenType?: FieldType | FieldType[]
|
|
367
|
-
): boolean => {
|
|
368
|
-
if (value === null) return true;
|
|
369
|
-
if (Array.isArray(fieldType))
|
|
370
|
-
return Utils.detectFieldType(value, fieldType) !== undefined;
|
|
371
|
-
if (fieldType === "array" && fieldChildrenType && Array.isArray(value))
|
|
372
|
-
return value.some(
|
|
373
|
-
(v) =>
|
|
374
|
-
Utils.detectFieldType(
|
|
375
|
-
v,
|
|
376
|
-
Array.isArray(fieldChildrenType)
|
|
377
|
-
? fieldChildrenType
|
|
378
|
-
: [fieldChildrenType]
|
|
379
|
-
) !== undefined
|
|
380
|
-
);
|
|
381
|
-
|
|
382
|
-
switch (fieldType) {
|
|
383
|
-
case "string":
|
|
384
|
-
// TO-DO: and not email, url, password ...
|
|
385
|
-
return !Utils.isNumber(value);
|
|
386
|
-
case "password":
|
|
387
|
-
return !Utils.isNumber(value) && Utils.isPassword(value);
|
|
388
|
-
case "number":
|
|
389
|
-
return Utils.isNumber(value);
|
|
390
|
-
case "boolean":
|
|
391
|
-
return (
|
|
392
|
-
typeof value === "boolean" || value === "true" || value === "false"
|
|
393
|
-
);
|
|
394
|
-
case "date":
|
|
395
|
-
return Utils.isDate(value);
|
|
396
|
-
case "object":
|
|
397
|
-
return Utils.isObject(value);
|
|
398
|
-
case "array":
|
|
399
|
-
return Array.isArray(value);
|
|
400
|
-
case "email":
|
|
401
|
-
return Utils.isEmail(value);
|
|
402
|
-
case "url":
|
|
403
|
-
return Utils.isURL(value);
|
|
404
|
-
case "table":
|
|
405
|
-
// feat: check if id exists
|
|
406
|
-
if (Array.isArray(value))
|
|
407
|
-
return (
|
|
408
|
-
(Utils.isArrayOfObjects(value) &&
|
|
409
|
-
value.every(
|
|
410
|
-
(element: Data) =>
|
|
411
|
-
element.hasOwnProperty("id") &&
|
|
412
|
-
(Utils.isValidID(element.id) || Utils.isNumber(element.id))
|
|
413
|
-
)) ||
|
|
414
|
-
value.every(Utils.isNumber) ||
|
|
415
|
-
Utils.isValidID(value)
|
|
416
|
-
);
|
|
417
|
-
else if (Utils.isObject(value))
|
|
418
|
-
return (
|
|
419
|
-
value.hasOwnProperty("id") &&
|
|
420
|
-
(Utils.isValidID((value as Data).id) ||
|
|
421
|
-
Utils.isNumber((value as Data).id))
|
|
422
|
-
);
|
|
423
|
-
else return Utils.isNumber(value) || Utils.isValidID(value);
|
|
424
|
-
default:
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
395
|
if (Utils.isArrayOfObjects(data))
|
|
429
396
|
for (const single_data of data as Data[])
|
|
430
397
|
this.validateData(single_data, schema, skipRequiredField);
|
|
@@ -437,7 +404,8 @@ export default class Inibase {
|
|
|
437
404
|
)
|
|
438
405
|
throw this.throwError("FIELD_REQUIRED", field.key);
|
|
439
406
|
if (
|
|
440
|
-
|
|
407
|
+
data.hasOwnProperty(field.key) &&
|
|
408
|
+
!Utils.validateFieldType(
|
|
441
409
|
data[field.key],
|
|
442
410
|
field.type,
|
|
443
411
|
(field as any)?.children &&
|
|
@@ -472,7 +440,6 @@ export default class Inibase {
|
|
|
472
440
|
): Data | Data[] | number | string => {
|
|
473
441
|
if (Array.isArray(field.type))
|
|
474
442
|
field.type = Utils.detectFieldType(value, field.type);
|
|
475
|
-
|
|
476
443
|
switch (field.type) {
|
|
477
444
|
case "array":
|
|
478
445
|
if (typeof field.children === "string") {
|
|
@@ -489,16 +456,16 @@ export default class Inibase {
|
|
|
489
456
|
value.map((item: any) =>
|
|
490
457
|
Utils.isNumber(item.id)
|
|
491
458
|
? Number(item.id)
|
|
492
|
-
:
|
|
459
|
+
: UtilsServer.decodeID(item.id, this.salt)
|
|
493
460
|
);
|
|
494
461
|
} else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
495
462
|
return value.map((item: number | string) =>
|
|
496
463
|
Utils.isNumber(item)
|
|
497
464
|
? Number(item as string)
|
|
498
|
-
:
|
|
465
|
+
: UtilsServer.decodeID(item as string, this.salt)
|
|
499
466
|
);
|
|
500
467
|
} else if (Utils.isValidID(value))
|
|
501
|
-
return [
|
|
468
|
+
return [UtilsServer.decodeID(value, this.salt)];
|
|
502
469
|
else if (Utils.isNumber(value)) return [Number(value)];
|
|
503
470
|
} else if (data.hasOwnProperty(field.key)) return value;
|
|
504
471
|
} else if (Utils.isArrayOfObjects(field.children))
|
|
@@ -526,21 +493,28 @@ export default class Inibase {
|
|
|
526
493
|
)
|
|
527
494
|
return Utils.isNumber(value.id)
|
|
528
495
|
? Number(value.id)
|
|
529
|
-
:
|
|
496
|
+
: UtilsServer.decodeID(value.id, this.salt);
|
|
530
497
|
} else if (Utils.isValidID(value) || Utils.isNumber(value))
|
|
531
498
|
return Utils.isNumber(value)
|
|
532
499
|
? Number(value)
|
|
533
|
-
:
|
|
500
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
534
501
|
break;
|
|
535
502
|
case "password":
|
|
536
|
-
return value.length === 161 ? value :
|
|
503
|
+
return value.length === 161 ? value : UtilsServer.hashPassword(value);
|
|
537
504
|
case "number":
|
|
538
505
|
return Utils.isNumber(value) ? Number(value) : null;
|
|
506
|
+
case "id":
|
|
507
|
+
return Utils.isNumber(value)
|
|
508
|
+
? value
|
|
509
|
+
: UtilsServer.decodeID(value, this.salt);
|
|
539
510
|
default:
|
|
540
511
|
return value;
|
|
541
512
|
}
|
|
542
513
|
return null;
|
|
543
514
|
};
|
|
515
|
+
|
|
516
|
+
this.validateData(data, schema, formatOnlyAvailiableKeys);
|
|
517
|
+
|
|
544
518
|
if (Utils.isArrayOfObjects(data))
|
|
545
519
|
return data.map((single_data: Data) =>
|
|
546
520
|
this.formatData(single_data, schema, formatOnlyAvailiableKeys)
|
|
@@ -549,7 +523,7 @@ export default class Inibase {
|
|
|
549
523
|
let RETURN: Data = {};
|
|
550
524
|
for (const field of schema) {
|
|
551
525
|
if (!data.hasOwnProperty(field.key)) {
|
|
552
|
-
if (formatOnlyAvailiableKeys) continue;
|
|
526
|
+
if (formatOnlyAvailiableKeys || !field.required) continue;
|
|
553
527
|
RETURN[field.key] = this.getDefaultValue(field);
|
|
554
528
|
continue;
|
|
555
529
|
}
|
|
@@ -676,16 +650,15 @@ export default class Inibase {
|
|
|
676
650
|
if (!options.columns) options.columns = [];
|
|
677
651
|
else if (!Array.isArray(options.columns))
|
|
678
652
|
options.columns = [options.columns];
|
|
679
|
-
|
|
680
|
-
options.columns.length &&
|
|
681
|
-
!(options.columns as string[]).includes("id")
|
|
682
|
-
)
|
|
653
|
+
if (options.columns.length && !(options.columns as string[]).includes("id"))
|
|
683
654
|
options.columns.push("id");
|
|
684
655
|
if (!options.page) options.page = 1;
|
|
685
656
|
if (!options.per_page) options.per_page = 15;
|
|
686
657
|
let RETURN!: Data | Data[] | null;
|
|
687
|
-
let schema = this.getTableSchema(tableName);
|
|
658
|
+
let schema = await this.getTableSchema(tableName);
|
|
688
659
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
660
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
661
|
+
if (!(await File.isExists(idFilePath))) return null;
|
|
689
662
|
const filterSchemaByColumns = (schema: Schema, columns: string[]): Schema =>
|
|
690
663
|
schema
|
|
691
664
|
.map((field) => {
|
|
@@ -699,12 +672,8 @@ export default class Inibase {
|
|
|
699
672
|
Utils.isArrayOfObjects(field.children) &&
|
|
700
673
|
columns.filter(
|
|
701
674
|
(column) =>
|
|
702
|
-
column.startsWith(
|
|
703
|
-
|
|
704
|
-
) ||
|
|
705
|
-
column.startsWith(
|
|
706
|
-
"!" + field.key + (field.type === "array" ? ".*." : ".")
|
|
707
|
-
)
|
|
675
|
+
column.startsWith(field.key + ".") ||
|
|
676
|
+
column.startsWith("!" + field.key + ".")
|
|
708
677
|
).length
|
|
709
678
|
) {
|
|
710
679
|
field.children = filterSchemaByColumns(
|
|
@@ -712,19 +681,10 @@ export default class Inibase {
|
|
|
712
681
|
columns
|
|
713
682
|
.filter(
|
|
714
683
|
(column) =>
|
|
715
|
-
column.startsWith(
|
|
716
|
-
|
|
717
|
-
) ||
|
|
718
|
-
column.startsWith(
|
|
719
|
-
"!" + field.key + (field.type === "array" ? ".*." : ".")
|
|
720
|
-
)
|
|
721
|
-
)
|
|
722
|
-
.map((column) =>
|
|
723
|
-
column.replace(
|
|
724
|
-
field.key + (field.type === "array" ? ".*." : "."),
|
|
725
|
-
""
|
|
726
|
-
)
|
|
684
|
+
column.startsWith(field.key + ".") ||
|
|
685
|
+
column.startsWith("!" + field.key + ".")
|
|
727
686
|
)
|
|
687
|
+
.map((column) => column.replace(field.key + ".", ""))
|
|
728
688
|
);
|
|
729
689
|
return field;
|
|
730
690
|
}
|
|
@@ -851,7 +811,7 @@ export default class Inibase {
|
|
|
851
811
|
if (RETURN[index][field.key])
|
|
852
812
|
Object.entries(item).forEach(([key, value], _index) => {
|
|
853
813
|
RETURN[index][field.key] = RETURN[index][field.key].map(
|
|
854
|
-
(_obj, _i) => ({ ..._obj, [key]: value[
|
|
814
|
+
(_obj, _i) => ({ ..._obj, [key]: value[_i] })
|
|
855
815
|
);
|
|
856
816
|
});
|
|
857
817
|
else if (Object.values(item).every(Utils.isArrayOfArrays))
|
|
@@ -885,70 +845,77 @@ export default class Inibase {
|
|
|
885
845
|
options.columns = (options.columns as string[])
|
|
886
846
|
.filter((column) => column.includes(`${field.key}.*.`))
|
|
887
847
|
.map((column) => column.replace(`${field.key}.*.`, ""));
|
|
888
|
-
|
|
889
|
-
(
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
848
|
+
const [items, total_lines] = await File.get(
|
|
849
|
+
join(
|
|
850
|
+
path,
|
|
851
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
852
|
+
),
|
|
853
|
+
linesNumber,
|
|
854
|
+
field.type,
|
|
855
|
+
(field as FieldDefault & (FieldArrayType | FieldArrayArrayType))
|
|
856
|
+
.children as FieldType | FieldType[],
|
|
857
|
+
this.salt
|
|
858
|
+
);
|
|
859
|
+
|
|
860
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
861
|
+
for (const [index, item] of Object.entries(items)) {
|
|
900
862
|
if (!RETURN[index]) RETURN[index] = {};
|
|
901
|
-
RETURN[index][field.key] =
|
|
902
|
-
? await this.get(field.key,
|
|
863
|
+
RETURN[index][field.key] = item
|
|
864
|
+
? await this.get(field.key, item as number, options)
|
|
903
865
|
: this.getDefaultValue(field);
|
|
904
866
|
}
|
|
905
867
|
} else if (
|
|
906
|
-
|
|
868
|
+
await File.isExists(
|
|
907
869
|
join(
|
|
908
870
|
path,
|
|
909
871
|
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
910
872
|
)
|
|
911
873
|
)
|
|
912
|
-
)
|
|
913
|
-
|
|
914
|
-
(
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
874
|
+
) {
|
|
875
|
+
const [items, total_lines] = await File.get(
|
|
876
|
+
join(
|
|
877
|
+
path,
|
|
878
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
879
|
+
),
|
|
880
|
+
linesNumber,
|
|
881
|
+
field.type,
|
|
882
|
+
(field as any)?.children,
|
|
883
|
+
this.salt
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
887
|
+
for (const [index, item] of Object.entries(items)) {
|
|
924
888
|
if (!RETURN[index]) RETURN[index] = {};
|
|
925
889
|
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
926
|
-
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
927
892
|
} else if (field.type === "object") {
|
|
928
|
-
Object.entries(
|
|
893
|
+
for (const [index, item] of Object.entries(
|
|
929
894
|
(await getItemsFromSchema(
|
|
930
895
|
path,
|
|
931
896
|
field.children as Schema,
|
|
932
897
|
linesNumber,
|
|
933
898
|
(prefix ?? "") + field.key + "."
|
|
934
899
|
)) ?? {}
|
|
935
|
-
)
|
|
900
|
+
)) {
|
|
936
901
|
if (!RETURN[index]) RETURN[index] = {};
|
|
937
902
|
if (Utils.isObject(item)) {
|
|
938
903
|
if (!Object.values(item).every((i) => i === null))
|
|
939
904
|
RETURN[index][field.key] = item;
|
|
940
905
|
else RETURN[index][field.key] = null;
|
|
941
906
|
} else RETURN[index][field.key] = null;
|
|
942
|
-
}
|
|
907
|
+
}
|
|
943
908
|
} else if (field.type === "table") {
|
|
944
909
|
if (
|
|
945
|
-
|
|
946
|
-
|
|
910
|
+
(await File.isExists(
|
|
911
|
+
join(this.folder, this.database, field.key)
|
|
912
|
+
)) &&
|
|
913
|
+
(await File.isExists(
|
|
947
914
|
join(
|
|
948
915
|
path,
|
|
949
916
|
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
950
917
|
)
|
|
951
|
-
)
|
|
918
|
+
))
|
|
952
919
|
) {
|
|
953
920
|
if (options.columns)
|
|
954
921
|
options.columns = (options.columns as string[])
|
|
@@ -958,41 +925,43 @@ export default class Inibase {
|
|
|
958
925
|
!column.includes(`${field.key}.*.`)
|
|
959
926
|
)
|
|
960
927
|
.map((column) => column.replace(`${field.key}.`, ""));
|
|
961
|
-
|
|
962
|
-
(
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
)
|
|
928
|
+
const [items, total_lines] = await File.get(
|
|
929
|
+
join(
|
|
930
|
+
path,
|
|
931
|
+
File.encodeFileName((prefix ?? "") + field.key, "inib")
|
|
932
|
+
),
|
|
933
|
+
linesNumber,
|
|
934
|
+
"number",
|
|
935
|
+
undefined,
|
|
936
|
+
this.salt
|
|
937
|
+
);
|
|
938
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
939
|
+
for (const [index, item] of Object.entries(items)) {
|
|
971
940
|
if (!RETURN[index]) RETURN[index] = {};
|
|
972
|
-
RETURN[index][field.key] =
|
|
973
|
-
? await this.get(field.key,
|
|
941
|
+
RETURN[index][field.key] = item
|
|
942
|
+
? await this.get(field.key, item as number, options)
|
|
974
943
|
: this.getDefaultValue(field);
|
|
975
944
|
}
|
|
976
945
|
}
|
|
977
946
|
} else if (
|
|
978
|
-
|
|
947
|
+
await File.isExists(
|
|
979
948
|
join(path, File.encodeFileName((prefix ?? "") + field.key, "inib"))
|
|
980
949
|
)
|
|
981
|
-
)
|
|
982
|
-
|
|
983
|
-
(
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
).forEach(([index, item]) => {
|
|
950
|
+
) {
|
|
951
|
+
const [items, total_lines] = await File.get(
|
|
952
|
+
join(path, File.encodeFileName((prefix ?? "") + field.key, "inib")),
|
|
953
|
+
linesNumber,
|
|
954
|
+
field.type,
|
|
955
|
+
(field as any)?.children,
|
|
956
|
+
this.salt
|
|
957
|
+
);
|
|
958
|
+
|
|
959
|
+
this.totalItems[tableName + "-" + field.key] = total_lines;
|
|
960
|
+
for (const [index, item] of Object.entries(items)) {
|
|
993
961
|
if (!RETURN[index]) RETURN[index] = {};
|
|
994
962
|
RETURN[index][field.key] = item ?? this.getDefaultValue(field);
|
|
995
|
-
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
996
965
|
}
|
|
997
966
|
return RETURN;
|
|
998
967
|
};
|
|
@@ -1000,7 +969,7 @@ export default class Inibase {
|
|
|
1000
969
|
// Display all data
|
|
1001
970
|
RETURN = Object.values(
|
|
1002
971
|
await getItemsFromSchema(
|
|
1003
|
-
join(this.
|
|
972
|
+
join(this.folder, this.database, tableName),
|
|
1004
973
|
schema,
|
|
1005
974
|
Array.from(
|
|
1006
975
|
{ length: options.per_page },
|
|
@@ -1014,18 +983,19 @@ export default class Inibase {
|
|
|
1014
983
|
} else if (Utils.isValidID(where) || Utils.isNumber(where)) {
|
|
1015
984
|
let Ids = where as string | number | (string | number)[];
|
|
1016
985
|
if (!Array.isArray(Ids)) Ids = [Ids];
|
|
1017
|
-
const idFilePath = join(this.databasePath, tableName, "id.inib");
|
|
1018
|
-
if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
|
|
1019
986
|
const [lineNumbers, countItems] = await File.search(
|
|
1020
987
|
idFilePath,
|
|
1021
988
|
"[]",
|
|
1022
989
|
Utils.isNumber(Ids)
|
|
1023
990
|
? Ids.map((id) => Number(id as string))
|
|
1024
|
-
: Ids.map((id) =>
|
|
991
|
+
: Ids.map((id) => UtilsServer.decodeID(id as string, this.salt)),
|
|
1025
992
|
undefined,
|
|
1026
993
|
"number",
|
|
1027
994
|
undefined,
|
|
1028
|
-
Ids.length
|
|
995
|
+
Ids.length,
|
|
996
|
+
0,
|
|
997
|
+
false,
|
|
998
|
+
this.salt
|
|
1029
999
|
);
|
|
1030
1000
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1031
1001
|
throw this.throwError(
|
|
@@ -1034,7 +1004,7 @@ export default class Inibase {
|
|
|
1034
1004
|
);
|
|
1035
1005
|
RETURN = Object.values(
|
|
1036
1006
|
(await getItemsFromSchema(
|
|
1037
|
-
join(this.
|
|
1007
|
+
join(this.folder, this.database, tableName),
|
|
1038
1008
|
schema,
|
|
1039
1009
|
Object.keys(lineNumbers).map(Number)
|
|
1040
1010
|
)) ?? {}
|
|
@@ -1227,9 +1197,10 @@ export default class Inibase {
|
|
|
1227
1197
|
searchOperator = "=";
|
|
1228
1198
|
searchComparedAtValue = value as number | boolean;
|
|
1229
1199
|
}
|
|
1230
|
-
const [searchResult,
|
|
1200
|
+
const [searchResult, total_lines] = await File.search(
|
|
1231
1201
|
join(
|
|
1232
|
-
this.
|
|
1202
|
+
this.folder,
|
|
1203
|
+
this.database,
|
|
1233
1204
|
tableName,
|
|
1234
1205
|
File.encodeFileName(key, "inib")
|
|
1235
1206
|
),
|
|
@@ -1240,12 +1211,12 @@ export default class Inibase {
|
|
|
1240
1211
|
(field as any)?.children,
|
|
1241
1212
|
options.per_page,
|
|
1242
1213
|
(options.page as number) - 1 * (options.per_page as number) + 1,
|
|
1243
|
-
true
|
|
1214
|
+
true,
|
|
1215
|
+
this.salt
|
|
1244
1216
|
);
|
|
1245
1217
|
if (searchResult) {
|
|
1246
1218
|
RETURN = Utils.deepMerge(RETURN, searchResult);
|
|
1247
|
-
|
|
1248
|
-
this.pageInfoArray[key].total_items = totlaItems;
|
|
1219
|
+
this.totalItems[tableName + "-" + key] = total_lines;
|
|
1249
1220
|
}
|
|
1250
1221
|
if (allTrue && index > 0) {
|
|
1251
1222
|
if (!Object.keys(RETURN).length) RETURN = {};
|
|
@@ -1264,30 +1235,12 @@ export default class Inibase {
|
|
|
1264
1235
|
if (RETURN) {
|
|
1265
1236
|
if (onlyLinesNumbers) return Object.keys(RETURN).map(Number);
|
|
1266
1237
|
const alreadyExistsColumns = Object.keys(Object.values(RETURN)[0]).map(
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
greatestColumnTotalItems = alreadyExistsColumns.reduce(
|
|
1270
|
-
(maxItem: string, currentItem: string) =>
|
|
1271
|
-
this.pageInfoArray[currentItem]?.total_items ||
|
|
1272
|
-
(0 > (this.pageInfoArray[maxItem]?.total_items || 0) &&
|
|
1273
|
-
this.pageInfoArray[currentItem].total_items)
|
|
1274
|
-
? currentItem
|
|
1275
|
-
: maxItem,
|
|
1276
|
-
""
|
|
1277
|
-
);
|
|
1278
|
-
if (greatestColumnTotalItems)
|
|
1279
|
-
this.pageInfo = {
|
|
1280
|
-
...(({ columns, ...restOfOptions }) => restOfOptions)(options),
|
|
1281
|
-
...this.pageInfoArray[greatestColumnTotalItems],
|
|
1282
|
-
total_pages: Math.ceil(
|
|
1283
|
-
this.pageInfoArray[greatestColumnTotalItems].total_items /
|
|
1284
|
-
options.per_page
|
|
1285
|
-
),
|
|
1286
|
-
};
|
|
1238
|
+
(key) => File.decodeFileName(parse(key).name)
|
|
1239
|
+
);
|
|
1287
1240
|
RETURN = Object.values(
|
|
1288
1241
|
Utils.deepMerge(
|
|
1289
1242
|
await getItemsFromSchema(
|
|
1290
|
-
join(this.
|
|
1243
|
+
join(this.folder, this.database, tableName),
|
|
1291
1244
|
schema.filter(
|
|
1292
1245
|
(field) => !alreadyExistsColumns.includes(field.key)
|
|
1293
1246
|
),
|
|
@@ -1304,15 +1257,18 @@ export default class Inibase {
|
|
|
1304
1257
|
(Array.isArray(RETURN) && !RETURN.length)
|
|
1305
1258
|
)
|
|
1306
1259
|
return null;
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1260
|
+
|
|
1261
|
+
const greatestTotalItems = Math.max(
|
|
1262
|
+
...Object.entries(this.totalItems)
|
|
1263
|
+
.filter(([k]) => k.startsWith(tableName + "-"))
|
|
1264
|
+
.map(([, v]) => v)
|
|
1265
|
+
);
|
|
1266
|
+
this.pageInfo = {
|
|
1267
|
+
...(({ columns, ...restOfOptions }) => restOfOptions)(options),
|
|
1268
|
+
total_pages: Math.ceil(greatestTotalItems / options.per_page),
|
|
1269
|
+
total: greatestTotalItems,
|
|
1270
|
+
};
|
|
1271
|
+
return RETURN;
|
|
1316
1272
|
}
|
|
1317
1273
|
|
|
1318
1274
|
public async post(
|
|
@@ -1321,52 +1277,55 @@ export default class Inibase {
|
|
|
1321
1277
|
options: Options = {
|
|
1322
1278
|
page: 1,
|
|
1323
1279
|
per_page: 15,
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1280
|
+
},
|
|
1281
|
+
returnPostedData: boolean = true
|
|
1282
|
+
): Promise<Data | Data[] | null | void> {
|
|
1283
|
+
const schema = await this.getTableSchema(tableName);
|
|
1327
1284
|
let RETURN: Data | Data[] | null | undefined;
|
|
1328
1285
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1329
|
-
const idFilePath = join(this.
|
|
1330
|
-
let last_id =
|
|
1331
|
-
? Number(
|
|
1286
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1287
|
+
let last_id = (await File.isExists(idFilePath))
|
|
1288
|
+
? Number(
|
|
1289
|
+
Object.values(
|
|
1290
|
+
await File.get(idFilePath, -1, "number", undefined, this.salt)
|
|
1291
|
+
)[0]
|
|
1292
|
+
)
|
|
1332
1293
|
: 0;
|
|
1333
1294
|
if (Utils.isArrayOfObjects(data))
|
|
1334
1295
|
(data as Data[]).forEach((single_data, index) => {
|
|
1335
1296
|
if (!RETURN) RETURN = [];
|
|
1336
|
-
RETURN[index] = (({ id, updated_at, created_at, ...rest }) =>
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1297
|
+
RETURN[index] = (({ id, updated_at, created_at, ...rest }) => ({
|
|
1298
|
+
id: ++last_id,
|
|
1299
|
+
...rest,
|
|
1300
|
+
created_at: new Date(),
|
|
1301
|
+
}))(single_data);
|
|
1341
1302
|
});
|
|
1342
|
-
else
|
|
1343
|
-
RETURN = (({ id, updated_at, created_at, ...rest }) =>
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
}
|
|
1303
|
+
else
|
|
1304
|
+
RETURN = (({ id, updated_at, created_at, ...rest }) => ({
|
|
1305
|
+
id: ++last_id,
|
|
1306
|
+
...rest,
|
|
1307
|
+
created_at: new Date(),
|
|
1308
|
+
}))(data as Data);
|
|
1349
1309
|
if (!RETURN) throw this.throwError("NO_DATA");
|
|
1350
|
-
this.validateData(RETURN, schema);
|
|
1351
1310
|
RETURN = this.formatData(RETURN, schema);
|
|
1352
1311
|
const pathesContents = this.joinPathesContents(
|
|
1353
|
-
join(this.
|
|
1312
|
+
join(this.folder, this.database, tableName),
|
|
1354
1313
|
RETURN
|
|
1355
1314
|
);
|
|
1356
|
-
for (const [path, content] of Object.entries(pathesContents))
|
|
1357
|
-
|
|
1315
|
+
for await (const [path, content] of Object.entries(pathesContents))
|
|
1316
|
+
await appendFile(
|
|
1358
1317
|
path,
|
|
1359
|
-
(Array.isArray(content) ? content.join("\n") : content ?? "") + "\n"
|
|
1360
|
-
"utf8"
|
|
1318
|
+
(Array.isArray(content) ? content.join("\n") : content ?? "") + "\n"
|
|
1361
1319
|
);
|
|
1362
1320
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1321
|
+
if (returnPostedData)
|
|
1322
|
+
return this.get(
|
|
1323
|
+
tableName,
|
|
1324
|
+
Utils.isArrayOfObjects(RETURN)
|
|
1325
|
+
? RETURN.map((data: Data) => data.id)
|
|
1326
|
+
: ((RETURN as Data).id as number),
|
|
1327
|
+
options
|
|
1328
|
+
);
|
|
1370
1329
|
}
|
|
1371
1330
|
|
|
1372
1331
|
public async put(
|
|
@@ -1376,11 +1335,14 @@ export default class Inibase {
|
|
|
1376
1335
|
options: Options = {
|
|
1377
1336
|
page: 1,
|
|
1378
1337
|
per_page: 15,
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1338
|
+
},
|
|
1339
|
+
returnPostedData: boolean = true
|
|
1340
|
+
): Promise<Data | Data[] | null | void> {
|
|
1341
|
+
const schema = await this.getTableSchema(tableName);
|
|
1382
1342
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1383
|
-
this.
|
|
1343
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1344
|
+
if (!(await File.isExists(idFilePath)))
|
|
1345
|
+
throw this.throwError("NO_ITEMS", tableName);
|
|
1384
1346
|
data = this.formatData(data, schema, true);
|
|
1385
1347
|
if (!where) {
|
|
1386
1348
|
if (Utils.isArrayOfObjects(data)) {
|
|
@@ -1401,11 +1363,11 @@ export default class Inibase {
|
|
|
1401
1363
|
return this.put(
|
|
1402
1364
|
tableName,
|
|
1403
1365
|
data,
|
|
1404
|
-
|
|
1366
|
+
UtilsServer.decodeID((data as Data).id as string, this.salt)
|
|
1405
1367
|
);
|
|
1406
1368
|
} else {
|
|
1407
1369
|
const pathesContents = this.joinPathesContents(
|
|
1408
|
-
join(this.
|
|
1370
|
+
join(this.folder, this.database, tableName),
|
|
1409
1371
|
Utils.isArrayOfObjects(data)
|
|
1410
1372
|
? (data as Data[]).map((item) => ({
|
|
1411
1373
|
...(({ id, ...restOfData }) => restOfData)(item),
|
|
@@ -1418,21 +1380,22 @@ export default class Inibase {
|
|
|
1418
1380
|
);
|
|
1419
1381
|
for (const [path, content] of Object.entries(pathesContents))
|
|
1420
1382
|
await File.replace(path, content);
|
|
1421
|
-
return this.get(tableName, where, options);
|
|
1383
|
+
if (returnPostedData) return this.get(tableName, where, options);
|
|
1422
1384
|
}
|
|
1423
1385
|
} else if (Utils.isValidID(where)) {
|
|
1424
1386
|
let Ids = where as string | string[];
|
|
1425
1387
|
if (!Array.isArray(Ids)) Ids = [Ids];
|
|
1426
|
-
const idFilePath = join(this.databasePath, tableName, "id.inib");
|
|
1427
|
-
if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
|
|
1428
1388
|
const [lineNumbers, countItems] = await File.search(
|
|
1429
1389
|
idFilePath,
|
|
1430
1390
|
"[]",
|
|
1431
|
-
Ids.map((id) =>
|
|
1391
|
+
Ids.map((id) => UtilsServer.decodeID(id, this.salt)),
|
|
1432
1392
|
undefined,
|
|
1433
1393
|
"number",
|
|
1434
1394
|
undefined,
|
|
1435
|
-
Ids.length
|
|
1395
|
+
Ids.length,
|
|
1396
|
+
0,
|
|
1397
|
+
false,
|
|
1398
|
+
this.salt
|
|
1436
1399
|
);
|
|
1437
1400
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1438
1401
|
throw this.throwError("INVALID_ID");
|
|
@@ -1442,7 +1405,7 @@ export default class Inibase {
|
|
|
1442
1405
|
const pathesContents = Object.fromEntries(
|
|
1443
1406
|
Object.entries(
|
|
1444
1407
|
this.joinPathesContents(
|
|
1445
|
-
join(this.
|
|
1408
|
+
join(this.folder, this.database, tableName),
|
|
1446
1409
|
Utils.isArrayOfObjects(data)
|
|
1447
1410
|
? (data as Data[]).map((item) => ({
|
|
1448
1411
|
...item,
|
|
@@ -1463,7 +1426,7 @@ export default class Inibase {
|
|
|
1463
1426
|
);
|
|
1464
1427
|
for (const [path, content] of Object.entries(pathesContents))
|
|
1465
1428
|
await File.replace(path, content);
|
|
1466
|
-
return this.get(tableName, where, options);
|
|
1429
|
+
if (returnPostedData) return this.get(tableName, where, options);
|
|
1467
1430
|
} else if (typeof where === "object" && !Array.isArray(where)) {
|
|
1468
1431
|
const lineNumbers = this.get(tableName, where, undefined, true);
|
|
1469
1432
|
if (!lineNumbers || !Array.isArray(lineNumbers) || !lineNumbers.length)
|
|
@@ -1476,31 +1439,35 @@ export default class Inibase {
|
|
|
1476
1439
|
tableName: string,
|
|
1477
1440
|
where?: number | string | (number | string)[] | Criteria,
|
|
1478
1441
|
_id?: string | string[]
|
|
1479
|
-
): Promise<string | string[]> {
|
|
1480
|
-
const schema = this.getTableSchema(tableName);
|
|
1442
|
+
): Promise<string | string[] | null> {
|
|
1443
|
+
const schema = await this.getTableSchema(tableName);
|
|
1481
1444
|
if (!schema) throw this.throwError("NO_SCHEMA", tableName);
|
|
1445
|
+
const idFilePath = join(this.folder, this.database, tableName, "id.inib");
|
|
1446
|
+
if (!(await File.isExists(idFilePath)))
|
|
1447
|
+
throw this.throwError("NO_ITEMS", tableName);
|
|
1482
1448
|
if (!where) {
|
|
1483
|
-
const files =
|
|
1449
|
+
const files = await readdir(join(this.folder, this.database, tableName));
|
|
1484
1450
|
if (files.length) {
|
|
1485
1451
|
for (const file in files.filter(
|
|
1486
|
-
(fileName: string) => fileName !== "schema
|
|
1452
|
+
(fileName: string) => fileName !== "schema"
|
|
1487
1453
|
))
|
|
1488
|
-
|
|
1454
|
+
await unlink(join(this.folder, this.database, tableName, file));
|
|
1489
1455
|
}
|
|
1490
1456
|
return "*";
|
|
1491
1457
|
} else if (Utils.isValidID(where)) {
|
|
1492
1458
|
let Ids = where as string | string[];
|
|
1493
1459
|
if (!Array.isArray(Ids)) Ids = [Ids];
|
|
1494
|
-
const idFilePath = join(this.databasePath, tableName, "id.inib");
|
|
1495
|
-
if (!existsSync(idFilePath)) throw this.throwError("NO_ITEMS", tableName);
|
|
1496
1460
|
const [lineNumbers, countItems] = await File.search(
|
|
1497
1461
|
idFilePath,
|
|
1498
1462
|
"[]",
|
|
1499
|
-
Ids.map((id) =>
|
|
1463
|
+
Ids.map((id) => UtilsServer.decodeID(id, this.salt)),
|
|
1500
1464
|
undefined,
|
|
1501
1465
|
"number",
|
|
1502
1466
|
undefined,
|
|
1503
|
-
Ids.length
|
|
1467
|
+
Ids.length,
|
|
1468
|
+
0,
|
|
1469
|
+
false,
|
|
1470
|
+
this.salt
|
|
1504
1471
|
);
|
|
1505
1472
|
if (!lineNumbers || !Object.keys(lineNumbers).length)
|
|
1506
1473
|
throw this.throwError("INVALID_ID");
|
|
@@ -1510,23 +1477,26 @@ export default class Inibase {
|
|
|
1510
1477
|
where as string | string[]
|
|
1511
1478
|
);
|
|
1512
1479
|
} else if (Utils.isNumber(where)) {
|
|
1513
|
-
const files =
|
|
1480
|
+
const files = await readdir(join(this.folder, this.database, tableName));
|
|
1514
1481
|
if (files.length) {
|
|
1515
1482
|
if (!_id)
|
|
1516
1483
|
_id = Object.values(
|
|
1517
1484
|
await File.get(
|
|
1518
|
-
join(this.
|
|
1485
|
+
join(this.folder, this.database, tableName, "id.inib"),
|
|
1519
1486
|
where as number | number[],
|
|
1520
|
-
"number"
|
|
1487
|
+
"number",
|
|
1488
|
+
undefined,
|
|
1489
|
+
this.salt
|
|
1521
1490
|
)
|
|
1522
1491
|
)
|
|
1523
1492
|
.map(Number)
|
|
1524
|
-
.map((id) =>
|
|
1525
|
-
for (const file
|
|
1526
|
-
(fileName: string) =>
|
|
1493
|
+
.map((id) => UtilsServer.encodeID(id, this.salt));
|
|
1494
|
+
for (const file of files.filter(
|
|
1495
|
+
(fileName: string) =>
|
|
1496
|
+
fileName.endsWith(".inib") && fileName !== "schema"
|
|
1527
1497
|
))
|
|
1528
1498
|
await File.remove(
|
|
1529
|
-
join(this.
|
|
1499
|
+
join(this.folder, this.database, tableName, file),
|
|
1530
1500
|
where as number | number[]
|
|
1531
1501
|
);
|
|
1532
1502
|
return Array.isArray(_id) && _id.length === 1 ? _id[0] : _id;
|
|
@@ -1537,5 +1507,6 @@ export default class Inibase {
|
|
|
1537
1507
|
throw this.throwError("NO_ITEMS", tableName);
|
|
1538
1508
|
return this.delete(tableName, lineNumbers);
|
|
1539
1509
|
} else throw this.throwError("INVALID_PARAMETERS", tableName);
|
|
1510
|
+
return null;
|
|
1540
1511
|
}
|
|
1541
1512
|
}
|