inibase 1.6.0 → 1.6.1
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 +2 -1
- package/dist/index.js +30 -103
- package/dist/utils.d.ts +26 -9
- package/dist/utils.js +116 -13
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -77,8 +77,9 @@ export default class Inibase {
|
|
|
77
77
|
private uniqueMap;
|
|
78
78
|
private schemaFileExtension;
|
|
79
79
|
constructor(database: string, mainFolder?: string, language?: ErrorLang);
|
|
80
|
-
private static errorMessages;
|
|
81
80
|
createError(name: ErrorCode, variable?: string | number | (string | number)[]): Error;
|
|
81
|
+
private validateName;
|
|
82
|
+
private validateSchema;
|
|
82
83
|
private getFileExtension;
|
|
83
84
|
private schemaToIdsPath;
|
|
84
85
|
/**
|
package/dist/index.js
CHANGED
|
@@ -40,9 +40,9 @@ export default class Inibase {
|
|
|
40
40
|
uniqueMap;
|
|
41
41
|
schemaFileExtension = process.env.INIBASE_SCHEMA_EXTENSION ?? "json";
|
|
42
42
|
constructor(database, mainFolder = ".", language = "en") {
|
|
43
|
-
Utils.validateName(database);
|
|
44
|
-
this.databasePath = join(mainFolder, database);
|
|
45
43
|
this.language = language;
|
|
44
|
+
this.validateName(database);
|
|
45
|
+
this.databasePath = join(mainFolder, database);
|
|
46
46
|
this.pageInfo = {};
|
|
47
47
|
this.totalItems = new Map();
|
|
48
48
|
this.uniqueMap = new Map();
|
|
@@ -58,87 +58,14 @@ export default class Inibase {
|
|
|
58
58
|
else
|
|
59
59
|
globalConfig.salt = Buffer.from(process.env.INIBASE_SECRET, "hex");
|
|
60
60
|
}
|
|
61
|
-
static errorMessages = {
|
|
62
|
-
en: {
|
|
63
|
-
TABLE_EMPTY: "Table {variable} is empty",
|
|
64
|
-
TABLE_EXISTS: "Table {variable} already exists",
|
|
65
|
-
TABLE_NOT_EXISTS: "Table {variable} doesn't exist",
|
|
66
|
-
NO_SCHEMA: "Table {variable} does't have a schema",
|
|
67
|
-
GROUP_UNIQUE: "Group {variable} should be unique, got duplicated content in {variable}",
|
|
68
|
-
FIELD_UNIQUE: "Field {variable} should be unique, got {variable} instead",
|
|
69
|
-
FIELD_REQUIRED: "Field {variable} is required",
|
|
70
|
-
INVALID_ID: "The given ID(s) is/are not valid(s)",
|
|
71
|
-
INVALID_TYPE: "Expect {variable} to be {variable}, got {variable} instead",
|
|
72
|
-
INVALID_PARAMETERS: "The given parameters are not valid",
|
|
73
|
-
INVALID_REGEX_MATCH: "Field {variable} does not match the expected pattern",
|
|
74
|
-
INVALID_NAME: "Name {variable} is not valid",
|
|
75
|
-
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
76
|
-
? "please run with '--env-file=.env'"
|
|
77
|
-
: "please use dotenv",
|
|
78
|
-
},
|
|
79
|
-
ar: {
|
|
80
|
-
TABLE_EMPTY: "الجدول {variable} فارغ",
|
|
81
|
-
TABLE_EXISTS: "الجدول {variable} موجود بالفعل",
|
|
82
|
-
TABLE_NOT_EXISTS: "الجدول {variable} غير موجود",
|
|
83
|
-
NO_SCHEMA: "الجدول {variable} ليس لديه مخطط",
|
|
84
|
-
GROUP_UNIQUE: "المجموعة {variable} يجب أن تكون فريدة، تم العثور على محتوى مكرر في {variable}",
|
|
85
|
-
FIELD_UNIQUE: "الحقل {variable} يجب أن يكون فريدًا، تم العثور على {variable} بدلاً من ذلك",
|
|
86
|
-
FIELD_REQUIRED: "الحقل {variable} مطلوب",
|
|
87
|
-
INVALID_ID: "المعرف أو المعرفات المقدمة غير صالحة",
|
|
88
|
-
INVALID_TYPE: "من المتوقع أن يكون {variable} من النوع {variable}، لكن تم العثور على {variable} بدلاً من ذلك",
|
|
89
|
-
INVALID_PARAMETERS: "المعلمات المقدمة غير صالحة",
|
|
90
|
-
INVALID_REGEX_MATCH: "الحقل {variable} لا يتطابق مع النمط المتوقع",
|
|
91
|
-
INVALID_NAME: "الاسم {variable} غير صالح",
|
|
92
|
-
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
93
|
-
? "يرجى التشغيل باستخدام '--env-file=.env'"
|
|
94
|
-
: "يرجى استخدام dotenv",
|
|
95
|
-
},
|
|
96
|
-
fr: {
|
|
97
|
-
TABLE_EMPTY: "La table {variable} est vide",
|
|
98
|
-
TABLE_EXISTS: "La table {variable} existe déjà",
|
|
99
|
-
TABLE_NOT_EXISTS: "La table {variable} n'existe pas",
|
|
100
|
-
NO_SCHEMA: "La table {variable} n'a pas de schéma",
|
|
101
|
-
GROUP_UNIQUE: "Le groupe {variable} doit être unique, contenu dupliqué trouvé dans {variable}",
|
|
102
|
-
FIELD_UNIQUE: "Le champ {variable} doit être unique, trouvé {variable} à la place",
|
|
103
|
-
FIELD_REQUIRED: "Le champ {variable} est obligatoire",
|
|
104
|
-
INVALID_ID: "Le(s) ID donné(s) n'est/ne sont pas valide(s)",
|
|
105
|
-
INVALID_TYPE: "Attendu que {variable} soit de type {variable}, mais trouvé {variable} à la place",
|
|
106
|
-
INVALID_PARAMETERS: "Les paramètres donnés ne sont pas valides",
|
|
107
|
-
INVALID_REGEX_MATCH: "Le champ {variable} ne correspond pas au modèle attendu",
|
|
108
|
-
INVALID_NAME: "Le nom {variable} n'est pas valide",
|
|
109
|
-
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
110
|
-
? "veuillez exécuter avec '--env-file=.env'"
|
|
111
|
-
: "veuillez utiliser dotenv",
|
|
112
|
-
},
|
|
113
|
-
es: {
|
|
114
|
-
TABLE_EMPTY: "La tabla {variable} está vacía",
|
|
115
|
-
TABLE_EXISTS: "La tabla {variable} ya existe",
|
|
116
|
-
TABLE_NOT_EXISTS: "La tabla {variable} no existe",
|
|
117
|
-
NO_SCHEMA: "La tabla {variable} no tiene un esquema",
|
|
118
|
-
GROUP_UNIQUE: "El grupo {variable} debe ser único, se encontró contenido duplicado en {variable}",
|
|
119
|
-
FIELD_UNIQUE: "El campo {variable} debe ser único, se encontró {variable} en su lugar",
|
|
120
|
-
FIELD_REQUIRED: "El campo {variable} es obligatorio",
|
|
121
|
-
INVALID_ID: "El/los ID proporcionado(s) no es/son válido(s)",
|
|
122
|
-
INVALID_TYPE: "Se espera que {variable} sea {variable}, pero se encontró {variable} en su lugar",
|
|
123
|
-
INVALID_PARAMETERS: "Los parámetros proporcionados no son válidos",
|
|
124
|
-
INVALID_REGEX_MATCH: "El campo {variable} no coincide con el patrón esperado",
|
|
125
|
-
INVALID_NAME: "El nombre {variable} no es válido",
|
|
126
|
-
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
127
|
-
? "por favor ejecute con '--env-file=.env'"
|
|
128
|
-
: "por favor use dotenv",
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
61
|
createError(name, variable) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
: errorMessage.replaceAll("{variable}", ""));
|
|
140
|
-
error.name = name;
|
|
141
|
-
return error;
|
|
62
|
+
return Utils.createError(this.language, name, variable);
|
|
63
|
+
}
|
|
64
|
+
validateName(name) {
|
|
65
|
+
Utils.validateName(name, this.language);
|
|
66
|
+
}
|
|
67
|
+
validateSchema(schema) {
|
|
68
|
+
Utils.validateSchema(schema, this.language);
|
|
142
69
|
}
|
|
143
70
|
getFileExtension(tableName) {
|
|
144
71
|
let mainExtension = this.fileExtension;
|
|
@@ -169,9 +96,9 @@ export default class Inibase {
|
|
|
169
96
|
* @param {TableConfig} [config]
|
|
170
97
|
*/
|
|
171
98
|
async createTable(tableName, schema, config) {
|
|
172
|
-
|
|
99
|
+
this.validateName(tableName);
|
|
173
100
|
if (schema)
|
|
174
|
-
|
|
101
|
+
this.validateSchema(schema);
|
|
175
102
|
const tablePath = join(this.databasePath, tableName);
|
|
176
103
|
if (await File.isExists(tablePath))
|
|
177
104
|
throw this.createError("TABLE_EXISTS", tableName);
|
|
@@ -220,15 +147,15 @@ export default class Inibase {
|
|
|
220
147
|
* @param {(TableConfig&{name?: string})} [config]
|
|
221
148
|
*/
|
|
222
149
|
async updateTable(tableName, schema, config) {
|
|
223
|
-
|
|
150
|
+
this.validateName(tableName);
|
|
224
151
|
if (config?.name)
|
|
225
|
-
|
|
152
|
+
this.validateName(config.name);
|
|
226
153
|
const table = await this.getTable(tableName);
|
|
227
154
|
if (!table)
|
|
228
155
|
return;
|
|
229
156
|
const tablePath = join(this.databasePath, tableName);
|
|
230
157
|
if (schema) {
|
|
231
|
-
|
|
158
|
+
this.validateSchema(schema);
|
|
232
159
|
// remove id from schema
|
|
233
160
|
schema = schema.filter(({ key }) => !["id", "createdAt", "updatedAt"].includes(key));
|
|
234
161
|
let schemaIdFilePath = "";
|
|
@@ -343,7 +270,7 @@ export default class Inibase {
|
|
|
343
270
|
* @return {*} {Promise<TableObject | undefined>}
|
|
344
271
|
*/
|
|
345
272
|
async getTable(tableName) {
|
|
346
|
-
|
|
273
|
+
this.validateName(tableName);
|
|
347
274
|
const tablePath = join(this.databasePath, tableName);
|
|
348
275
|
if (!(await File.isExists(tablePath)))
|
|
349
276
|
throw this.createError("TABLE_NOT_EXISTS", tableName);
|
|
@@ -363,7 +290,7 @@ export default class Inibase {
|
|
|
363
290
|
return globalConfig[this.databasePath].tables?.get(tableName);
|
|
364
291
|
}
|
|
365
292
|
async getTableSchema(tableName) {
|
|
366
|
-
|
|
293
|
+
this.validateName(tableName);
|
|
367
294
|
const tablePath = join(this.databasePath, tableName);
|
|
368
295
|
let schemaFile;
|
|
369
296
|
let schema;
|
|
@@ -1166,7 +1093,7 @@ export default class Inibase {
|
|
|
1166
1093
|
* @param {string} tableName
|
|
1167
1094
|
*/
|
|
1168
1095
|
async clearCache(tableName) {
|
|
1169
|
-
|
|
1096
|
+
this.validateName(tableName);
|
|
1170
1097
|
const cacheFolderPath = join(this.databasePath, tableName, ".cache");
|
|
1171
1098
|
await rm(cacheFolderPath, { recursive: true, force: true });
|
|
1172
1099
|
await mkdir(cacheFolderPath);
|
|
@@ -1175,7 +1102,7 @@ export default class Inibase {
|
|
|
1175
1102
|
page: 1,
|
|
1176
1103
|
perPage: 15,
|
|
1177
1104
|
}, onlyOne, onlyLinesNumbers, _whereIsLinesNumbers) {
|
|
1178
|
-
|
|
1105
|
+
this.validateName(tableName);
|
|
1179
1106
|
const tablePath = join(this.databasePath, tableName);
|
|
1180
1107
|
// Ensure options.columns is an array
|
|
1181
1108
|
if (options.columns) {
|
|
@@ -1183,7 +1110,7 @@ export default class Inibase {
|
|
|
1183
1110
|
? options.columns
|
|
1184
1111
|
: [options.columns];
|
|
1185
1112
|
for (const column of options.columns)
|
|
1186
|
-
|
|
1113
|
+
this.validateName(column);
|
|
1187
1114
|
if (options.columns.length && !options.columns.includes("id"))
|
|
1188
1115
|
options.columns.push("id");
|
|
1189
1116
|
}
|
|
@@ -1426,12 +1353,12 @@ export default class Inibase {
|
|
|
1426
1353
|
page: 1,
|
|
1427
1354
|
perPage: 15,
|
|
1428
1355
|
};
|
|
1429
|
-
|
|
1356
|
+
this.validateName(tableName);
|
|
1430
1357
|
if (options.columns)
|
|
1431
1358
|
for (const column of (Array.isArray(options.columns)
|
|
1432
1359
|
? options.columns
|
|
1433
1360
|
: [options.columns]))
|
|
1434
|
-
|
|
1361
|
+
this.validateName(column);
|
|
1435
1362
|
const tablePath = join(this.databasePath, tableName);
|
|
1436
1363
|
await this.getTable(tableName);
|
|
1437
1364
|
if (!globalConfig[this.databasePath].tables?.get(tableName)?.schema)
|
|
@@ -1512,12 +1439,12 @@ export default class Inibase {
|
|
|
1512
1439
|
perPage: 15,
|
|
1513
1440
|
}, returnUpdatedData, _whereIsLinesNumbers) {
|
|
1514
1441
|
const renameList = [];
|
|
1515
|
-
|
|
1442
|
+
this.validateName(tableName);
|
|
1516
1443
|
if (options.columns)
|
|
1517
1444
|
for (const column of (Array.isArray(options.columns)
|
|
1518
1445
|
? options.columns
|
|
1519
1446
|
: [options.columns]))
|
|
1520
|
-
|
|
1447
|
+
this.validateName(column);
|
|
1521
1448
|
const tablePath = join(this.databasePath, tableName);
|
|
1522
1449
|
await this.throwErrorIfTableEmpty(tableName);
|
|
1523
1450
|
let clonedData = structuredClone(data);
|
|
@@ -1632,7 +1559,7 @@ export default class Inibase {
|
|
|
1632
1559
|
* @return {boolean | null} {(Promise<boolean | null>)}
|
|
1633
1560
|
*/
|
|
1634
1561
|
async delete(tableName, where, _whereIsLinesNumbers) {
|
|
1635
|
-
|
|
1562
|
+
this.validateName(tableName);
|
|
1636
1563
|
const tablePath = join(this.databasePath, tableName);
|
|
1637
1564
|
await this.throwErrorIfTableEmpty(tableName);
|
|
1638
1565
|
if (!where) {
|
|
@@ -1726,11 +1653,11 @@ export default class Inibase {
|
|
|
1726
1653
|
return false;
|
|
1727
1654
|
}
|
|
1728
1655
|
async sum(tableName, columns, where) {
|
|
1729
|
-
|
|
1656
|
+
this.validateName(tableName);
|
|
1730
1657
|
if (!Array.isArray(columns))
|
|
1731
1658
|
columns = [columns];
|
|
1732
1659
|
for (const column of columns)
|
|
1733
|
-
|
|
1660
|
+
this.validateName(column);
|
|
1734
1661
|
await this.throwErrorIfTableEmpty(tableName);
|
|
1735
1662
|
const RETURN = {};
|
|
1736
1663
|
const tablePath = join(this.databasePath, tableName);
|
|
@@ -1750,11 +1677,11 @@ export default class Inibase {
|
|
|
1750
1677
|
return columns.length > 1 ? RETURN : Object.values(RETURN)[0];
|
|
1751
1678
|
}
|
|
1752
1679
|
async max(tableName, columns, where) {
|
|
1753
|
-
|
|
1680
|
+
this.validateName(tableName);
|
|
1754
1681
|
if (!Array.isArray(columns))
|
|
1755
1682
|
columns = [columns];
|
|
1756
1683
|
for (const column of columns)
|
|
1757
|
-
|
|
1684
|
+
this.validateName(column);
|
|
1758
1685
|
const RETURN = {};
|
|
1759
1686
|
const tablePath = join(this.databasePath, tableName);
|
|
1760
1687
|
await this.throwErrorIfTableEmpty(tableName);
|
|
@@ -1774,11 +1701,11 @@ export default class Inibase {
|
|
|
1774
1701
|
return RETURN;
|
|
1775
1702
|
}
|
|
1776
1703
|
async min(tableName, columns, where) {
|
|
1777
|
-
|
|
1704
|
+
this.validateName(tableName);
|
|
1778
1705
|
if (!Array.isArray(columns))
|
|
1779
1706
|
columns = [columns];
|
|
1780
1707
|
for (const column of columns)
|
|
1781
|
-
|
|
1708
|
+
this.validateName(column);
|
|
1782
1709
|
const RETURN = {};
|
|
1783
1710
|
const tablePath = join(this.databasePath, tableName);
|
|
1784
1711
|
await this.throwErrorIfTableEmpty(tableName);
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComparisonOperator, Field, FieldType, Schema } from "./index.js";
|
|
1
|
+
import type { ComparisonOperator, ErrorCode, ErrorLang, Field, FieldType, Schema } from "./index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Type guard function to check if the input is an array of objects.
|
|
4
4
|
*
|
|
@@ -218,16 +218,31 @@ export declare const findLastIdNumber: (schema: Schema) => number;
|
|
|
218
218
|
export declare function addIdToSchema(schema: Schema, startWithID: {
|
|
219
219
|
value: number;
|
|
220
220
|
}): Field[];
|
|
221
|
+
/**
|
|
222
|
+
* Translated error messages for every supported language and error code.
|
|
223
|
+
* The `{variable}` placeholder is replaced with the relevant value by
|
|
224
|
+
* {@link createError}.
|
|
225
|
+
*/
|
|
226
|
+
export declare const ERROR_MESSAGES: Record<ErrorLang, Record<ErrorCode, string>>;
|
|
227
|
+
/**
|
|
228
|
+
* Creates a translated error exactly like the ones thrown by Inibase methods.
|
|
229
|
+
*
|
|
230
|
+
* @param language - The language to render the error message in.
|
|
231
|
+
* @param name - The error code, also used as the error `name`.
|
|
232
|
+
* @param variable - Optional value(s) used to fill the `{variable}` placeholders.
|
|
233
|
+
* @returns An `Error` whose `name` is the error code and `message` is translated.
|
|
234
|
+
*/
|
|
235
|
+
export declare const createError: (language: ErrorLang, name: ErrorCode, variable?: string | number | (string | number)[]) => Error;
|
|
221
236
|
/**
|
|
222
237
|
* Validates that a string is a safe name for a table, database or column.
|
|
223
238
|
*
|
|
224
|
-
* Names must
|
|
225
|
-
*
|
|
226
|
-
* 255 characters long.
|
|
239
|
+
* Names must start with an alphanumeric character (Latin or Arabic), followed
|
|
240
|
+
* by alphanumerics (Latin or Arabic), underscores, hyphens or spaces, and be
|
|
241
|
+
* at most 255 characters long. Leading or trailing spaces are not allowed.
|
|
227
242
|
*
|
|
228
243
|
* This prevents path traversal (`../`, `..\\`), null-byte injection (`\0`),
|
|
229
|
-
* shell injection (`;`, `|`, backticks, `$()`,
|
|
230
|
-
* reserved-name issues.
|
|
244
|
+
* shell injection (`;`, `|`, backticks, `$()`, tabs, newlines, slashes) and
|
|
245
|
+
* other reserved-name issues.
|
|
231
246
|
*
|
|
232
247
|
* @param input - The value to be checked.
|
|
233
248
|
* @returns boolean - True if the name is safe to use, false otherwise.
|
|
@@ -235,16 +250,18 @@ export declare function addIdToSchema(schema: Schema, startWithID: {
|
|
|
235
250
|
export declare const isValidName: (input: unknown) => input is string;
|
|
236
251
|
/**
|
|
237
252
|
* Validates that a string is a safe name for a table, database or column and
|
|
238
|
-
* throws
|
|
253
|
+
* throws a translated `INVALID_NAME` error if it is not.
|
|
239
254
|
*
|
|
240
255
|
* @param name - The name to validate.
|
|
256
|
+
* @param language - The language to render the error message in.
|
|
241
257
|
* @throws {Error} If the name is not a safe name.
|
|
242
258
|
*/
|
|
243
|
-
export declare const validateName: (name: string) => void;
|
|
259
|
+
export declare const validateName: (name: string, language?: ErrorLang) => void;
|
|
244
260
|
/**
|
|
245
261
|
* Recursively validates every field key of a schema.
|
|
246
262
|
*
|
|
247
263
|
* @param schema - The schema to validate.
|
|
264
|
+
* @param language - The language to render the error message in.
|
|
248
265
|
* @throws {Error} If any field key is not a safe name.
|
|
249
266
|
*/
|
|
250
|
-
export declare const validateSchema: (schema: Schema) => void;
|
|
267
|
+
export declare const validateSchema: (schema: Schema, language?: ErrorLang) => void;
|
package/dist/utils.js
CHANGED
|
@@ -628,16 +628,111 @@ export function addIdToSchema(schema, startWithID) {
|
|
|
628
628
|
const addIdToSchemaHelper = (schema) => schema.map(addIdToField);
|
|
629
629
|
return addIdToSchemaHelper(clonedSchema);
|
|
630
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* Translated error messages for every supported language and error code.
|
|
633
|
+
* The `{variable}` placeholder is replaced with the relevant value by
|
|
634
|
+
* {@link createError}.
|
|
635
|
+
*/
|
|
636
|
+
export const ERROR_MESSAGES = {
|
|
637
|
+
en: {
|
|
638
|
+
TABLE_EMPTY: "Table {variable} is empty",
|
|
639
|
+
TABLE_EXISTS: "Table {variable} already exists",
|
|
640
|
+
TABLE_NOT_EXISTS: "Table {variable} doesn't exist",
|
|
641
|
+
NO_SCHEMA: "Table {variable} does't have a schema",
|
|
642
|
+
GROUP_UNIQUE: "Group {variable} should be unique, got duplicated content in {variable}",
|
|
643
|
+
FIELD_UNIQUE: "Field {variable} should be unique, got {variable} instead",
|
|
644
|
+
FIELD_REQUIRED: "Field {variable} is required",
|
|
645
|
+
INVALID_ID: "The given ID(s) is/are not valid(s)",
|
|
646
|
+
INVALID_TYPE: "Expect {variable} to be {variable}, got {variable} instead",
|
|
647
|
+
INVALID_PARAMETERS: "The given parameters are not valid",
|
|
648
|
+
INVALID_REGEX_MATCH: "Field {variable} does not match the expected pattern",
|
|
649
|
+
INVALID_NAME: "Name {variable} is not valid",
|
|
650
|
+
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
651
|
+
? "please run with '--env-file=.env'"
|
|
652
|
+
: "please use dotenv",
|
|
653
|
+
},
|
|
654
|
+
ar: {
|
|
655
|
+
TABLE_EMPTY: "الجدول {variable} فارغ",
|
|
656
|
+
TABLE_EXISTS: "الجدول {variable} موجود بالفعل",
|
|
657
|
+
TABLE_NOT_EXISTS: "الجدول {variable} غير موجود",
|
|
658
|
+
NO_SCHEMA: "الجدول {variable} ليس لديه مخطط",
|
|
659
|
+
GROUP_UNIQUE: "المجموعة {variable} يجب أن تكون فريدة، تم العثور على محتوى مكرر في {variable}",
|
|
660
|
+
FIELD_UNIQUE: "الحقل {variable} يجب أن يكون فريدًا، تم العثور على {variable} بدلاً من ذلك",
|
|
661
|
+
FIELD_REQUIRED: "الحقل {variable} مطلوب",
|
|
662
|
+
INVALID_ID: "المعرف أو المعرفات المقدمة غير صالحة",
|
|
663
|
+
INVALID_TYPE: "من المتوقع أن يكون {variable} من النوع {variable}، لكن تم العثور على {variable} بدلاً من ذلك",
|
|
664
|
+
INVALID_PARAMETERS: "المعلمات المقدمة غير صالحة",
|
|
665
|
+
INVALID_REGEX_MATCH: "الحقل {variable} لا يتطابق مع النمط المتوقع",
|
|
666
|
+
INVALID_NAME: "الاسم {variable} غير صالح",
|
|
667
|
+
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
668
|
+
? "يرجى التشغيل باستخدام '--env-file=.env'"
|
|
669
|
+
: "يرجى استخدام dotenv",
|
|
670
|
+
},
|
|
671
|
+
fr: {
|
|
672
|
+
TABLE_EMPTY: "La table {variable} est vide",
|
|
673
|
+
TABLE_EXISTS: "La table {variable} existe déjà",
|
|
674
|
+
TABLE_NOT_EXISTS: "La table {variable} n'existe pas",
|
|
675
|
+
NO_SCHEMA: "La table {variable} n'a pas de schéma",
|
|
676
|
+
GROUP_UNIQUE: "Le groupe {variable} doit être unique, contenu dupliqué trouvé dans {variable}",
|
|
677
|
+
FIELD_UNIQUE: "Le champ {variable} doit être unique, trouvé {variable} à la place",
|
|
678
|
+
FIELD_REQUIRED: "Le champ {variable} est obligatoire",
|
|
679
|
+
INVALID_ID: "Le(s) ID donné(s) n'est/ne sont pas valide(s)",
|
|
680
|
+
INVALID_TYPE: "Attendu que {variable} soit de type {variable}, mais trouvé {variable} à la place",
|
|
681
|
+
INVALID_PARAMETERS: "Les paramètres donnés ne sont pas valides",
|
|
682
|
+
INVALID_REGEX_MATCH: "Le champ {variable} ne correspond pas au modèle attendu",
|
|
683
|
+
INVALID_NAME: "Le nom {variable} n'est pas valide",
|
|
684
|
+
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
685
|
+
? "veuillez exécuter avec '--env-file=.env'"
|
|
686
|
+
: "veuillez utiliser dotenv",
|
|
687
|
+
},
|
|
688
|
+
es: {
|
|
689
|
+
TABLE_EMPTY: "La tabla {variable} está vacía",
|
|
690
|
+
TABLE_EXISTS: "La tabla {variable} ya existe",
|
|
691
|
+
TABLE_NOT_EXISTS: "La tabla {variable} no existe",
|
|
692
|
+
NO_SCHEMA: "La tabla {variable} no tiene un esquema",
|
|
693
|
+
GROUP_UNIQUE: "El grupo {variable} debe ser único, se encontró contenido duplicado en {variable}",
|
|
694
|
+
FIELD_UNIQUE: "El campo {variable} debe ser único, se encontró {variable} en su lugar",
|
|
695
|
+
FIELD_REQUIRED: "El campo {variable} es obligatorio",
|
|
696
|
+
INVALID_ID: "El/los ID proporcionado(s) no es/son válido(s)",
|
|
697
|
+
INVALID_TYPE: "Se espera que {variable} sea {variable}, pero se encontró {variable} en su lugar",
|
|
698
|
+
INVALID_PARAMETERS: "Los parámetros proporcionados no son válidos",
|
|
699
|
+
INVALID_REGEX_MATCH: "El campo {variable} no coincide con el patrón esperado",
|
|
700
|
+
INVALID_NAME: "El nombre {variable} no es válido",
|
|
701
|
+
NO_ENV: Number(process.versions.node.split(".").reduce((a, b) => a + b)) >= 26
|
|
702
|
+
? "por favor ejecute con '--env-file=.env'"
|
|
703
|
+
: "por favor use dotenv",
|
|
704
|
+
},
|
|
705
|
+
};
|
|
706
|
+
/**
|
|
707
|
+
* Creates a translated error exactly like the ones thrown by Inibase methods.
|
|
708
|
+
*
|
|
709
|
+
* @param language - The language to render the error message in.
|
|
710
|
+
* @param name - The error code, also used as the error `name`.
|
|
711
|
+
* @param variable - Optional value(s) used to fill the `{variable}` placeholders.
|
|
712
|
+
* @returns An `Error` whose `name` is the error code and `message` is translated.
|
|
713
|
+
*/
|
|
714
|
+
export const createError = (language, name, variable) => {
|
|
715
|
+
const errorMessage = ERROR_MESSAGES[language]?.[name];
|
|
716
|
+
if (!errorMessage)
|
|
717
|
+
return new Error("ERR");
|
|
718
|
+
const error = new Error(variable
|
|
719
|
+
? Array.isArray(variable)
|
|
720
|
+
? errorMessage.replace(/\{variable\}/g, () => variable.shift()?.toString() ?? "")
|
|
721
|
+
: errorMessage.replaceAll("{variable}", `'${variable.toString()}'`)
|
|
722
|
+
: errorMessage.replaceAll("{variable}", ""));
|
|
723
|
+
error.name = name;
|
|
724
|
+
return error;
|
|
725
|
+
};
|
|
631
726
|
/**
|
|
632
727
|
* Validates that a string is a safe name for a table, database or column.
|
|
633
728
|
*
|
|
634
|
-
* Names must
|
|
635
|
-
*
|
|
636
|
-
* 255 characters long.
|
|
729
|
+
* Names must start with an alphanumeric character (Latin or Arabic), followed
|
|
730
|
+
* by alphanumerics (Latin or Arabic), underscores, hyphens or spaces, and be
|
|
731
|
+
* at most 255 characters long. Leading or trailing spaces are not allowed.
|
|
637
732
|
*
|
|
638
733
|
* This prevents path traversal (`../`, `..\\`), null-byte injection (`\0`),
|
|
639
|
-
* shell injection (`;`, `|`, backticks, `$()`,
|
|
640
|
-
* reserved-name issues.
|
|
734
|
+
* shell injection (`;`, `|`, backticks, `$()`, tabs, newlines, slashes) and
|
|
735
|
+
* other reserved-name issues.
|
|
641
736
|
*
|
|
642
737
|
* @param input - The value to be checked.
|
|
643
738
|
* @returns boolean - True if the name is safe to use, false otherwise.
|
|
@@ -645,30 +740,38 @@ export function addIdToSchema(schema, startWithID) {
|
|
|
645
740
|
export const isValidName = (input) => typeof input === "string" &&
|
|
646
741
|
input.length > 0 &&
|
|
647
742
|
input.length <= 255 &&
|
|
648
|
-
|
|
743
|
+
validNamePattern.test(input);
|
|
744
|
+
// Word characters: Latin alphanumerics, underscores, hyphens and Arabic blocks.
|
|
745
|
+
const nameWordCharClass = "a-zA-Z0-9_\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF-";
|
|
746
|
+
// Leading characters: same as word chars minus underscore and hyphen.
|
|
747
|
+
const nameFirstCharClass = "a-zA-Z0-9\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF";
|
|
748
|
+
// eslint-disable-next-line no-misleading-character-class
|
|
749
|
+
const validNamePattern = new RegExp(`^[${nameFirstCharClass}](?:[${nameWordCharClass} ]*[${nameWordCharClass}])?$`);
|
|
649
750
|
/**
|
|
650
751
|
* Validates that a string is a safe name for a table, database or column and
|
|
651
|
-
* throws
|
|
752
|
+
* throws a translated `INVALID_NAME` error if it is not.
|
|
652
753
|
*
|
|
653
754
|
* @param name - The name to validate.
|
|
755
|
+
* @param language - The language to render the error message in.
|
|
654
756
|
* @throws {Error} If the name is not a safe name.
|
|
655
757
|
*/
|
|
656
|
-
export const validateName = (name) => {
|
|
758
|
+
export const validateName = (name, language = "en") => {
|
|
657
759
|
if (!isValidName(name))
|
|
658
|
-
throw
|
|
760
|
+
throw createError(language, "INVALID_NAME", name);
|
|
659
761
|
};
|
|
660
762
|
/**
|
|
661
763
|
* Recursively validates every field key of a schema.
|
|
662
764
|
*
|
|
663
765
|
* @param schema - The schema to validate.
|
|
766
|
+
* @param language - The language to render the error message in.
|
|
664
767
|
* @throws {Error} If any field key is not a safe name.
|
|
665
768
|
*/
|
|
666
|
-
export const validateSchema = (schema) => {
|
|
769
|
+
export const validateSchema = (schema, language = "en") => {
|
|
667
770
|
for (const field of schema) {
|
|
668
|
-
validateName(field.key);
|
|
771
|
+
validateName(field.key, language);
|
|
669
772
|
if (field.table)
|
|
670
|
-
validateName(field.table);
|
|
773
|
+
validateName(field.table, language);
|
|
671
774
|
if (field.children && isArrayOfObjects(field.children))
|
|
672
|
-
validateSchema(field.children);
|
|
775
|
+
validateSchema(field.children, language);
|
|
673
776
|
}
|
|
674
777
|
};
|