dbtasker 1.0.0 → 2.5.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/validation.js ADDED
@@ -0,0 +1,1329 @@
1
+ const cstyler = require("cstyler");
2
+ const fncs = require("./function");
3
+ const eng = require("./enginesupport");
4
+
5
+ function validateMySQLComment(comment) {
6
+ const errors = [];
7
+
8
+ // 1. Must be string
9
+ if (typeof comment !== "string") {
10
+ errors.push("Comment is not a string");
11
+ return { valid: false, errors };
12
+ }
13
+
14
+ // 2. Must not contain NULL byte
15
+ if (/[\x00]/.test(comment)) {
16
+ errors.push("Comment contains NULL byte (\\x00)");
17
+ }
18
+
19
+ // 3. Length limit (MySQL: 1024 bytes)
20
+ const byteLength = Buffer.byteLength(comment, "utf8");
21
+ if (byteLength > 1024) {
22
+ errors.push(`Comment exceeds 1024 bytes (found ${byteLength})`);
23
+ }
24
+
25
+ return {
26
+ valid: errors.length === 0,
27
+ errors
28
+ };
29
+ }
30
+ function parseQuotedListSafely(text) {
31
+ if (Array.isArray(text)) return text;
32
+ if (typeof text !== 'string') return [];
33
+
34
+ // Check: does it look like a quoted comma-separated list?
35
+ const isListLike = /^('.*?')(,\s*'.*?')*$/.test(text.trim());
36
+
37
+ if (!isListLike) {
38
+ return [];
39
+ }
40
+
41
+ return text
42
+ .split(",")
43
+ .map(item => item.trim().replace(/^'(.*)'$/, "$1"))
44
+ .filter(item => item.length > 0);
45
+ }
46
+ const mysqlTypeMetadata = {
47
+ // Numeric types
48
+ TINYINT: { lengthType: "int", required: false, query: "TINYINT(3)", supportsUnsigned: true, dataType: "numeric" },
49
+ SMALLINT: { lengthType: "int", required: false, query: "SMALLINT(5)", supportsUnsigned: true, dataType: "numeric" },
50
+ MEDIUMINT: { lengthType: "int", required: false, query: "MEDIUMINT(8)", supportsUnsigned: true, dataType: "numeric" },
51
+ INT: { lengthType: "int", required: false, query: "INT(11)", supportsUnsigned: true, dataType: "numeric" },
52
+ INTEGER: { lengthType: "int", required: false, query: "INTEGER(11)", supportsUnsigned: true, dataType: "numeric" },
53
+ BIGINT: { lengthType: "int", required: false, query: "BIGINT(20)", supportsUnsigned: true, dataType: "numeric" },
54
+ FLOAT: { lengthType: "two-int", required: false, query: "FLOAT(10,2)", supportsUnsigned: true, dataType: "numeric" },
55
+ DOUBLE: { lengthType: "two-int", required: false, query: "DOUBLE(16,4)", supportsUnsigned: true, dataType: "numeric" },
56
+ REAL: { lengthType: "two-int", required: false, query: "REAL(16,4)", supportsUnsigned: true, dataType: "numeric" },
57
+ DECIMAL: { lengthType: "two-int", required: true, query: "DECIMAL(10,2)", supportsUnsigned: true, dataType: "numeric" },
58
+ NUMERIC: { lengthType: "two-int", required: true, query: "NUMERIC(10,2)", supportsUnsigned: true, dataType: "numeric" },
59
+
60
+ // Boolean types
61
+ BOOLEAN: { lengthType: "none", required: false, query: "BOOLEAN", supportsUnsigned: false, dataType: "boolean" },
62
+ BOOL: { lengthType: "none", required: false, query: "BOOL", supportsUnsigned: false, dataType: "boolean" },
63
+
64
+ // Bit type // you can specify how many bits (1–64)
65
+ BIT: { lengthType: "int", required: true, query: "BIT(1)", supportsUnsigned: false, dataType: "bit" },
66
+
67
+ // Date & Time types
68
+ DATE: { lengthType: "none", required: false, query: "DATE", supportsUnsigned: false, dataType: "datetime" },
69
+ TIME: { lengthType: "fsp", required: false, query: "TIME(6)", supportsUnsigned: false, dataType: "datetime" },
70
+ YEAR: { lengthType: "none", required: false, query: "YEAR", supportsUnsigned: false, dataType: "datetime" },
71
+ DATETIME: { lengthType: "fsp", required: false, query: "DATETIME(6)", supportsUnsigned: false, dataType: "datetime" },
72
+ TIMESTAMP: { lengthType: "fsp", required: false, query: "TIMESTAMP(6)", supportsUnsigned: false, dataType: "datetime" },
73
+
74
+ // String types
75
+ CHAR: { lengthType: "int", required: true, query: "CHAR(1)", supportsUnsigned: false, dataType: "string" },
76
+ VARCHAR: { lengthType: "int", required: true, query: "VARCHAR(255)", supportsUnsigned: false, dataType: "string" },
77
+ TINYTEXT: { lengthType: "none", required: false, query: "TINYTEXT", supportsUnsigned: false, dataType: "string" },
78
+ TEXT: { lengthType: "none", required: false, query: "TEXT", supportsUnsigned: false, dataType: "string" },
79
+ MEDIUMTEXT: { lengthType: "none", required: false, query: "MEDIUMTEXT", supportsUnsigned: false, dataType: "string" },
80
+ LONGTEXT: { lengthType: "none", required: false, query: "LONGTEXT", supportsUnsigned: false, dataType: "string" },
81
+ ENUM: { lengthType: "list", required: true, query: "ENUM('option1', 'option2')", supportsUnsigned: false, dataType: "text" },
82
+ SET: { lengthType: "list", required: true, query: "SET('a','b','c')", supportsUnsigned: false, dataType: "text" },
83
+
84
+ // Binary types
85
+ BINARY: { lengthType: "int", required: true, query: "BINARY(1)", supportsUnsigned: false, dataType: "binary" },
86
+ VARBINARY: { lengthType: "int", required: true, query: "VARBINARY(255)", supportsUnsigned: false, dataType: "binary" },
87
+ TINYBLOB: { lengthType: "none", required: false, query: "TINYBLOB", supportsUnsigned: false, dataType: "binary" },
88
+ BLOB: { lengthType: "none", required: false, query: "BLOB", supportsUnsigned: false, dataType: "binary" },
89
+ MEDIUMBLOB: { lengthType: "none", required: false, query: "MEDIUMBLOB", supportsUnsigned: false, dataType: "binary" },
90
+ LONGBLOB: { lengthType: "none", required: false, query: "LONGBLOB", supportsUnsigned: false, dataType: "binary" },
91
+
92
+ // Spatial types
93
+ GEOMETRY: { lengthType: "none", required: false, query: "GEOMETRY", supportsUnsigned: false, dataType: "geometry" },
94
+ POINT: { lengthType: "none", required: false, query: "POINT", supportsUnsigned: false, dataType: "geometry" },
95
+ LINESTRING: { lengthType: "none", required: false, query: "LINESTRING", supportsUnsigned: false, dataType: "geometry" },
96
+ POLYGON: { lengthType: "none", required: false, query: "POLYGON", supportsUnsigned: false, dataType: "geometry" },
97
+ MULTIPOINT: { lengthType: "none", required: false, query: "MULTIPOINT", supportsUnsigned: false, dataType: "geometry" },
98
+ MULTILINESTRING: { lengthType: "none", required: false, query: "MULTILINESTRING", supportsUnsigned: false, dataType: "geometry" },
99
+ MULTIPOLYGON: { lengthType: "none", required: false, query: "MULTIPOLYGON", supportsUnsigned: false, dataType: "geometry" },
100
+ GEOMETRYCOLLECTION: { lengthType: "none", required: false, query: "GEOMETRYCOLLECTION", supportsUnsigned: false, dataType: "geometry" },
101
+
102
+ // JSON
103
+ JSON: { lengthType: "none", required: false, query: "JSON", supportsUnsigned: false, dataType: "json" }
104
+ };
105
+ const validIndexValues = [
106
+ "INDEX",
107
+ "UNIQUE",
108
+ "PRIMARY",
109
+ "PRIMARY KEY",
110
+ "FULLTEXT",
111
+ "SPATIAL"
112
+ ];
113
+ const truers = [true, 1, "1", "true", "True", "TRUE"];
114
+ const falsers = [false, 0, "0", "false", "False", "FALSE"];
115
+ function validateDefault(columnType, defaultValue, length_value, nullable = false) {
116
+ const type = columnType.toUpperCase();
117
+
118
+ // If default is undefined (not explicitly set) → usually valid
119
+ if (defaultValue === undefined) return { valid: true, message: null };
120
+
121
+ // NULL default
122
+ if (defaultValue === null) {
123
+ return nullable
124
+ ? { valid: true, message: null }
125
+ : { valid: false, message: "Column does not allow NULL as default" };
126
+ }
127
+
128
+ // Numeric types
129
+ if (["INT", "BIGINT", "SMALLINT", "TINYINT", "DECIMAL", "NUMERIC", "FLOAT", "DOUBLE", "REAL"].includes(type)) {
130
+ if (typeof defaultValue === "number") return { valid: true, message: null };
131
+ if (typeof defaultValue === "string" && !isNaN(defaultValue)) return { valid: true, message: null };
132
+ return { valid: false, message: "Invalid numeric default value" };
133
+ }
134
+
135
+ // ENUM / SET
136
+ if (["ENUM", "SET"].includes(type)) {
137
+ if (!length_value) return { valid: false, message: "Missing ENUM/SET options" };
138
+ const options = length_value.split(",").map(s => s.trim().replace(/^'(.*)'$/, "$1"));
139
+ if (options.includes(defaultValue)) return { valid: true, message: null };
140
+ return { valid: false, message: `Default value not in ENUM/SET options [${options.join(", ")}]` };
141
+ }
142
+
143
+ // Character types
144
+ if (["CHAR", "VARCHAR"].includes(type)) {
145
+ return typeof defaultValue === "string"
146
+ ? { valid: true, message: null }
147
+ : { valid: false, message: "Default must be a string" };
148
+ }
149
+
150
+ // TEXT types → valid if no default, invalid only if default explicitly set
151
+ if (["TEXT", "TINYTEXT", "MEDIUMTEXT", "LONGTEXT"].includes(type)) {
152
+ return { valid: false, message: "TEXT columns cannot have default values" };
153
+ }
154
+
155
+ // Binary types
156
+ if (["BINARY", "VARBINARY"].includes(type)) {
157
+ return typeof defaultValue === "string" || /^x'[0-9A-Fa-f]+'$/.test(defaultValue)
158
+ ? { valid: true, message: null }
159
+ : { valid: false, message: "Invalid binary default value" };
160
+ }
161
+ if (["BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB"].includes(type)) {
162
+ return { valid: false, message: "BLOB columns cannot have default values" };
163
+ }
164
+
165
+ // Date / Time types
166
+ if (["DATETIME", "TIMESTAMP"].includes(type)) {
167
+ if (typeof defaultValue !== "string") return { valid: false, message: "Default must be a string for DATETIME/TIMESTAMP" };
168
+ if (/^(CURRENT_TIMESTAMP)(\(\d{0,6}\))?$/i.test(defaultValue)) return { valid: true, message: null };
169
+ if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(defaultValue)) return { valid: true, message: null };
170
+ return { valid: false, message: "Invalid DATETIME/TIMESTAMP default format" };
171
+ }
172
+ if (type === "DATE") {
173
+ return /^\d{4}-\d{2}-\d{2}$/.test(defaultValue)
174
+ ? { valid: true, message: null }
175
+ : { valid: false, message: "Invalid DATE default format" };
176
+ }
177
+ if (type === "TIME") {
178
+ return /^\d{2}:\d{2}:\d{2}$/.test(defaultValue)
179
+ ? { valid: true, message: null }
180
+ : { valid: false, message: "Invalid TIME default format" };
181
+ }
182
+ if (type === "YEAR") {
183
+ return /^\d{4}$/.test(defaultValue)
184
+ ? { valid: true, message: null }
185
+ : { valid: false, message: "Invalid YEAR default format" };
186
+ }
187
+
188
+ // BOOLEAN
189
+ if (type === "BOOLEAN") {
190
+ return defaultValue === 0 || defaultValue === 1
191
+ ? { valid: true, message: null }
192
+ : { valid: false, message: "BOOLEAN default must be 0 or 1" };
193
+ }
194
+
195
+ // JSON
196
+ if (type === "JSON") {
197
+ return defaultValue === null || defaultValue === '{}' || defaultValue === '[]'
198
+ ? { valid: true, message: null }
199
+ : { valid: false, message: "JSON columns cannot have this default" };
200
+ }
201
+
202
+ // Unknown types
203
+ return { valid: false, message: "Unknown column type or invalid default" };
204
+ }
205
+
206
+
207
+ async function JSONchecker(table_json, config, seperator = "_") {
208
+ // lets check all table name and column name
209
+ let baddatabaseName = [];
210
+ let badTableNames = [];
211
+ let badColumnNames = [];
212
+ let badtype = [];
213
+ let badautoincrement = [];
214
+ let badindex = [];
215
+ let badnulls = [];
216
+ let baddefaults = [];
217
+ let badlength = [];
218
+ let badforeighkey = [];
219
+ let badcomment = [];
220
+ let badunsigned = [];
221
+ let badzerofill = [];
222
+ let badcharacterset = [];
223
+ let badcollation = [];
224
+ let badcarcol = [];
225
+ let badengine = [];
226
+ console.log("Initializing JSON checking...");
227
+ // get all character set and collate
228
+ let characterSets;
229
+ let collations;
230
+ const getCharsetAndCollations = await fncs.getCharsetAndCollations(config);
231
+ if (fncs.isJsonObject(getCharsetAndCollations)) {
232
+ characterSets = getCharsetAndCollations.characterSets;
233
+ collations = getCharsetAndCollations.collations;
234
+ } else {
235
+ console.error(cstyler.red.bold("There is a problem connecting to the database. Please check database info or connection."));
236
+ return null;
237
+ }
238
+ // get all mysql table engines
239
+ const mysqlEngines = await fncs.getMySQLEngines(config);
240
+ if (!fncs.isJsonObject(mysqlEngines)) {
241
+ console.error(cstyler.red.bold("There is a problem connecting to the database. Please check database info or connection."));
242
+ return null;
243
+ }
244
+ // key variabls
245
+ const charactersetkeys = ['_character_set_', '_characterset_', '_charset_', '_char_set_', 'character_set', 'characterset', 'charset', 'char_set'];
246
+ const collationkeys = ['_collate_', '_collation_', 'collate', 'collation'];
247
+ const enginekey = ["engine", "_engine_", "__engine__"];
248
+ const commetnkey = ["comment", "_comment_", "__comment__"];
249
+ let contentObj = {};
250
+ if (fncs.isJsonObject(table_json)) {
251
+ // lets loop databases
252
+ for (const databaseName of Object.keys(table_json)) {
253
+ if (fncs.perseDatabaseNameWithLoop(databaseName, seperator) === false) {
254
+ baddatabaseName.push(
255
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
256
+ `${cstyler.red('- database name is not valid.')}`
257
+ )
258
+ }
259
+ if (!contentObj[databaseName]) contentObj[databaseName] = {};
260
+ if (fncs.isJsonObject(table_json[databaseName])) {
261
+ // lets loop tables
262
+ for (const tableName of Object.keys(table_json[databaseName])) {
263
+ if (!contentObj[databaseName][tableName]) contentObj[databaseName][tableName] = {};
264
+ let engine = undefined;
265
+ for (const ecolumn of Object.keys(table_json[databaseName][tableName])) {
266
+ if (enginekey.includes(ecolumn.toLowerCase())) {
267
+ engine = table_json[databaseName][tableName][ecolumn];
268
+ }
269
+ }
270
+ if (fncs.isJsonObject(table_json[databaseName][tableName])) {
271
+ if (fncs.perseTableNameWithLoop(tableName, seperator) === false) {
272
+ badTableNames.push(
273
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
274
+ `${cstyler.purple('of table:')} ${cstyler.blue(tableName)} ` +
275
+ `${cstyler.red('- table name is not valid.')}`
276
+ );
277
+ }
278
+ // lets loop columns
279
+ for (const columnName of Object.keys(table_json[databaseName][tableName])) {
280
+ if (fncs.isJsonObject(table_json[databaseName][tableName][columnName])) {
281
+ if (!contentObj[databaseName][tableName][columnName]) contentObj[databaseName][tableName][columnName] = {}
282
+ const deepColumn = table_json[databaseName][tableName][columnName];
283
+ let columntype = undefined;
284
+ let length_value = undefined;
285
+ let autoincrement = undefined;
286
+ let indexes = undefined;
287
+ let nulls = undefined;
288
+ let defaults = undefined;
289
+ let comment = undefined;
290
+ let unsigned = undefined;
291
+ let zerofill = undefined;
292
+ let _charset_ = undefined;
293
+ let _collate_ = undefined;
294
+ /**
295
+ * Lets get variables
296
+ */
297
+ /**
298
+ * type
299
+ * Type
300
+ * TYPE
301
+ * column_type
302
+ * Column_Type
303
+ * columntype
304
+ * ColumnType
305
+ * COLUMNTYPE
306
+ */
307
+ const coltypekeys = ['type', 'columntype', 'column_type', 'datatype', 'data_type', 'typename', 'type_name'];
308
+ for (const item of Object.keys(deepColumn)) {
309
+ if (coltypekeys.includes(item.toLowerCase())) {
310
+ columntype = deepColumn[item];
311
+ break;
312
+ }
313
+ }
314
+ if (typeof columntype !== "string" && columntype !== undefined) {
315
+ columntype = null;
316
+ }
317
+ /**
318
+ * Length_Value
319
+ */
320
+ const legnthkeys = ["lengthvalue", "length_value", 'size', 'scale', 'lengths', 'length', 'value', 'values', 'range', 'maxlength', 'max_length', 'precision'];
321
+ for (const item of Object.keys(deepColumn)) {
322
+ if (legnthkeys.includes(item.toLowerCase())) {
323
+ length_value = deepColumn[item];
324
+ break;
325
+ }
326
+ }
327
+ /**
328
+ * AUTO_INCREMENT
329
+ */
330
+ const autoincrementkeys = ['autoincrement', 'auto_increment', 'increment', 'serial', 'generated', 'isidentity', 'identity']
331
+ for (const item of Object.keys(deepColumn)) {
332
+ if (autoincrementkeys.includes(item.toLowerCase())) {
333
+ autoincrement = deepColumn[item];
334
+ break;
335
+ }
336
+ }
337
+ if (truers.includes(autoincrement)) {
338
+ autoincrement = true;
339
+ } else if (falsers.includes(autoincrement)) {
340
+ autoincrement = false;
341
+ } else if (autoincrement === undefined) {
342
+ autoincrement = undefined;
343
+ } else {
344
+ autoincrement = null;
345
+ }
346
+ /**
347
+ * index
348
+ * INDEX
349
+ * Index
350
+ */
351
+ let indexvalue = undefined;
352
+ const indexkey = ["index", 'indexkey', 'index_key', 'indexing'];
353
+ for (const item of Object.keys(deepColumn)) {
354
+ if (indexkey.includes(item.toLowerCase())) {
355
+ indexes = deepColumn[item];
356
+ break;
357
+ } else if (['primarykey', 'primary_key', 'primary', 'isprimary', 'isprimarykey'].includes(item.toLowerCase())) {
358
+ if (truers.includes(deepColumn[item])) {
359
+ indexes = "PRIMARY KEY";
360
+ break;
361
+ } else {
362
+ indexes = undefined;
363
+ }
364
+ } else if (['isunique', 'isuniquekey', 'uniqueindex', 'uniquekey', 'unique_index', 'unique_key'].includes(item.toLowerCase())) {
365
+ if (truers.includes(deepColumn[item])) {
366
+ indexes = "UNIQUE";
367
+ break;
368
+ } else {
369
+ indexes = undefined;
370
+ }
371
+ } else if (['fulltext', 'isfulltext'].includes(item.toLowerCase())) {
372
+ if (truers.includes(deepColumn[item])) {
373
+ indexes = "FULLTEXT";
374
+ break;
375
+ } else {
376
+ indexes = undefined;
377
+ }
378
+ } else if (['spatial', 'isspatial'].includes(item.toLowerCase())) {
379
+ if (truers.includes(deepColumn[item])) {
380
+ indexes = "SPATIAL";
381
+ break;
382
+ } else {
383
+ indexes = undefined;
384
+ }
385
+ } else if (['index'].includes(item.toLowerCase())) {
386
+ if (truers.includes(deepColumn[item])) {
387
+ indexes = "INDEX";
388
+ break;
389
+ } else {
390
+ indexes = undefined;
391
+ }
392
+ }
393
+ }
394
+ if (indexes !== undefined) { indexes = fncs.stringifyAny(indexes).toUpperCase(); }
395
+ else if (indexes === "PRIMARY") { indexes = "PRIMARY KEY" }
396
+ else if (indexes === "FULL") {
397
+ indexes = "FULLTEXT";
398
+ }
399
+ /**
400
+ * null
401
+ * NULL
402
+ * Null
403
+ */
404
+ const nullkeys = ['null', 'nulls', 'nullable', 'optional', 'isnulable', 'allownull', 'canbenull'];
405
+ for (const item of Object.keys(deepColumn)) {
406
+ if (nullkeys.includes(item.toLowerCase())) {
407
+ if (truers.includes(deepColumn[item])) {
408
+ nulls = true;
409
+ break;
410
+ } else if (falsers.includes(deepColumn[item])) {
411
+ nulls = false;
412
+ break;
413
+ } else {
414
+ nulls = true;
415
+ break;
416
+ }
417
+ } else if (['notnull', 'not_null', 'nonnullable', 'notnullable', 'required', 'disallownull', 'non_nullable', 'not_nullable', 'disallow_null'].includes(item.toLowerCase())) {
418
+ if (truers.includes(deepColumn[item])) {
419
+ nulls = false;
420
+ break;
421
+ } else if (falsers.includes(deepColumn[item])) {
422
+ nulls = true;
423
+ break;
424
+ } else {
425
+ nulls = true;
426
+ break;
427
+ }
428
+ }
429
+ }
430
+ if (truers.includes(nulls)) {
431
+ nulls = true;
432
+ } else if (falsers.includes(nulls)) {
433
+ nulls = false;
434
+ } else if (nulls === undefined) {
435
+ nulls = true;
436
+ } else {
437
+ // lets check bad null
438
+ badnulls.push(
439
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ${cstyler.yellow('NULL')} ${cstyler.red('- must be true or false')}`
440
+ );
441
+ }
442
+ /**
443
+ * COMMENT
444
+ */
445
+ const commentkeys = ['comment', 'comments', 'columncomment', 'column_comment', 'description', 'label', 'helptext', 'hint', 'note'];
446
+ for (const item of Object.keys(deepColumn)) {
447
+ if (commentkeys.includes(item.toLowerCase())) {
448
+ comment = deepColumn[item];
449
+ break;
450
+ }
451
+ }
452
+ /**
453
+ * UNSIGNED
454
+ */
455
+ const unsignekey = ['numericunsigned', 'numeric_unsigned', 'unsigned', 'isunsigned'];
456
+ let signed = undefined;
457
+ for (const item of Object.keys(deepColumn)) {
458
+ if (unsignekey.includes(item.toLowerCase())) {
459
+ if (truers.includes(deepColumn[item])) {
460
+ unsigned = true;
461
+ break;
462
+ } else if (falsers.includes(deepColumn[item])) {
463
+ unsigned = false;
464
+ break;
465
+ } else {
466
+ unsigned = null;
467
+ break;
468
+ }
469
+ } else if (['signed', 'issigned'].includes(item.toLowerCase())) {
470
+ if (truers.includes(deepColumn[item])) {
471
+ unsigned = false;
472
+ break;
473
+ } else if (falsers.includes(deepColumn[item])) {
474
+ unsigned = true;
475
+ break;
476
+ } else {
477
+ unsigned = null;
478
+ break;
479
+ }
480
+ }
481
+ }
482
+ /**
483
+ * DEFAULT
484
+ */
485
+ const defaultkeys = ['default', 'defaults', 'defaultvalue', 'default_value', 'example', 'sample', 'columndefault', 'column_default'];
486
+ for (const item of Object.keys(deepColumn)) {
487
+ if (defaultkeys.includes(item.toLowerCase())) {
488
+ defaults = deepColumn[item];
489
+ break;
490
+ }
491
+ }
492
+ /**
493
+ * ZEROFILL
494
+ */
495
+ const zerofkeys = ['zerofill', 'zero_fill', 'iszerofill', 'zerofillup'];
496
+ for (const item of Object.keys(deepColumn)) {
497
+ if (zerofkeys.includes(item.toLowerCase())) {
498
+ zerofill = deepColumn[item];
499
+ break;
500
+ }
501
+ }
502
+ if (truers.includes(zerofill)) {
503
+ zerofill = true;
504
+ } else if (falsers.includes(zerofill)) {
505
+ zerofill = false;
506
+ } else if (zerofill === undefined) {
507
+ zerofill = undefined;
508
+ } else {
509
+ zerofill = null;
510
+ }
511
+ // Let's work on character set and collate
512
+ for (const item of charactersetkeys) {
513
+ if (deepColumn.hasOwnProperty(item)) {
514
+ _charset_ = deepColumn[item];
515
+ }
516
+ }
517
+ for (const item of collationkeys) {
518
+ if (deepColumn.hasOwnProperty(item)) {
519
+ _collate_ = deepColumn[item];
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Getting variable is ended
525
+ */
526
+ const typeInfo = mysqlTypeMetadata[columntype.toUpperCase()];
527
+
528
+ // lets check column names
529
+ if (!fncs.isValidColumnName(columnName.toLowerCase())) {
530
+ badColumnNames.push(
531
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
532
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
533
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
534
+ `${cstyler.red('- column name is not valid.')}`
535
+ );
536
+ }
537
+ // check type
538
+ const allMySQLColumnTypes = Object.keys(mysqlTypeMetadata);
539
+ if (typeof columntype !== "string") {
540
+ badtype.push(
541
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
542
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
543
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
544
+ `${cstyler.red('- must have type.')}`
545
+ );
546
+ columntype = null;
547
+ } else {
548
+ if (engine !== undefined) {
549
+ if (!eng.isColumnTypeAllowed(engine, columntype.toUpperCase())) {
550
+ badengine.push(
551
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
552
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
553
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
554
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
555
+ `${cstyler.purple('> Type:')} ${cstyler.blue(columntype.toUpperCase())} ` +
556
+ `${cstyler.red('> type is not supported by engine.')}`
557
+ )
558
+ }
559
+ }
560
+ if (!allMySQLColumnTypes.includes(columntype.toUpperCase())) {
561
+ badtype.push(
562
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
563
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
564
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
565
+ `${cstyler.red('> type - must have valid column type.')}`
566
+ );
567
+ columntype = null;
568
+ }
569
+ }
570
+ // check LengthValue
571
+ if (typeInfo !== undefined) {
572
+
573
+ // Check if length is required but missing
574
+ if (typeInfo.required && length_value === undefined) {
575
+ badlength.push(
576
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.red('requires length but none provided.')}`
577
+ );
578
+ } else if (length_value !== undefined) {
579
+ let lenVals = length_value;
580
+ if (fncs.isNumber(lenVals)) {
581
+ lenVals = Number(lenVals);
582
+ }
583
+ if (typeInfo.lengthType === "int") {
584
+ if (!Number.isInteger(lenVals)) {
585
+ badlength.push(
586
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.red('should have a valid integer length')}`
587
+ );
588
+ }
589
+ } else if (typeInfo.lengthType === "two-int") {
590
+ const parsed = parseQuotedListSafely(lenVals);
591
+ if (parsed.length !== 2) {
592
+ badlength.push(
593
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.red('should have two integer values [precision, scale]')}`
594
+ );
595
+ } else {
596
+ const [precision, scale] = parsed;
597
+ if (
598
+ !Number.isInteger(precision) || precision <= 0 || precision > 65 ||
599
+ !Number.isInteger(scale) || scale < 0 || scale > precision
600
+ ) {
601
+ badlength.push(
602
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.red('has invalid precision or scale')}`
603
+ );
604
+ }
605
+ }
606
+ } else if (typeInfo.lengthType === "list") {
607
+ const parsed = parseQuotedListSafely(lenVals);
608
+ if (parsed.length === 0) {
609
+ badlength.push(
610
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.red('should have a valid list of options')}`
611
+ );
612
+ }
613
+ }
614
+ }
615
+ }
616
+ // check auto increment
617
+ if (autoincrement === true && typeInfo.dataType === "numeric") {
618
+ if (typeof indexes === "string") {
619
+ if (typeInfo.dataType !== "numeric" || !['PRIMARY KEY', 'UNIQUE'].includes(indexes) || nulls === true || defaults !== undefined) {
620
+ badautoincrement.push(
621
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
622
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
623
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
624
+ `${cstyler.red('column must be')} ${cstyler.yellow('integer')} ${cstyler.red('type, should be')} ${cstyler.yellow('primary key')} ${cstyler.red('or')} ${cstyler.yellow('unique indexed')}, ` +
625
+ `${cstyler.red('should be')} ${cstyler.yellow('NOT NULL')}, ` +
626
+ `${cstyler.red('can not have a')} ${cstyler.yellow('DEFAULT')} ${cstyler.red('value.')}`
627
+ );
628
+ }
629
+ } else {
630
+ badautoincrement.push(
631
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
632
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
633
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
634
+ `${cstyler.red('a valid')} ${cstyler.yellow('index')} ${cstyler.red('value must be ')}` +
635
+ `${cstyler.yellow('PRIMARY KEY, UNIQUE')} ${cstyler.red('for autoincrement.')}`
636
+ );
637
+ }
638
+ if (engine !== undefined) {
639
+ if (!eng.isEngineFeatureAllowed(engine, 'AutoIncrement')) {
640
+ badengine.push(
641
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
642
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
643
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
644
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
645
+ `${cstyler.red('> Engine - does not support')}` +
646
+ `${cstyler.yellow(' - Autoincrement')}`
647
+ )
648
+ }
649
+ }
650
+ // check multi autoincrement
651
+ let autoincrementcolumnlist = [];
652
+ for (const column of Object.keys(table_json[databaseName][tableName])) {
653
+ const doubleDeepColumn = table_json[databaseName][tableName][column];
654
+ let allautoincrement = undefined;
655
+ for (const item of autoincrementkeys) {
656
+ if (doubleDeepColumn.hasOwnProperty(item)) {
657
+ allautoincrement = doubleDeepColumn[item];
658
+ break;
659
+ }
660
+ }
661
+ if (truers.includes(allautoincrement)) {
662
+ autoincrementcolumnlist.push(column);
663
+ }
664
+ }
665
+ if (autoincrementcolumnlist.length > 1) {
666
+ badautoincrement.push(
667
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
668
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
669
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
670
+ `${cstyler.red('- This table has more than one')} ${cstyler.yellow('auto increment')} ${cstyler.red('column. A table can have only one')} ${cstyler.yellow('auto increment')} ${cstyler.red('column.')}`
671
+ );
672
+ }
673
+ } else if (autoincrement === null) {
674
+ badautoincrement.push(
675
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
676
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
677
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
678
+ `${cstyler.red('- must true or false as valid autoincrement value')}`
679
+ );
680
+ }
681
+ // check unsigned
682
+ if (typeof unsigned === "boolean") {
683
+ // ❌ Invalid use of unsigned on a non-numeric type
684
+ if (typeInfo !== undefined) {
685
+ if (typeInfo.supportsUnsigned === false) {
686
+ badunsigned.push(
687
+ cstyler`{purple Database:} {blue ${databaseName}} ` +
688
+ cstyler`{purple > Table:} {blue ${tableName}} ` +
689
+ cstyler`{purple > Column:} {blue ${columnName}} ` +
690
+ `${cstyler.red(" - has `unsigned` but type ")} ${cstyler.yellow(columntype)} ${cstyler.red(" do not support signed or unsigned modifiers.")}`
691
+ );
692
+ }
693
+ } else {
694
+ badunsigned.push(
695
+ cstyler`{purple Database:} {blue ${databaseName}} ` +
696
+ cstyler`{purple > Table:} {blue ${tableName}} ` +
697
+ cstyler`{purple > Column:} {blue ${columnName}} ` +
698
+ cstyler.red(" - can not validate signed or unsigned modifier with invalid column type")
699
+ );
700
+ }
701
+ } else if (unsigned === null) {
702
+ badunsigned.push(
703
+ cstyler`{purple Database:} {blue ${databaseName}} ` +
704
+ cstyler`{purple > Table:} {blue ${tableName}} ` +
705
+ cstyler`{purple > Column:} {blue ${columnName}} ` +
706
+ cstyler.red(" - has invalid signed or unsigned value")
707
+ );
708
+ }
709
+ // check comment
710
+ if (comment !== undefined) {
711
+ // Invalid comment flags
712
+ const invalids = [];
713
+
714
+ if (typeof comment !== "string") {
715
+ invalids.push(cstyler.red("Not a string"));
716
+ } else {
717
+ if (comment.includes('"')) {
718
+ invalids.push(cstyler.red('Contains double quote (") '));
719
+ }
720
+
721
+ if (comment.includes("'")) {
722
+ invalids.push(cstyler.red("Contains single quote (') "));
723
+ }
724
+
725
+ if (/[\x00]/.test(comment)) {
726
+ invalids.push(cstyler.red("Contains null byte "));
727
+ }
728
+
729
+ if (comment.length > 1024) {
730
+ invalids.push(cstyler.red("Comment too long (exceeds 1024 characters)"));
731
+ }
732
+ }
733
+
734
+ if (invalids.length) {
735
+ badcomment.push(
736
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
737
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
738
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
739
+ `${cstyler.red('- Invalid comment:')} ${invalids.join(cstyler.red(' | '))}`
740
+ );
741
+ }
742
+ }
743
+ // check zerofill
744
+ if (zerofill === true && typeInfo !== undefined) {
745
+ if (!typeInfo.dataType === "numeric") {
746
+ badzerofill.push(
747
+ cstyler`{purple Database:} {blue ${databaseName}} ` +
748
+ cstyler`{purple > Table:} {blue ${tableName}} ` +
749
+ cstyler`{purple > Column:} {blue ${columnName}} ` +
750
+ cstyler.red(" - for `zerofill` column type has to be numeric")
751
+ );
752
+ }
753
+ if (engine !== undefined) {
754
+ if (!eng.isEngineFeatureAllowed(engine, 'ZeroFill')) {
755
+ badengine.push(
756
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
757
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
758
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
759
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
760
+ `${cstyler.red('> Engine - does not support')}` +
761
+ `${cstyler.yellow(' - ZeroFill')}`
762
+ )
763
+ }
764
+ }
765
+ } else if (zerofill === null) {
766
+ badzerofill.push(
767
+ cstyler`{purple Database:} {blue ${databaseName}} ` +
768
+ cstyler`{purple > Table:} {blue ${tableName}} ` +
769
+ cstyler`{purple > Column:} {blue ${columnName}} ` +
770
+ cstyler.red(" - has invalid `zerofill` value and must be boolean or simillar")
771
+ );
772
+ }
773
+ // check index
774
+ if (indexes !== undefined) {
775
+ if (typeof indexes === "string") {
776
+ if (columntype === "JSON") {
777
+ badindex.push(
778
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
779
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
780
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
781
+ `${cstyler.red('- is a JSON column which can not have an ')}${cstyler.yellow('index')} ${cstyler.red('property')}`
782
+ );
783
+ } else if (typeInfo.dataType !== "geometry" && indexes === "SPATIAL" || typeInfo.dataType === "geometry" && indexes !== "SPATIAL") {
784
+ badindex.push(
785
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
786
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
787
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
788
+ `${cstyler.red(' - ')}${cstyler.yellow('SPATIAL - index')} ${cstyler.red('can only be used with ')}${cstyler.yellow('GEOMETRY')} ${cstyler.red('data type and ')}${cstyler.yellow('GEOMETRY')} ${cstyler.red('can only be used with ')}${cstyler.yellow('SPATIAL - index')}`
789
+ );
790
+ } else if (indexes === "FULLTEXT" && typeInfo.dataType !== "string") {
791
+ badindex.push(
792
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
793
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
794
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
795
+ `${cstyler.red(' - ')}${cstyler.yellow('FULLTEXT - index')} ${cstyler.red('can only be used with ')}${cstyler.yellow('CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT')} ${cstyler.red('column types which are string.')}`
796
+ );
797
+ } else if (!validIndexValues.includes(indexes)) {
798
+ console.log(indexes);
799
+ badindex.push(
800
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
801
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
802
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
803
+ `${cstyler.red('- has unsupported index value.')} ` +
804
+ `${cstyler.red('Value must be')} ${cstyler.yellow(validIndexValues.join(', '))}`
805
+ );
806
+ }
807
+
808
+ if (engine !== undefined) {
809
+ if (!eng.isEngineFeatureAllowed(engine, 'Index')) {
810
+ badengine.push(
811
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
812
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
813
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
814
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
815
+ `${cstyler.red('> Engine - does not support')}` +
816
+ `${cstyler.yellow(' - Index')}`
817
+ )
818
+ }
819
+ }
820
+ } else {
821
+ badindex.push(
822
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
823
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
824
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
825
+ `${cstyler.red('- ')}${cstyler.yellow('index')} ${cstyler.red('value must be text or string.')}`
826
+ );
827
+ }
828
+ // check multi autoincrement
829
+ let doubblePrimary = [];
830
+ for (const column of Object.keys(table_json[databaseName][tableName])) {
831
+ const doubleDeepColumn = table_json[databaseName][tableName][column];
832
+ for (const item of indexkey) {
833
+ if (doubleDeepColumn.hasOwnProperty(item)) {
834
+ if (doubleDeepColumn[item].toUpperCase() === "KEY" || doubleDeepColumn[item].toUpperCase() === "PRIMARY KEY")
835
+ doubblePrimary.push(doubleDeepColumn[item]);
836
+ break;
837
+ }
838
+ }
839
+ }
840
+ if (doubblePrimary.length > 1) {
841
+ badindex.push(
842
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
843
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
844
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
845
+ `${cstyler.red('- This table has more than one')} ${cstyler.yellow('PRIMARY KEY')} ${cstyler.red('column. A table can have only one')} ${cstyler.yellow('PRIMARY KEY')} ${cstyler.red('column.')}`
846
+ );
847
+ }
848
+ }
849
+ // Lets work on character set and collat
850
+ if (_charset_ !== undefined && typeInfo !== undefined) {
851
+ if (characterSets.includes(_charset_) && ['text', 'string'].includes(typeInfo.dataType)) {
852
+ contentObj[databaseName][tableName][columnName]._charset_ = _charset_;
853
+ } else if (!['text', 'string'].includes(typeInfo.dataType)) {
854
+ badcharacterset.push(
855
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.purple("> column type:")} ${cstyler.blue(columntype)} ${cstyler.red('can not accept character set and must be a type that accept TEXT or STRING to set a')} ${cstyler.yellow("character set")}`
856
+ );
857
+ } else {
858
+ badcharacterset.push(
859
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.yellow("character set")} ${cstyler.red('value must have a valid value')}`
860
+ );
861
+ }
862
+ }
863
+ if (_collate_ !== undefined && typeInfo !== undefined) {
864
+ if (collations.includes(_collate_) && ['text', 'string'].includes(typeInfo.dataType)) {
865
+ contentObj[databaseName][tableName][columnName]._collate_ = _collate_;
866
+ } else if (!['text', 'string'].includes(typeInfo.dataType)) {
867
+ badcollation.push(
868
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.purple("> column type:")} ${cstyler.blue(columntype)} ${cstyler.red('can not accept collate and must be a type that accept TEXT or STRING to set a')} ${cstyler.yellow("collate")}`
869
+ );
870
+ } else {
871
+ badcollation.push(
872
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ${cstyler.yellow("collate")} ${cstyler.red('value must have a valid value')}`
873
+ );
874
+ }
875
+ }
876
+ if (contentObj[databaseName][tableName][columnName].hasOwnProperty("_collate_") && contentObj[databaseName][tableName][columnName].hasOwnProperty("_charset_")) {
877
+ const isvalid = await fncs.isCharsetCollationValid(config, contentObj[databaseName][tableName][columnName]._charset_, contentObj[databaseName][tableName][columnName]._collate_);
878
+ if (isvalid === false) {
879
+ badcarcol.push(
880
+ `${cstyler.purple("Database:")} ${cstyler.blue(databaseName)} ` +
881
+ `${cstyler.purple("Table:")} ${cstyler.blue(tableName)} ` +
882
+ `${cstyler.purple("Column:")} ${cstyler.blue(columnName)} ` +
883
+ `${cstyler.purple("> Character set:")} ${cstyler.blue(contentObj[databaseName][tableName][columnName]._charset_)} ` +
884
+ `${cstyler.purple("> Collate:")} ${cstyler.blue(contentObj[databaseName][tableName][columnName]._collate_)} ` +
885
+ `${cstyler.red("- is invalid combination")} `
886
+ )
887
+ }
888
+ }
889
+ // lets check default fsp list none
890
+ const result = validateDefault(columntype, defaults, length_value, nulls);
891
+
892
+ if (!result.valid) {
893
+ baddefaults.push(
894
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ` +
895
+ `${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ` +
896
+ `${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ${cstyler.red(result.message)}`
897
+ );
898
+ }
899
+ // lets check bad foreign_key delete and update options
900
+ let deleteOption = undefined;
901
+ let updateOption = undefined;
902
+ let fktable = undefined;
903
+ let fkcolumn = undefined;
904
+ let foreign_key = {};
905
+ const fk_variations = ["fk", "foreign_key", "foreignkey"];
906
+ for (const item of Object.keys(deepColumn)) {
907
+ if (fk_variations.includes(item.toLowerCase())) {
908
+ foreign_key = deepColumn[item];
909
+ break;
910
+ }
911
+ }
912
+ if (fncs.isJsonObject(foreign_key) && Object.keys(foreign_key).length > 0) {
913
+ const validFKSetOption = new Set([null, "NULL", "SET NULL", true, "DL", "DEL", "DELETE", "CASCADE", "DEFAULT", "SET DEFAULT", "RESTRICT", "NO ACTION"]);
914
+ /**
915
+ * CASCADE: Child value is updated to match the new parent value.
916
+ * SET NULL: Child value becomes NULL. Column must allow NULL.
917
+ * SET DEFAULT: Child value is set to the column’s default value.
918
+ * RESTRICT: Prevents update if any matching child exists.
919
+ * NO ACTION: Like RESTRICT (timing differences in some DB engines).
920
+ */
921
+ const deleteVariations = ["delete", "ondelete", "on_delete", "when_Delete", "whenDelete", 'ifdelete', 'if_delete']
922
+ for (const item of Object.keys(foreign_key)) {
923
+ if (deleteVariations.includes(item.toLowerCase())) {
924
+ deleteOption = foreign_key[item];
925
+ if (typeof deleteOption === "string") {
926
+ deleteOption = deleteOption.toUpperCase();
927
+ }
928
+ break;
929
+ }
930
+ }
931
+ // Lets get update options
932
+ const onupdatevariations = ["update", "onupdate", "on_update", "ifupdate", "if_update", "when_update", "whenupdate"];
933
+ for (const item of Object.keys(foreign_key)) {
934
+ if (onupdatevariations.includes(item.toLowerCase())) {
935
+ updateOption = foreign_key[item];
936
+ if (typeof updateOption === "string") {
937
+ updateOption = updateOption.toUpperCase();
938
+ }
939
+ break;
940
+ }
941
+ }
942
+ if (!validFKSetOption.has(deleteOption)) {
943
+ badforeighkey.push(
944
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ` +
945
+ `${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ` +
946
+ `${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ` +
947
+ `${cstyler.blue('foreign_key > delete')} ` +
948
+ `${cstyler.red('must be one of:')} ` +
949
+ `${cstyler.yellow('[true, "DELETE"] > work as > CASCADE, "CASCADE", [null, "NULL"] > work as > "SET NULL", "DEFAULT" > work as > "SET DEFAULT", "RESTRICT", "NO ACTION"')}, ` +
950
+ `${cstyler.red(". You can use lowercase too.")}`
951
+ );
952
+ } else {
953
+ // If DELETE is null (SET NULL), column must allow NULLs
954
+ if ([null, "SET NULL", "NULL"].includes(deleteOption) && nulls !== true) {
955
+ badforeighkey.push(
956
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ` +
957
+ `${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ` +
958
+ `${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ` +
959
+ `${cstyler.blue('foreign_key >')} ` +
960
+ `${cstyler.yellow('delete')} === ${cstyler.yellow('null')} - then column ${cstyler.red('NULL must be true')}`
961
+ );
962
+ }
963
+ // If DELETE is 'set default', column must have a DEFAULT value
964
+ else if (["DEFAULT", "SET DEFAULT"].includes(deleteOption) && defaults === undefined) {
965
+ badforeighkey.push(
966
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
967
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
968
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
969
+ `${cstyler.blue('foreign_key >')} ${cstyler.red("delete === 'set default'")} - then column ${cstyler.red('DEFAULT must be defined')}`
970
+ );
971
+ }
972
+ }
973
+ // check on update
974
+ // null, true, "CASCADE", "SET NULL", "DEFAULT", "SET DEFAULT", "RESTRICT", "NO ACTION"
975
+ if (updateOption !== undefined) {
976
+ if (!validFKSetOption.has(updateOption)) {
977
+ badforeighkey.push(
978
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ` +
979
+ `${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ` +
980
+ `${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ` +
981
+ `${cstyler.blue('foreign_key > ONUPDATE')} ` +
982
+ `${cstyler.red('must be one of:')} ` +
983
+ `${cstyler.yellow('[true, "DELETE"] > work as > CASCADE, "CASCADE", [null, "NULL"] > work as > "SET NULL", "DEFAULT" > work as > "SET DEFAULT", "RESTRICT", "NO ACTION"')}, ` +
984
+ `${cstyler.red(". You can use lowercase too.")}`
985
+ );
986
+
987
+ } else {
988
+ // If ONUPDATE is null (SET NULL), column must allow NULLs
989
+ if ([null, "SET NULL", "NULL"].includes(updateOption) && nulls !== true) {
990
+ badforeighkey.push(
991
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} > ` +
992
+ `${cstyler.purple('Table:')} ${cstyler.blue(tableName)} > ` +
993
+ `${cstyler.purple('Column:')} ${cstyler.blue(columnName)} ` +
994
+ `${cstyler.blue('foreign_key >')} ` +
995
+ `${cstyler.yellow('update set to')} ${cstyler.yellow('null')} - then column ${cstyler.red('must be null true')}`
996
+ );
997
+ }
998
+
999
+ // If DELETE is 'set default', column must have a DEFAULT value
1000
+ else if (["DEFAULT", "SET DEFAULT"].includes(updateOption) && defaults === undefined) {
1001
+ badforeighkey.push(
1002
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
1003
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
1004
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
1005
+ `${cstyler.blue('foreign_key >')} ${cstyler.red("update === 'set default'")} - then column ${cstyler.red('DEFAULT must be defined')}`
1006
+ );
1007
+
1008
+ }
1009
+ }
1010
+ }
1011
+ // check reference table and column
1012
+ // lets add foreign key table to variable
1013
+ const tableKeyVariation = ["table", "fktable", "fk_table", "foreignkeytable", "foreign_key_table"]
1014
+ for (const item of Object.keys(foreign_key)) {
1015
+ if (tableKeyVariation.includes(item.toLowerCase())) {
1016
+ fktable = foreign_key[item];
1017
+ break;
1018
+ }
1019
+ }
1020
+ // lets add foreign key column to variable
1021
+ const columnKeyVariation = ["column", "fkcolumn", "fk_column", "foreignkeycolumn", "foreign_key_column"]
1022
+ for (const item of Object.keys(foreign_key)) {
1023
+ if (columnKeyVariation.includes(item.toLowerCase())) {
1024
+ fkcolumn = foreign_key[item];
1025
+ break;
1026
+ }
1027
+ }
1028
+ // lets work on that
1029
+ if (fktable && fkcolumn) {
1030
+ if (table_json[databaseName].hasOwnProperty(fktable)) {
1031
+ if (!table_json[databaseName][fktable].hasOwnProperty(fkcolumn)) {
1032
+ badforeighkey.push(
1033
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
1034
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
1035
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
1036
+ `${cstyler.purple('foreign_key > references > table > column -')} ${cstyler.yellow.underline(fkcolumn)} ${cstyler.red('do not exist')}`
1037
+ );
1038
+ }
1039
+ } else {
1040
+ badforeighkey.push(`${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Column:')} ${cstyler.blue(`${columnName} > foreign_key > references >`)} ${cstyler.purple('Table:')} ${cstyler.underline.yellow(fktable)} - ${cstyler.red('do not exist')}`)
1041
+ }
1042
+ } else {
1043
+ badforeighkey.push(
1044
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
1045
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
1046
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
1047
+ `${cstyler.blue('foreign_key > references -')} ${cstyler.red('must have a table and column property referancing to referance table column')}`
1048
+ );
1049
+ }
1050
+
1051
+ }
1052
+ // Lets add values to a passing object to use it
1053
+ if (typeof columntype === "string") {
1054
+ contentObj[databaseName][tableName][columnName].columntype = columntype.toUpperCase();
1055
+ }
1056
+ if (length_value) {
1057
+ if (["ENUM", "SET"].includes(fncs.stringifyAny(columntype).toUpperCase())) {
1058
+ length_value = parseQuotedListSafely(length_value);
1059
+ }
1060
+ contentObj[databaseName][tableName][columnName].length_value = length_value;
1061
+ }
1062
+ if (autoincrement === true) {
1063
+ contentObj[databaseName][tableName][columnName].autoincrement = true;
1064
+ }
1065
+ // indexes
1066
+ if (typeof indexes === "string" && validIndexValues.includes(fncs.stringifyAny(indexes).toUpperCase())) {
1067
+ contentObj[databaseName][tableName][columnName].index = indexes;
1068
+ }
1069
+ if (typeof nulls === "boolean") {
1070
+ contentObj[databaseName][tableName][columnName].nulls = nulls;
1071
+
1072
+ if (engine !== undefined) {
1073
+ if (!eng.isEngineFeatureAllowed(engine, 'Null')) {
1074
+ badengine.push(
1075
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
1076
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
1077
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
1078
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
1079
+ `${cstyler.red('> Engine - does not support')}` +
1080
+ `${cstyler.yellow(' - Null')}`
1081
+ )
1082
+ }
1083
+ }
1084
+ }
1085
+ if (typeof defaults === "string" || typeof defaults === "number") {
1086
+ contentObj[databaseName][tableName][columnName].defaults = defaults;
1087
+
1088
+ if (engine !== undefined) {
1089
+ if (!eng.isEngineFeatureAllowed(engine, 'Default')) {
1090
+ badengine.push(
1091
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ` +
1092
+ `${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ` +
1093
+ `${cstyler.purple('> Engine:')} ${cstyler.blue(engine)} ` +
1094
+ `${cstyler.purple('> Column:')} ${cstyler.blue(columnName)} ` +
1095
+ `${cstyler.red('> Engine - does not support')}` +
1096
+ `${cstyler.yellow(' - Default')}`
1097
+ )
1098
+ }
1099
+ }
1100
+ }
1101
+ if (comment !== undefined) {
1102
+ contentObj[databaseName][tableName][columnName].comment = comment;
1103
+ }
1104
+ if (typeof unsigned === "boolean") {
1105
+ contentObj[databaseName][tableName][columnName].unsigned = unsigned;
1106
+ }
1107
+ if (typeof zerofill === "boolean") {
1108
+ contentObj[databaseName][tableName][columnName].zerofill = zerofill;
1109
+ }
1110
+ // foreign key
1111
+ if (deepColumn.hasOwnProperty("foreign_key")) {
1112
+ contentObj[databaseName][tableName][columnName].foreign_key = {};
1113
+ contentObj[databaseName][tableName][columnName].foreign_key.table = fktable;
1114
+ contentObj[databaseName][tableName][columnName].foreign_key.column = fkcolumn;
1115
+ // lets refine
1116
+ if ([true, "DL", "DEL", "DELETE", "CASCADE"].includes(deleteOption)) {
1117
+ deleteOption = "CASCADE";
1118
+ } else if ([null, "NULL", "SET NULL"].includes(deleteOption)) {
1119
+ deleteOption = "SET NULL";
1120
+ } else if (["DEFAULT", "SET DEFAULT"].includes(deleteOption)) {
1121
+ deleteOption = "SET DEFAULT";
1122
+ }
1123
+ if ([true, "DL", "DEL", "DELETE", "CASCADE"].includes(updateOption)) {
1124
+ updateOption = "CASCADE";
1125
+ } else if ([null, "NULL", "SET NULL"].includes(updateOption)) {
1126
+ updateOption = "SET NULL";
1127
+ } else if (["DEFAULT", "SET DEFAULT"].includes(updateOption)) {
1128
+ updateOption = "SET DEFAULT";
1129
+ }
1130
+ if (deleteOption !== undefined) {
1131
+ contentObj[databaseName][tableName][columnName].foreign_key.deleteOption = deleteOption;
1132
+ }
1133
+ if (updateOption !== undefined) {
1134
+ contentObj[databaseName][tableName][columnName].foreign_key.updateOption = updateOption;
1135
+ }
1136
+ }
1137
+ } else {
1138
+ if (charactersetkeys.includes(columnName.toLowerCase())) {
1139
+ const charvalue = table_json[databaseName][tableName][columnName];
1140
+ if (characterSets.includes(charvalue)) {
1141
+ contentObj[databaseName][tableName]._charset_ = charvalue;
1142
+ } else {
1143
+ badcharacterset.push(
1144
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> character set key:')} ${cstyler.blue(columnName)} ${cstyler.red('must have a valid character set value')}`
1145
+ );
1146
+ }
1147
+ } else if (collationkeys.includes(columnName.toLowerCase())) {
1148
+ const colvalue = table_json[databaseName][tableName][columnName];
1149
+ if (collations.includes(colvalue)) {
1150
+ contentObj[databaseName][tableName]._collate_ = colvalue;
1151
+ } else {
1152
+ badcollation.push(
1153
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> collate key:')} ${cstyler.blue(columnName)} ${cstyler.red('must have a valid collate value')}`
1154
+ );
1155
+ }
1156
+ } else if (enginekey.includes(columnName.toLowerCase())) {
1157
+ const engvalue = table_json[databaseName][tableName][columnName];
1158
+ if (Object.keys(mysqlEngines).includes(engvalue)) {
1159
+ if (mysqlEngines[engvalue].support === "YES") {
1160
+ contentObj[databaseName][tableName]._engine_ = engvalue;
1161
+ } else {
1162
+ badengine.push(
1163
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Engine key:')} ${cstyler.blue(columnName)} ${cstyler.purple("Engine name: ")} ${cstyler.blue(engvalue)} ${cstyler.red('- The storage engine exists in MySQL source code but is not available on this server.')}`
1164
+ );
1165
+ }
1166
+ } else {
1167
+ badengine.push(
1168
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> Engine key:')} ${cstyler.blue(columnName)} ${cstyler.purple("Engine name:")} ${cstyler.blue(engvalue)} ${cstyler.red('- must have a valid engine value')}`
1169
+ );
1170
+ }
1171
+ } else if (commetnkey.includes(columnName.toLowerCase())) {
1172
+ const commentval = table_json[databaseName][tableName][columnName];
1173
+ if (!validateMySQLComment(commentval).valid) {
1174
+ badcomment.push(
1175
+ `${cstyler.purple("Database:")} ${cstyler.blue(databaseName)} ` +
1176
+ `${cstyler.purple("> Table:")} ${cstyler.blue(tableName)} ` +
1177
+ `${cstyler.purple("> Table comment:")} ${cstyler.blue(columnName)} ` +
1178
+ `${cstyler.red("- Invalid comment:")} ` +
1179
+ result.errors.map(e => cstyler.red(e)).join(", ")
1180
+ )
1181
+ }
1182
+ } else {
1183
+ badColumnNames.push(
1184
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.purple('> columnName:')} ${cstyler.blue(columnName)} ${cstyler.red('- That column name have some problem with its value')}`
1185
+ )
1186
+ }
1187
+ if (contentObj[databaseName][tableName].hasOwnProperty("_collate_") && contentObj[databaseName][tableName].hasOwnProperty("_charset_")) {
1188
+ const isvalid = await fncs.isCharsetCollationValid(config, contentObj[databaseName][tableName]._charset_, contentObj[databaseName][tableName]._collate_);
1189
+ if (isvalid === false) {
1190
+ badcarcol.push(
1191
+ `${cstyler.purple("Database:")} ${cstyler.blue(databaseName)} ` +
1192
+ `${cstyler.purple("Table:")} ${cstyler.blue(tableName)} ` +
1193
+ `${cstyler.purple("> Character set:")} ${cstyler.blue(contentObj[databaseName][tableName]._charset_)} ` +
1194
+ `${cstyler.purple("> Collate:")} ${cstyler.blue(contentObj[databaseName][tableName]._collate_)} ` +
1195
+ `${cstyler.red("- is invalid combination")} `
1196
+ )
1197
+ }
1198
+ }
1199
+ }
1200
+ }
1201
+ } else {
1202
+ if (charactersetkeys.includes(tableName.toLowerCase())) {
1203
+ const charvalue = table_json[databaseName][tableName];
1204
+ if (characterSets.includes(charvalue)) {
1205
+ contentObj[databaseName]._charset_ = charvalue;
1206
+ } else {
1207
+ badcharacterset.push(
1208
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> character set key:')} ${cstyler.blue(tableName)} ${cstyler.red('must have a valid character set value')}`
1209
+ );
1210
+ }
1211
+ } else if (collationkeys.includes(tableName.toLowerCase())) {
1212
+ const colvalue = table_json[databaseName][tableName];
1213
+ if (collations.includes(colvalue)) {
1214
+ contentObj[databaseName]._collate_ = colvalue;
1215
+ } else {
1216
+ badcollation.push(
1217
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('> collate key:')} ${cstyler.blue(tableName)} ${cstyler.red('must have a valid collate value')}`
1218
+ );
1219
+ }
1220
+ } else if (commetnkey.includes(tableName.toLowerCase())) {
1221
+ const commentval = table_json[databaseName][tableName];
1222
+ if (validateMySQLComment(commentval).valid) {
1223
+ contentObj[databaseName]._comment_ = commentval;
1224
+ } else {
1225
+ badcomment.push(
1226
+ `${cstyler.purple("Database:")} ${cstyler.blue(databaseName)} ` +
1227
+ `${cstyler.purple("> Database comment:")} ${cstyler.blue(tableName)} ` +
1228
+ `${cstyler.red("- Invalid comment:")} ` +
1229
+ result.errors.map(e => cstyler.red(e)).join(", ")
1230
+ )
1231
+ }
1232
+ } else {
1233
+ badTableNames.push(
1234
+ `${cstyler.purple('Database:')} ${cstyler.blue(databaseName)} ${cstyler.purple('Table:')} ${cstyler.blue(tableName)} ${cstyler.red('- That table may have some problem with its property')}`
1235
+ )
1236
+ }
1237
+ if (contentObj[databaseName].hasOwnProperty("_collate_") && contentObj[databaseName].hasOwnProperty("_charset_")) {
1238
+ const isvalid = await fncs.isCharsetCollationValid(config, contentObj[databaseName]._charset_, contentObj[databaseName]._collate_);
1239
+ if (isvalid === false) {
1240
+ badcarcol.push(
1241
+ `${cstyler.purple("Database:")} ${cstyler.blue(databaseName)} ` +
1242
+ `${cstyler.purple("> Character set:")} ${cstyler.blue(contentObj[databaseName]._charset_)} ` +
1243
+ `${cstyler.purple("> Collate:")} ${cstyler.blue(contentObj[databaseName]._collate_)} ` +
1244
+ `${cstyler.red("- is invalid combination")} `
1245
+ )
1246
+ }
1247
+ }
1248
+
1249
+ }
1250
+ }
1251
+ } else {
1252
+ console.error("Tables of database: ", databaseName, " must be in Json format.");
1253
+ return false;
1254
+ }
1255
+ }
1256
+ // Lets return result
1257
+ if (baddatabaseName.length === 0 && badcarcol.length === 0 && badengine.length === 0 && badTableNames.length === 0 && badColumnNames.length === 0 && badcomment.length === 0 && badunsigned.length === 0 && badzerofill.length === 0 && badtype.length === 0 && badindex.length === 0 && badautoincrement.length === 0 && badnulls.length === 0 && baddefaults.length === 0 && badlength.length === 0 && badforeighkey.length === 0 && badcharacterset.length === 0 && badcollation.length === 0) {
1258
+ console.log(cstyler.underline.green("All JSON checking is done | Clear to continue"));
1259
+ return { status: true, data: contentObj };
1260
+ }
1261
+
1262
+ // lets print on the console
1263
+ if (baddatabaseName.length > 0) {
1264
+ console.error(`Database names are not correct. May have reserved words or length is bigger than 64 character. Names are:\n${baddatabaseName.join("\n")}`);
1265
+ }
1266
+ if (badTableNames.length > 0) {
1267
+ console.error(`Table names are not correct: \n${badTableNames.join("\n")}`);
1268
+ }
1269
+ if (badColumnNames.length > 0) {
1270
+ console.error(`Column names are not correct: \n${badColumnNames.join("\n")}`);
1271
+ }
1272
+ if (badtype.length > 0) {
1273
+ console.log(cstyler.yellow("Valid column types:"));
1274
+ console.log(cstyler.dark.yellow(Object.keys(mysqlTypeMetadata).join(", ")));
1275
+ console.error(`Column type are not correct: \n${badtype.join("\n")}`);
1276
+ }
1277
+ if (badlength.length > 0) {
1278
+ console.error(`ENUM values that are not correct: \n${badlength.join("\n")}`);
1279
+ }
1280
+ if (badautoincrement.length > 0) {
1281
+ console.error(`Auto Increment values that are not correct: \n${badautoincrement.join("\n")}`);
1282
+ }
1283
+ if (badindex.length > 0) {
1284
+ console.error(`Index values that are not correct: \n${badindex.join("\n")}`);
1285
+ }
1286
+ if (badunsigned.length > 0) {
1287
+ console.error(`UNSIGNED values that are not correct: \n${badunsigned.join("\n")}`);
1288
+ }
1289
+ if (badnulls.length > 0) {
1290
+ console.error(`NULL values that are not correct: \n${badnulls.join("\n")}`);
1291
+ }
1292
+ if (baddefaults.length > 0) {
1293
+ console.error(`DEFAULT values that are not correct: \n${baddefaults.join("\n")}`);
1294
+ }
1295
+ if (badcomment.length > 0) {
1296
+ console.error(`Comment values that are not correct: \n${badcomment.join("\n")}`);
1297
+ }
1298
+ if (badforeighkey.length > 0) {
1299
+ console.error(`Foreign keys and values that are not correct: \n${badforeighkey.join("\n")}`);
1300
+ }
1301
+ if (badcharacterset.length > 0) {
1302
+ console.log(cstyler.yellow("Valid character sets:"));
1303
+ console.log(cstyler.dark.yellow(characterSets.join(", ")));
1304
+ console.error(`Character sets are not correct: \n${badcharacterset.join("\n")}`);
1305
+ }
1306
+ if (badcollation.length > 0) {
1307
+ console.log(cstyler.yellow("Valid collates:"));
1308
+ console.log(cstyler.dark.yellow(collations.join(", ")));
1309
+ console.error(`Collation are not correct: \n${badcollation.join("\n")}`);
1310
+ }
1311
+ if (badcarcol.length > 0) {
1312
+ console.error(`Character set and Collation combination are not correct: \n${badcarcol.join("\n")}`);
1313
+ }
1314
+ if (badengine.length > 0) {
1315
+ console.log(cstyler.yellow("Valid engines:"));
1316
+ console.log(cstyler.dark.yellow(Object.keys(mysqlEngines).join(", ")));
1317
+ console.error(`Engines are not correct: \n${badengine.join("\n")}`);
1318
+ }
1319
+ console.log(cstyler.red("<<<All JSON checking is done. JSON need correction.>>>"));
1320
+ return false;
1321
+ } else {
1322
+ console.error("Plese provide a valid json file");
1323
+ return false;
1324
+ }
1325
+ }
1326
+ module.exports = {
1327
+ JSONchecker,
1328
+ mysqlTypeMetadata
1329
+ }