inibase 1.2.20 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +13 -7
- package/dist/index.js +79 -44
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +48 -3
- package/dist/utils.server.d.ts +1 -20
- package/dist/utils.server.js +1 -53
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface Data {
|
|
|
7
7
|
}
|
|
8
8
|
export type FieldType = "string" | "number" | "boolean" | "date" | "email" | "url" | "table" | "object" | "array" | "password" | "html" | "ip" | "json" | "id";
|
|
9
9
|
export type Field = {
|
|
10
|
-
id?:
|
|
10
|
+
id?: number;
|
|
11
11
|
key: string;
|
|
12
12
|
type: FieldType | FieldType[];
|
|
13
13
|
required?: boolean;
|
|
@@ -63,18 +63,24 @@ export declare const globalConfig: {
|
|
|
63
63
|
} & {
|
|
64
64
|
salt?: string | Buffer;
|
|
65
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* @param {string} database - Database name
|
|
68
|
+
* @param {string} [mainFolder="."] - Main folder path
|
|
69
|
+
* @param {ErrorLang} [language="en"] - Language for error messages
|
|
70
|
+
*/
|
|
66
71
|
export default class Inibase {
|
|
67
72
|
pageInfo: Record<string, pageInfo>;
|
|
68
73
|
language: ErrorLang;
|
|
69
74
|
fileExtension: string;
|
|
75
|
+
totalItems: Map<string, number>;
|
|
70
76
|
private databasePath;
|
|
71
77
|
private uniqueMap;
|
|
72
|
-
|
|
78
|
+
private schemaFileExtension;
|
|
73
79
|
constructor(database: string, mainFolder?: string, language?: ErrorLang);
|
|
74
80
|
private static errorMessages;
|
|
75
81
|
createError(name: ErrorCode, variable?: string | number | (string | number)[]): Error;
|
|
76
82
|
private getFileExtension;
|
|
77
|
-
private
|
|
83
|
+
private schemaToIdsPath;
|
|
78
84
|
/**
|
|
79
85
|
* Create a new table inside database, with predefined schema and config
|
|
80
86
|
*
|
|
@@ -100,11 +106,11 @@ export default class Inibase {
|
|
|
100
106
|
* @param {string} tableName
|
|
101
107
|
* @return {*} {Promise<TableObject>}
|
|
102
108
|
*/
|
|
103
|
-
getTable(tableName: string
|
|
104
|
-
getTableSchema(tableName: string
|
|
109
|
+
getTable(tableName: string): Promise<TableObject>;
|
|
110
|
+
getTableSchema(tableName: string): Promise<Schema>;
|
|
105
111
|
private throwErrorIfTableEmpty;
|
|
106
|
-
|
|
107
|
-
private
|
|
112
|
+
validateData(data: Data | Data[], schema: Schema, skipRequiredField?: boolean): void;
|
|
113
|
+
private validateTableData;
|
|
108
114
|
private cleanObject;
|
|
109
115
|
private formatField;
|
|
110
116
|
private checkUnique;
|
package/dist/index.js
CHANGED
|
@@ -25,13 +25,19 @@ export const ERROR_CODES = [
|
|
|
25
25
|
// hide ExperimentalWarning glob()
|
|
26
26
|
process.removeAllListeners("warning");
|
|
27
27
|
export const globalConfig = {};
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} database - Database name
|
|
30
|
+
* @param {string} [mainFolder="."] - Main folder path
|
|
31
|
+
* @param {ErrorLang} [language="en"] - Language for error messages
|
|
32
|
+
*/
|
|
28
33
|
export default class Inibase {
|
|
29
34
|
pageInfo;
|
|
30
35
|
language;
|
|
31
36
|
fileExtension = ".txt";
|
|
37
|
+
totalItems;
|
|
32
38
|
databasePath;
|
|
33
39
|
uniqueMap;
|
|
34
|
-
|
|
40
|
+
schemaFileExtension = process.env.INIBASE_SCHEMA_EXTENSION ?? "json";
|
|
35
41
|
constructor(database, mainFolder = ".", language = "en") {
|
|
36
42
|
this.databasePath = join(mainFolder, database);
|
|
37
43
|
this.language = language;
|
|
@@ -137,15 +143,16 @@ export default class Inibase {
|
|
|
137
143
|
mainExtension += ".gz";
|
|
138
144
|
return mainExtension;
|
|
139
145
|
}
|
|
140
|
-
|
|
146
|
+
schemaToIdsPath(tableName, schema, prefix = "") {
|
|
141
147
|
const RETURN = {};
|
|
142
148
|
for (const field of schema)
|
|
143
149
|
if ((field.type === "array" || field.type === "object") &&
|
|
144
150
|
field.children &&
|
|
145
151
|
Utils.isArrayOfObjects(field.children))
|
|
146
|
-
Utils.deepMerge(RETURN, this.
|
|
152
|
+
Utils.deepMerge(RETURN, this.schemaToIdsPath(tableName, field.children, `${(prefix ?? "") + field.key}.`));
|
|
147
153
|
else if (field.id)
|
|
148
|
-
RETURN[
|
|
154
|
+
RETURN[field.id] =
|
|
155
|
+
`${(prefix ?? "") + field.key}${this.getFileExtension(tableName)}`;
|
|
149
156
|
return RETURN;
|
|
150
157
|
}
|
|
151
158
|
/**
|
|
@@ -179,7 +186,9 @@ export default class Inibase {
|
|
|
179
186
|
}
|
|
180
187
|
if (schema) {
|
|
181
188
|
const lastSchemaID = { value: 0 };
|
|
182
|
-
await writeFile(join(tablePath,
|
|
189
|
+
await writeFile(join(tablePath, `schema.${this.schemaFileExtension}`), this.schemaFileExtension === "json"
|
|
190
|
+
? JSON.stringify(Utils.addIdToSchema(schema, lastSchemaID), null, 2)
|
|
191
|
+
: Inison.stringify(Utils.addIdToSchema(schema, lastSchemaID)));
|
|
183
192
|
await writeFile(join(tablePath, `${lastSchemaID.value}.schema`), "");
|
|
184
193
|
}
|
|
185
194
|
else
|
|
@@ -213,21 +222,25 @@ export default class Inibase {
|
|
|
213
222
|
const lastSchemaID = {
|
|
214
223
|
value: schemaIdFilePath ? Number(parse(schemaIdFilePath).name) : 0,
|
|
215
224
|
};
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
225
|
+
schema = Utils.addIdToSchema(schema, lastSchemaID);
|
|
226
|
+
// if schema.json exists, update columns files names based on field id
|
|
227
|
+
if ((await File.isExists(join(tablePath, `schema.${this.schemaFileExtension}`))) &&
|
|
228
|
+
table.schema?.length) {
|
|
229
|
+
const replaceOldPathes = Utils.findChangedProperties(this.schemaToIdsPath(tableName, table.schema), this.schemaToIdsPath(tableName, schema));
|
|
230
|
+
if (replaceOldPathes)
|
|
231
|
+
await Promise.all(Object.entries(replaceOldPathes).map(async ([oldPath, newPath]) => {
|
|
232
|
+
if (await File.isExists(join(tablePath, oldPath))) {
|
|
233
|
+
// if newPath is null, it means the field was removed
|
|
234
|
+
if (newPath === null)
|
|
235
|
+
await unlink(join(tablePath, oldPath));
|
|
236
|
+
else
|
|
224
237
|
await rename(join(tablePath, oldPath), join(tablePath, newPath));
|
|
225
|
-
}
|
|
226
|
-
|
|
238
|
+
}
|
|
239
|
+
}));
|
|
227
240
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
241
|
+
await writeFile(join(tablePath, `schema.${this.schemaFileExtension}`), this.schemaFileExtension === "json"
|
|
242
|
+
? JSON.stringify(schema, null, 2)
|
|
243
|
+
: Inison.stringify(schema));
|
|
231
244
|
if (schemaIdFilePath)
|
|
232
245
|
await rename(schemaIdFilePath, join(tablePath, `${lastSchemaID.value}.schema`));
|
|
233
246
|
else
|
|
@@ -294,10 +307,16 @@ export default class Inibase {
|
|
|
294
307
|
if (config.name) {
|
|
295
308
|
await rename(tablePath, join(this.databasePath, config.name));
|
|
296
309
|
// replace table name in other linked tables (relationship)
|
|
297
|
-
for await (const schemaPath of glob(
|
|
310
|
+
for await (const schemaPath of glob(`**/schema.${this.schemaFileExtension}`, {
|
|
298
311
|
cwd: this.databasePath,
|
|
299
312
|
}))
|
|
300
|
-
await this.replaceStringInFile(schemaPath,
|
|
313
|
+
await this.replaceStringInFile(schemaPath,
|
|
314
|
+
// TODO: escape caracters in table name
|
|
315
|
+
this.schemaFileExtension === "json"
|
|
316
|
+
? `"table": "${tableName}"`
|
|
317
|
+
: `table:${tableName}`, this.schemaFileExtension === "json"
|
|
318
|
+
? `"table": "${config.name}"`
|
|
319
|
+
: `table:${config.name}`);
|
|
301
320
|
}
|
|
302
321
|
}
|
|
303
322
|
globalConfig[this.databasePath].tables.delete(tableName);
|
|
@@ -308,7 +327,7 @@ export default class Inibase {
|
|
|
308
327
|
* @param {string} tableName
|
|
309
328
|
* @return {*} {Promise<TableObject>}
|
|
310
329
|
*/
|
|
311
|
-
async getTable(tableName
|
|
330
|
+
async getTable(tableName) {
|
|
312
331
|
const tablePath = join(this.databasePath, tableName);
|
|
313
332
|
if (!(await File.isExists(tablePath)))
|
|
314
333
|
throw this.createError("TABLE_NOT_EXISTS", tableName);
|
|
@@ -316,7 +335,7 @@ export default class Inibase {
|
|
|
316
335
|
globalConfig[this.databasePath].tables.get(tableName).timestamp !==
|
|
317
336
|
(await File.getFileDate(join(tablePath, "schema.json"))))
|
|
318
337
|
globalConfig[this.databasePath].tables.set(tableName, {
|
|
319
|
-
schema: await this.getTableSchema(tableName
|
|
338
|
+
schema: await this.getTableSchema(tableName),
|
|
320
339
|
config: {
|
|
321
340
|
compression: await File.isExists(join(tablePath, ".compression.config")),
|
|
322
341
|
cache: await File.isExists(join(tablePath, ".cache.config")),
|
|
@@ -327,15 +346,36 @@ export default class Inibase {
|
|
|
327
346
|
});
|
|
328
347
|
return globalConfig[this.databasePath].tables.get(tableName);
|
|
329
348
|
}
|
|
330
|
-
async getTableSchema(tableName
|
|
349
|
+
async getTableSchema(tableName) {
|
|
331
350
|
const tablePath = join(this.databasePath, tableName);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
351
|
+
let schemaFile;
|
|
352
|
+
let schema;
|
|
353
|
+
if (!(await File.isExists(join(tablePath, `schema.${this.schemaFileExtension}`)))) {
|
|
354
|
+
const otherSchemaFileExtension = this.schemaFileExtension === "json" ? "inis" : "json";
|
|
355
|
+
if (!(await File.isExists(join(tablePath, `schema.${otherSchemaFileExtension}`))))
|
|
356
|
+
return undefined;
|
|
357
|
+
schemaFile = await readFile(join(tablePath, `schema.${otherSchemaFileExtension}`), "utf8");
|
|
358
|
+
if (!schemaFile)
|
|
359
|
+
return undefined;
|
|
360
|
+
schema =
|
|
361
|
+
otherSchemaFileExtension === "json"
|
|
362
|
+
? JSON.parse(schemaFile)
|
|
363
|
+
: Inison.unstringify(schemaFile);
|
|
364
|
+
await writeFile(join(tablePath, `schema.${this.schemaFileExtension}`), this.schemaFileExtension === "json"
|
|
365
|
+
? JSON.stringify(schema, null, 2)
|
|
366
|
+
: Inison.stringify(schema));
|
|
367
|
+
await unlink(join(tablePath, `schema.${otherSchemaFileExtension}`));
|
|
368
|
+
}
|
|
369
|
+
else
|
|
370
|
+
schemaFile = await readFile(join(tablePath, `schema.${this.schemaFileExtension}`), "utf8");
|
|
335
371
|
if (!schemaFile)
|
|
336
372
|
return undefined;
|
|
337
|
-
|
|
338
|
-
|
|
373
|
+
if (!schema)
|
|
374
|
+
schema =
|
|
375
|
+
this.schemaFileExtension === "json"
|
|
376
|
+
? JSON.parse(schemaFile)
|
|
377
|
+
: Inison.unstringify(schemaFile);
|
|
378
|
+
return [
|
|
339
379
|
{
|
|
340
380
|
id: 0,
|
|
341
381
|
key: "id",
|
|
@@ -355,21 +395,18 @@ export default class Inibase {
|
|
|
355
395
|
type: "date",
|
|
356
396
|
},
|
|
357
397
|
];
|
|
358
|
-
if (!encodeIDs)
|
|
359
|
-
return schema;
|
|
360
|
-
return UtilsServer.encodeSchemaID(schema);
|
|
361
398
|
}
|
|
362
399
|
async throwErrorIfTableEmpty(tableName) {
|
|
363
|
-
const table = await this.getTable(tableName
|
|
400
|
+
const table = await this.getTable(tableName);
|
|
364
401
|
if (!table.schema)
|
|
365
402
|
throw this.createError("NO_SCHEMA", tableName);
|
|
366
403
|
if (!(await File.isExists(join(this.databasePath, tableName, `id${this.getFileExtension(tableName)}`))))
|
|
367
404
|
throw this.createError("TABLE_EMPTY", tableName);
|
|
368
405
|
}
|
|
369
|
-
|
|
406
|
+
validateData(data, schema, skipRequiredField = false) {
|
|
370
407
|
if (Utils.isArrayOfObjects(data)) {
|
|
371
408
|
for (const single_data of data)
|
|
372
|
-
this.
|
|
409
|
+
this.validateData(single_data, schema, skipRequiredField);
|
|
373
410
|
return;
|
|
374
411
|
}
|
|
375
412
|
if (Utils.isObject(data)) {
|
|
@@ -398,7 +435,7 @@ export default class Inibase {
|
|
|
398
435
|
if ((field.type === "array" || field.type === "object") &&
|
|
399
436
|
field.children &&
|
|
400
437
|
Utils.isArrayOfObjects(field.children))
|
|
401
|
-
this.
|
|
438
|
+
this.validateData(data[field.key], field.children, skipRequiredField);
|
|
402
439
|
else {
|
|
403
440
|
if (field.table &&
|
|
404
441
|
Utils.isObject(data[field.key]) &&
|
|
@@ -420,9 +457,7 @@ export default class Inibase {
|
|
|
420
457
|
exclude: new Set(),
|
|
421
458
|
columnsValues: new Map(),
|
|
422
459
|
});
|
|
423
|
-
if (!this.uniqueMap
|
|
424
|
-
.get(uniqueKey)
|
|
425
|
-
.columnsValues.has(field.id))
|
|
460
|
+
if (!this.uniqueMap.get(uniqueKey).columnsValues.has(field.id))
|
|
426
461
|
this.uniqueMap
|
|
427
462
|
.get(uniqueKey)
|
|
428
463
|
.columnsValues.set(field.id, new Set());
|
|
@@ -437,10 +472,10 @@ export default class Inibase {
|
|
|
437
472
|
}
|
|
438
473
|
}
|
|
439
474
|
}
|
|
440
|
-
async
|
|
475
|
+
async validateTableData(tableName, data, skipRequiredField = false) {
|
|
441
476
|
const clonedData = structuredClone(data);
|
|
442
477
|
// Skip ID and (created|updated)At
|
|
443
|
-
this.
|
|
478
|
+
this.validateData(clonedData, globalConfig[this.databasePath].tables.get(tableName).schema.slice(1, -2), skipRequiredField);
|
|
444
479
|
await this.checkUnique(tableName);
|
|
445
480
|
}
|
|
446
481
|
cleanObject(obj) {
|
|
@@ -1053,7 +1088,7 @@ export default class Inibase {
|
|
|
1053
1088
|
const searchResult = await this.applyCriteria(tableName, options, criteriaAND, true, searchIn);
|
|
1054
1089
|
if (searchResult) {
|
|
1055
1090
|
searchIn = new Set(Object.keys(searchResult).map(Number));
|
|
1056
|
-
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).filter(([_k, v], _i) => Object.keys(v).filter((key) => Object.keys(criteriaAND).
|
|
1091
|
+
RETURN = Utils.deepMerge(RETURN, Object.fromEntries(Object.entries(searchResult).filter(([_k, v], _i) => Object.keys(v).filter((key) => Object.keys(criteriaAND).find((criteriaKey) => criteriaKey === key || criteriaKey.startsWith(`${key}.`))).length)));
|
|
1057
1092
|
}
|
|
1058
1093
|
else
|
|
1059
1094
|
return null;
|
|
@@ -1355,7 +1390,7 @@ export default class Inibase {
|
|
|
1355
1390
|
returnPostedData = false;
|
|
1356
1391
|
let clonedData = structuredClone(data);
|
|
1357
1392
|
const keys = UtilsServer.hashString(Object.keys(Array.isArray(clonedData) ? clonedData[0] : clonedData).join("."));
|
|
1358
|
-
await this.
|
|
1393
|
+
await this.validateTableData(tableName, clonedData);
|
|
1359
1394
|
const renameList = [];
|
|
1360
1395
|
try {
|
|
1361
1396
|
await File.lock(join(tablePath, ".tmp"), keys);
|
|
@@ -1437,7 +1472,7 @@ export default class Inibase {
|
|
|
1437
1472
|
throw this.createError("INVALID_ID", clonedData.id);
|
|
1438
1473
|
return this.put(tableName, clonedData, clonedData.id, options, returnUpdatedData);
|
|
1439
1474
|
}
|
|
1440
|
-
await this.
|
|
1475
|
+
await this.validateTableData(tableName, clonedData, true);
|
|
1441
1476
|
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables.get(tableName).schema, true);
|
|
1442
1477
|
const pathesContents = this.joinPathesContents(tableName, {
|
|
1443
1478
|
...(({ id, ...restOfData }) => restOfData)(clonedData),
|
|
@@ -1469,7 +1504,7 @@ export default class Inibase {
|
|
|
1469
1504
|
(_whereIsLinesNumbers ||
|
|
1470
1505
|
!globalConfig[this.databasePath].tables.get(tableName).config.decodeID)) {
|
|
1471
1506
|
// "where" in this case, is the line(s) number(s) and not id(s)
|
|
1472
|
-
await this.
|
|
1507
|
+
await this.validateTableData(tableName, clonedData, true);
|
|
1473
1508
|
clonedData = this.formatData(clonedData, globalConfig[this.databasePath].tables.get(tableName).schema, true);
|
|
1474
1509
|
const pathesContents = Object.fromEntries(Object.entries(this.joinPathesContents(tableName, Array.isArray(clonedData)
|
|
1475
1510
|
? clonedData.map((item) => ({
|
package/dist/utils.d.ts
CHANGED
|
@@ -200,3 +200,21 @@ export declare const setField: (keyPath: string, schema: Schema, field: Omit<Fie
|
|
|
200
200
|
*/
|
|
201
201
|
export declare const unsetField: (keyPath: string, schema: Schema) => Field;
|
|
202
202
|
export declare function toDotNotation(obj: Record<string, any>, skipKeys?: string[], currentPath?: string): Record<string, any>;
|
|
203
|
+
export declare const extractIdsFromSchema: (schema: Schema) => number[];
|
|
204
|
+
/**
|
|
205
|
+
* Finds the last ID number in a schema, potentially decoding it if encrypted.
|
|
206
|
+
*
|
|
207
|
+
* @param schema - The schema to search, defined as an array of schema objects.
|
|
208
|
+
* @returns The last ID number in the schema, decoded if necessary.
|
|
209
|
+
*/
|
|
210
|
+
export declare const findLastIdNumber: (schema: Schema) => number;
|
|
211
|
+
/**
|
|
212
|
+
* Adds or updates IDs in a schema, encoding them using a provided secret key or salt.
|
|
213
|
+
*
|
|
214
|
+
* @param schema - The schema to update, defined as an array of schema objects.
|
|
215
|
+
* @param startWithID - An object containing the starting ID for generating new IDs.
|
|
216
|
+
* @returns The updated schema with encoded IDs.
|
|
217
|
+
*/
|
|
218
|
+
export declare function addIdToSchema(schema: Schema, startWithID: {
|
|
219
|
+
value: number;
|
|
220
|
+
}): Field[];
|
package/dist/utils.js
CHANGED
|
@@ -226,9 +226,14 @@ export const deepMerge = (target, source) => {
|
|
|
226
226
|
*/
|
|
227
227
|
export const findChangedProperties = (obj1, obj2) => {
|
|
228
228
|
const result = {};
|
|
229
|
-
for (const key1 in obj1)
|
|
230
|
-
if (Object.hasOwn(obj2, key1)
|
|
231
|
-
|
|
229
|
+
for (const key1 in obj1) {
|
|
230
|
+
if (Object.hasOwn(obj2, key1)) {
|
|
231
|
+
if (obj1[key1] !== obj2[key1])
|
|
232
|
+
result[obj1[key1]] = obj2[key1];
|
|
233
|
+
}
|
|
234
|
+
else
|
|
235
|
+
result[obj1[key1]] = null;
|
|
236
|
+
}
|
|
232
237
|
return Object.keys(result).length ? result : null;
|
|
233
238
|
};
|
|
234
239
|
/**
|
|
@@ -583,3 +588,43 @@ export function toDotNotation(obj, skipKeys, currentPath = "") {
|
|
|
583
588
|
}
|
|
584
589
|
return result;
|
|
585
590
|
}
|
|
591
|
+
// Function to recursively flatten an array of objects and their nested children
|
|
592
|
+
export const extractIdsFromSchema = (schema) => {
|
|
593
|
+
const result = [];
|
|
594
|
+
for (const field of schema) {
|
|
595
|
+
if (field.id)
|
|
596
|
+
result.push(field.id);
|
|
597
|
+
if (field.children && isArrayOfObjects(field.children))
|
|
598
|
+
result.push(...extractIdsFromSchema(field.children));
|
|
599
|
+
}
|
|
600
|
+
return result;
|
|
601
|
+
};
|
|
602
|
+
/**
|
|
603
|
+
* Finds the last ID number in a schema, potentially decoding it if encrypted.
|
|
604
|
+
*
|
|
605
|
+
* @param schema - The schema to search, defined as an array of schema objects.
|
|
606
|
+
* @returns The last ID number in the schema, decoded if necessary.
|
|
607
|
+
*/
|
|
608
|
+
export const findLastIdNumber = (schema) => Math.max(...extractIdsFromSchema(schema));
|
|
609
|
+
/**
|
|
610
|
+
* Adds or updates IDs in a schema, encoding them using a provided secret key or salt.
|
|
611
|
+
*
|
|
612
|
+
* @param schema - The schema to update, defined as an array of schema objects.
|
|
613
|
+
* @param startWithID - An object containing the starting ID for generating new IDs.
|
|
614
|
+
* @returns The updated schema with encoded IDs.
|
|
615
|
+
*/
|
|
616
|
+
export function addIdToSchema(schema, startWithID) {
|
|
617
|
+
const clonedSchema = structuredClone(schema);
|
|
618
|
+
function addIdToField(field) {
|
|
619
|
+
if (!field.id) {
|
|
620
|
+
startWithID.value++;
|
|
621
|
+
field.id = startWithID.value;
|
|
622
|
+
}
|
|
623
|
+
if ((field.type === "array" || field.type === "object") &&
|
|
624
|
+
isArrayOfObjects(field.children))
|
|
625
|
+
field.children = addIdToSchemaHelper(field.children);
|
|
626
|
+
return field;
|
|
627
|
+
}
|
|
628
|
+
const addIdToSchemaHelper = (schema) => schema.map(addIdToField);
|
|
629
|
+
return addIdToSchemaHelper(clonedSchema);
|
|
630
|
+
}
|
package/dist/utils.server.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import "dotenv/config";
|
|
|
2
2
|
import { execFile as execFileSync, exec as execSync } from "node:child_process";
|
|
3
3
|
import { gunzip as gunzipSync, gzip as gzipSync } from "node:zlib";
|
|
4
4
|
import RE2 from "re2";
|
|
5
|
-
import type { ComparisonOperator,
|
|
5
|
+
import type { ComparisonOperator, FieldType } from "./index.js";
|
|
6
6
|
export declare const exec: typeof execSync.__promisify__;
|
|
7
7
|
export declare const execFile: typeof execFileSync.__promisify__;
|
|
8
8
|
export declare const gzip: typeof gzipSync.__promisify__;
|
|
@@ -25,25 +25,6 @@ export declare const comparePassword: (hash: string, password: string) => boolea
|
|
|
25
25
|
export declare const encodeID: (id: number | string) => string;
|
|
26
26
|
export declare function decodeID(input: string, raw: true): string | null;
|
|
27
27
|
export declare function decodeID(input?: string, raw?: false): number | null;
|
|
28
|
-
export declare const extractIdsFromSchema: (schema: Schema) => number[];
|
|
29
|
-
/**
|
|
30
|
-
* Finds the last ID number in a schema, potentially decoding it if encrypted.
|
|
31
|
-
*
|
|
32
|
-
* @param schema - The schema to search, defined as an array of schema objects.
|
|
33
|
-
* @returns The last ID number in the schema, decoded if necessary.
|
|
34
|
-
*/
|
|
35
|
-
export declare const findLastIdNumber: (schema: Schema) => number;
|
|
36
|
-
/**
|
|
37
|
-
* Adds or updates IDs in a schema, encoding them using a provided secret key or salt.
|
|
38
|
-
*
|
|
39
|
-
* @param schema - The schema to update, defined as an array of schema objects.
|
|
40
|
-
* @param startWithID - An object containing the starting ID for generating new IDs.
|
|
41
|
-
* @returns The updated schema with encoded IDs.
|
|
42
|
-
*/
|
|
43
|
-
export declare const addIdToSchema: (schema: Schema, startWithID: {
|
|
44
|
-
value: number;
|
|
45
|
-
}) => Field[];
|
|
46
|
-
export declare const encodeSchemaID: (schema: Schema) => Schema;
|
|
47
28
|
export declare const hashString: (str: string) => string;
|
|
48
29
|
/**
|
|
49
30
|
* Evaluates a comparison between two values based on a specified operator and field types.
|
package/dist/utils.server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { promisify } from "node:util";
|
|
|
5
5
|
import { gunzip as gunzipSync, gzip as gzipSync } from "node:zlib";
|
|
6
6
|
import RE2 from "re2";
|
|
7
7
|
import { globalConfig } from "./index.js";
|
|
8
|
-
import { detectFieldType,
|
|
8
|
+
import { detectFieldType, isNumber, isPassword } from "./utils.js";
|
|
9
9
|
export const exec = promisify(execSync);
|
|
10
10
|
export const execFile = promisify(execFileSync);
|
|
11
11
|
export const gzip = promisify(gzipSync);
|
|
@@ -70,58 +70,6 @@ export function decodeID(input, raw) {
|
|
|
70
70
|
return null;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
// Function to recursively flatten an array of objects and their nested children
|
|
74
|
-
export const extractIdsFromSchema = (schema) => {
|
|
75
|
-
const result = [];
|
|
76
|
-
for (const field of schema) {
|
|
77
|
-
if (field.id)
|
|
78
|
-
result.push(typeof field.id === "number" ? field.id : decodeID(field.id));
|
|
79
|
-
if (field.children && isArrayOfObjects(field.children))
|
|
80
|
-
result.push(...extractIdsFromSchema(field.children));
|
|
81
|
-
}
|
|
82
|
-
return result;
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Finds the last ID number in a schema, potentially decoding it if encrypted.
|
|
86
|
-
*
|
|
87
|
-
* @param schema - The schema to search, defined as an array of schema objects.
|
|
88
|
-
* @returns The last ID number in the schema, decoded if necessary.
|
|
89
|
-
*/
|
|
90
|
-
export const findLastIdNumber = (schema) => Math.max(...extractIdsFromSchema(schema));
|
|
91
|
-
/**
|
|
92
|
-
* Adds or updates IDs in a schema, encoding them using a provided secret key or salt.
|
|
93
|
-
*
|
|
94
|
-
* @param schema - The schema to update, defined as an array of schema objects.
|
|
95
|
-
* @param startWithID - An object containing the starting ID for generating new IDs.
|
|
96
|
-
* @returns The updated schema with encoded IDs.
|
|
97
|
-
*/
|
|
98
|
-
export const addIdToSchema = (schema, startWithID) => {
|
|
99
|
-
function _addIdToField(field) {
|
|
100
|
-
if (!field.id) {
|
|
101
|
-
startWithID.value++;
|
|
102
|
-
field.id = startWithID.value;
|
|
103
|
-
}
|
|
104
|
-
else if (isValidID(field.id))
|
|
105
|
-
field.id = decodeID(field.id);
|
|
106
|
-
if ((field.type === "array" || field.type === "object") &&
|
|
107
|
-
isArrayOfObjects(field.children))
|
|
108
|
-
field.children = _addIdToSchema(field.children);
|
|
109
|
-
return field;
|
|
110
|
-
}
|
|
111
|
-
const _addIdToSchema = (schema) => schema.map(_addIdToField);
|
|
112
|
-
return _addIdToSchema(schema);
|
|
113
|
-
};
|
|
114
|
-
export const encodeSchemaID = (schema) => schema.map((field) => ({
|
|
115
|
-
...field,
|
|
116
|
-
id: isNumber(field.id) ? encodeID(field.id) : field.id,
|
|
117
|
-
...(field.children
|
|
118
|
-
? isArrayOfObjects(field.children)
|
|
119
|
-
? {
|
|
120
|
-
children: encodeSchemaID(field.children),
|
|
121
|
-
}
|
|
122
|
-
: { children: field.children }
|
|
123
|
-
: {}),
|
|
124
|
-
}));
|
|
125
73
|
export const hashString = (str) => createHash("sha256").update(str).digest("hex");
|
|
126
74
|
/**
|
|
127
75
|
* Evaluates a comparison between two values based on a specified operator and field types.
|