@andymic/pigeon 1.4.2 → 1.6.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/package.json +3 -3
- package/src/index.js +271 -213
- package/src/maps.js +49 -48
- package/src/pgAdmin.js +38 -47
- package/src/utils.js +42 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andymic/pigeon",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"author": "Andreas Michael <ateasm03@gmail.com>",
|
|
5
5
|
"description": "Pigeon is a TypeScript-based tool for generating TypeScript classes and methods from PostgreSQL database schemas.",
|
|
6
6
|
"keywords": [
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"meow": "^13.2.0",
|
|
35
|
-
"pg": "^8.
|
|
35
|
+
"pg": "^8.16.0",
|
|
36
36
|
"prompt-sync": "^4.2.0"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "6562b7ff32a6a9dd9f0ef108026c198db32b0aa9"
|
|
39
39
|
}
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { arrayMaker,
|
|
1
|
+
import { arrayMaker, getCombinations, getJSType, getPGType, nameBeautifier, queryMaker, runQuery, singularize, sleep, tabsInserter } from "./utils.js";
|
|
2
2
|
import prompt from "prompt-sync";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import * as path from "node:path";
|
|
@@ -27,20 +27,46 @@ export class Database {
|
|
|
27
27
|
this.pass = pass;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
export class Column {
|
|
31
|
+
name;
|
|
32
|
+
position;
|
|
33
|
+
defaultValue;
|
|
34
|
+
isNullable;
|
|
35
|
+
jsType;
|
|
36
|
+
pgType;
|
|
37
|
+
isIdentity;
|
|
38
|
+
identityGeneration;
|
|
39
|
+
isPrimary;
|
|
40
|
+
isUnique;
|
|
41
|
+
isForeign;
|
|
42
|
+
foreignSchema;
|
|
43
|
+
foreignTable;
|
|
44
|
+
foreignColumn;
|
|
45
|
+
constructor(name, position, defaultValue, isNullable, jsType, pgType, isIdentity, identityGeneration, isPrimary, isUnique, isForeign, foreignSchema, foreignTable, foreignColumn) {
|
|
46
|
+
this.name = name;
|
|
47
|
+
this.position = position;
|
|
48
|
+
this.defaultValue = defaultValue;
|
|
49
|
+
this.isNullable = isNullable;
|
|
50
|
+
this.jsType = jsType;
|
|
51
|
+
this.pgType = pgType;
|
|
52
|
+
this.isIdentity = isIdentity;
|
|
53
|
+
this.identityGeneration = identityGeneration;
|
|
54
|
+
this.isPrimary = isPrimary;
|
|
55
|
+
this.isUnique = isUnique;
|
|
56
|
+
this.isForeign = isForeign;
|
|
57
|
+
this.foreignSchema = foreignSchema;
|
|
58
|
+
this.foreignTable = foreignTable;
|
|
59
|
+
this.foreignColumn = foreignColumn;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
30
62
|
export class Table {
|
|
31
|
-
|
|
32
|
-
|
|
63
|
+
name;
|
|
64
|
+
schema;
|
|
33
65
|
columns = [];
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
constructor(table_schema, table_name, columns, primaryKey, foreignKeys, unique) {
|
|
38
|
-
this.table_schema = table_schema;
|
|
39
|
-
this.table_name = table_name;
|
|
66
|
+
constructor(name, schema, columns) {
|
|
67
|
+
this.name = name;
|
|
68
|
+
this.schema = schema;
|
|
40
69
|
this.columns = columns;
|
|
41
|
-
this.primaryKey = primaryKey;
|
|
42
|
-
this.foreignKeys = foreignKeys;
|
|
43
|
-
this.unique = unique;
|
|
44
70
|
}
|
|
45
71
|
}
|
|
46
72
|
export class Enum {
|
|
@@ -51,54 +77,6 @@ export class Enum {
|
|
|
51
77
|
this.labels = labels;
|
|
52
78
|
}
|
|
53
79
|
}
|
|
54
|
-
export class ColumnQueryRow {
|
|
55
|
-
column_name;
|
|
56
|
-
ordinal_position;
|
|
57
|
-
column_default;
|
|
58
|
-
is_nullable;
|
|
59
|
-
data_type;
|
|
60
|
-
udt_name;
|
|
61
|
-
is_identity;
|
|
62
|
-
identity_generation;
|
|
63
|
-
constructor(column_name, ordinal_position, column_default, is_nullable, data_type, udt_name, is_identity, identity_generation) {
|
|
64
|
-
this.column_name = column_name;
|
|
65
|
-
this.ordinal_position = ordinal_position;
|
|
66
|
-
this.column_default = column_default;
|
|
67
|
-
this.is_nullable = is_nullable;
|
|
68
|
-
this.data_type = data_type;
|
|
69
|
-
this.udt_name = udt_name;
|
|
70
|
-
this.is_identity = is_identity;
|
|
71
|
-
this.identity_generation = identity_generation;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
export class PrimaryKeyQueryRow {
|
|
75
|
-
column_name;
|
|
76
|
-
constructor(column_name) {
|
|
77
|
-
this.column_name = column_name;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export class ForeignKeyQueryRow {
|
|
81
|
-
local_schema;
|
|
82
|
-
local_table;
|
|
83
|
-
local_column;
|
|
84
|
-
foreign_schema;
|
|
85
|
-
foreign_table;
|
|
86
|
-
foreign_column;
|
|
87
|
-
constructor(local_schema, local_table, local_column, foreign_schema, foreign_table, foreign_column) {
|
|
88
|
-
this.local_schema = local_schema;
|
|
89
|
-
this.local_table = local_table;
|
|
90
|
-
this.local_column = local_column;
|
|
91
|
-
this.foreign_schema = foreign_schema;
|
|
92
|
-
this.foreign_table = foreign_table;
|
|
93
|
-
this.foreign_column = foreign_column;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
export class UniqueQueryRow {
|
|
97
|
-
columns;
|
|
98
|
-
constructor(columns) {
|
|
99
|
-
this.columns = columns;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
80
|
function createDir(dirPath) {
|
|
103
81
|
if (fs.existsSync(dirPath))
|
|
104
82
|
return new PigeonError(1, "", new Error("Generation directory already exists. Add the --force flag if you want to overwrite it."));
|
|
@@ -210,6 +188,10 @@ export async function queryDB(db) {
|
|
|
210
188
|
AND tc.table_name = $2::varchar;`, [table.table_schema, table.table_name], db);
|
|
211
189
|
if (typeof pKeyQuery === "undefined")
|
|
212
190
|
return new PigeonError(1, "", new Error("An SQL error has occurred."));
|
|
191
|
+
for (const pKey of pKeyQuery.rows)
|
|
192
|
+
for (const column of columnQuery.rows)
|
|
193
|
+
if (pKey.column_name === column.column_name)
|
|
194
|
+
column.isPrimary = true;
|
|
213
195
|
const fKeyQuery = await runQuery(`SELECT kcu1.table_schema AS local_schema,
|
|
214
196
|
kcu1.table_name AS local_table,
|
|
215
197
|
kcu1.column_name AS local_column,
|
|
@@ -231,6 +213,16 @@ export async function queryDB(db) {
|
|
|
231
213
|
AND kcu1.table_name = $2::varchar;`, [table.table_schema, table.table_name], db);
|
|
232
214
|
if (typeof fKeyQuery === "undefined")
|
|
233
215
|
return new PigeonError(1, "", new Error("An SQL error has occurred."));
|
|
216
|
+
for (const fKey of fKeyQuery.rows) {
|
|
217
|
+
for (const column of columnQuery.rows) {
|
|
218
|
+
if (fKey.local_schema === table.table_schema && fKey.local_table === table.table_name && fKey.local_column === column.column_name) {
|
|
219
|
+
column.isForeign = true;
|
|
220
|
+
column.foreignSchema = fKey.foreign_schema;
|
|
221
|
+
column.foreignTable = fKey.foreign_table;
|
|
222
|
+
column.foreignColumn = fKey.foreign_column;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
234
226
|
const uniqueQuery = await runQuery(`SELECT array_agg(a.attname) AS columns
|
|
235
227
|
FROM pg_constraint AS c
|
|
236
228
|
CROSS JOIN LATERAL unnest(c.conkey) AS k(c)
|
|
@@ -245,7 +237,15 @@ export async function queryDB(db) {
|
|
|
245
237
|
let uniques = [];
|
|
246
238
|
if (uniqueQuery.rowCount > 0)
|
|
247
239
|
uniques = uniqueQuery.rows[0].columns.slice(1, -1).split(",");
|
|
248
|
-
|
|
240
|
+
for (const unique of uniques)
|
|
241
|
+
for (const column of columnQuery.rows)
|
|
242
|
+
if (unique === column.column_name)
|
|
243
|
+
column.isUnique = true;
|
|
244
|
+
const columns = [];
|
|
245
|
+
for (const column of columnQuery.rows) {
|
|
246
|
+
columns.push(new Column(column.column_name, column.ordinal_position, column.column_default, column.is_nullable === "YES", getJSType(column.data_type, column.udt_name, column.is_nullable === "YES"), getPGType(column.data_type, column.udt_name), column.is_identity === "YES", column.identity_generation, column.isPrimary || false, column.isUnique || false, column.isForeign || false, column.foreignSchema, column.foreignTable, column.foreignColumn));
|
|
247
|
+
}
|
|
248
|
+
tables.push(new Table(table.table_name, table.table_schema, columns));
|
|
249
249
|
}
|
|
250
250
|
return {
|
|
251
251
|
tables: tables,
|
|
@@ -253,16 +253,16 @@ export async function queryDB(db) {
|
|
|
253
253
|
};
|
|
254
254
|
}
|
|
255
255
|
export function runGeneration(dir, db, tables, enums) {
|
|
256
|
-
if (
|
|
256
|
+
if (tables.length === 0)
|
|
257
257
|
return new PigeonError(1, "", new Error("No tables were found."));
|
|
258
258
|
const dirResult = createDir(dir);
|
|
259
259
|
if (dirResult instanceof PigeonError)
|
|
260
260
|
return dirResult;
|
|
261
261
|
let schemas = [];
|
|
262
262
|
for (const table of tables) {
|
|
263
|
-
if (schemas.includes(table.
|
|
263
|
+
if (schemas.includes(table.schema))
|
|
264
264
|
continue;
|
|
265
|
-
schemas.push(table.
|
|
265
|
+
schemas.push(table.schema);
|
|
266
266
|
}
|
|
267
267
|
for (const schema of schemas) {
|
|
268
268
|
const dirResult = createDir(path.join(dir, schema));
|
|
@@ -275,7 +275,7 @@ export function runGeneration(dir, db, tables, enums) {
|
|
|
275
275
|
if (enums) {
|
|
276
276
|
for (const cEnum of enums) {
|
|
277
277
|
for (const column of table.columns) {
|
|
278
|
-
if (cEnum.name
|
|
278
|
+
if (column.pgType.includes(cEnum.name)) {
|
|
279
279
|
const enumName = nameBeautifier(cEnum.name).replaceAll(" ", "");
|
|
280
280
|
ts += "/**\n An Enum representing the " + nameBeautifier(cEnum.name).toLowerCase() + ".\n * @readonly\n * @enum {string}\n */\n";
|
|
281
281
|
ts += "class " + enumName + " {\n";
|
|
@@ -290,37 +290,40 @@ export function runGeneration(dir, db, tables, enums) {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
-
ts += createClass(table.
|
|
293
|
+
ts += createClass(table.name, table.columns);
|
|
294
294
|
ts += "\n\n";
|
|
295
|
-
ts += createGetAll(table.
|
|
295
|
+
ts += createGetAll(table.schema, table.name, table.columns);
|
|
296
296
|
ts += "\n\n";
|
|
297
297
|
let keys = [];
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
for (const fKey of table.foreignKeys)
|
|
302
|
-
keys.push(fKey.local_column.replaceAll(" ", ""));
|
|
303
|
-
if (table.unique)
|
|
304
|
-
keys = keys.concat(table.unique.columns);
|
|
305
|
-
keys = [...new Set(keys)];
|
|
298
|
+
for (const column of table.columns)
|
|
299
|
+
if (column.isPrimary || column.isForeign || column.isUnique)
|
|
300
|
+
keys.push(column);
|
|
306
301
|
for (const keyCombination of getCombinations(keys)) {
|
|
307
|
-
ts += createGet(table.
|
|
302
|
+
ts += createGet(table.schema, table.name, table.columns, keyCombination);
|
|
308
303
|
ts += "\n\n";
|
|
309
304
|
}
|
|
310
305
|
let nonDefaults = [];
|
|
311
306
|
let softDefaults = [];
|
|
312
307
|
let hardDefaults = [];
|
|
313
308
|
for (const column of table.columns) {
|
|
314
|
-
if (column.
|
|
309
|
+
if (column.defaultValue === null && !column.isIdentity)
|
|
315
310
|
nonDefaults.push(column);
|
|
316
|
-
else if ((column.
|
|
311
|
+
else if ((column.defaultValue !== null && !column.defaultValue.includes("nextval")) || (column.isIdentity && column.identityGeneration === "BY DEFAULT"))
|
|
317
312
|
softDefaults.push(column);
|
|
318
|
-
else if ((column.
|
|
313
|
+
else if ((column.defaultValue !== null && column.defaultValue.includes("nextval")) || (column.isIdentity && column.identityGeneration === "ALWAYS"))
|
|
319
314
|
hardDefaults.push(column);
|
|
320
315
|
}
|
|
321
|
-
ts += createAdd(table.
|
|
316
|
+
ts += createAdd(table.schema, table.name, nonDefaults, [], hardDefaults.concat(softDefaults)) + "\n\n";
|
|
322
317
|
for (const softCombination of getCombinations(softDefaults))
|
|
323
|
-
ts += createAdd(table.
|
|
318
|
+
ts += createAdd(table.schema, table.name, nonDefaults, softCombination, hardDefaults.concat(softDefaults.filter(n => !getCombinations(softDefaults).includes([n])))) + "\n\n";
|
|
319
|
+
for (const keyCombination of getCombinations(keys)) {
|
|
320
|
+
ts += createUpdate(table.schema, table.name, table.columns, keyCombination);
|
|
321
|
+
ts += "\n\n";
|
|
322
|
+
}
|
|
323
|
+
for (const column of table.columns) {
|
|
324
|
+
ts += createDelete(table.schema, table.name, column, table.columns);
|
|
325
|
+
ts += "\n\n";
|
|
326
|
+
}
|
|
324
327
|
ts = ts.slice(0, -2);
|
|
325
328
|
const regex = /import ({?.*?}?) from "(.*?)";\n/g;
|
|
326
329
|
let importObjects = [];
|
|
@@ -365,47 +368,36 @@ export function runGeneration(dir, db, tables, enums) {
|
|
|
365
368
|
importString += "import pg from \"pg\";\n\n";
|
|
366
369
|
importString += "const {Client} = pg;\n\n";
|
|
367
370
|
ts = importString + ts;
|
|
368
|
-
fs.writeFileSync(path.join(dir, table.
|
|
371
|
+
fs.writeFileSync(path.join(dir, table.schema, table.name + ".ts"), ts);
|
|
369
372
|
}
|
|
370
373
|
}
|
|
371
|
-
function createClass(tableName, columns
|
|
374
|
+
function createClass(tableName, columns) {
|
|
372
375
|
let text = "";
|
|
373
376
|
text += "export class " + singularize(nameBeautifier(tableName)).replaceAll(" ", "") + " {\n";
|
|
374
377
|
for (const column of columns) {
|
|
375
|
-
let dataType = getType(column.data_type, column.udt_name).replaceAll(" ", "");
|
|
376
|
-
if (column.is_nullable === "YES")
|
|
377
|
-
dataType += " | undefined";
|
|
378
|
-
let isPrimaryKey = false;
|
|
379
|
-
if (column.column_name === primaryKey)
|
|
380
|
-
isPrimaryKey = true;
|
|
381
|
-
let foreignKeyIndex;
|
|
382
|
-
if (foreignKeys)
|
|
383
|
-
for (let i = 0; i < foreignKeys.length; i++)
|
|
384
|
-
if (foreignKeys[i].local_column === column.column_name)
|
|
385
|
-
foreignKeyIndex = i;
|
|
386
378
|
text += "\t/**\n";
|
|
387
|
-
if (
|
|
388
|
-
text += "\t * A primary key representing the " + nameBeautifier(column.
|
|
389
|
-
else if (
|
|
390
|
-
text += "\t * A foreign key representing the " + nameBeautifier(column.
|
|
391
|
-
else if (column.
|
|
392
|
-
text += "\t * Indicates whether this record in the table " + nameBeautifier(tableName) + " is currently " + nameBeautifier(column.
|
|
379
|
+
if (column.isPrimary)
|
|
380
|
+
text += "\t * A primary key representing the " + nameBeautifier(column.name) + " for the " + nameBeautifier(tableName) + " table.\n";
|
|
381
|
+
else if (column.isForeign && column.foreignColumn && column.foreignTable && column.foreignSchema)
|
|
382
|
+
text += "\t * A foreign key representing the " + nameBeautifier(column.name) + " for the " + nameBeautifier(tableName) + " table and referencing the " + nameBeautifier(column.foreignColumn) + " in the " + nameBeautifier(column.foreignTable) + " table in the " + nameBeautifier(column.foreignSchema) + " schema.\n";
|
|
383
|
+
else if (column.name.toLowerCase().startsWith("is_"))
|
|
384
|
+
text += "\t * Indicates whether this record in the table " + nameBeautifier(tableName) + " is currently " + nameBeautifier(column.name.slice(3)).toLowerCase() + ".\n";
|
|
393
385
|
else
|
|
394
|
-
text += "\t * The " + nameBeautifier(column.
|
|
395
|
-
text += "\t * @type {" +
|
|
386
|
+
text += "\t * The " + nameBeautifier(column.name) + " for the " + nameBeautifier(tableName) + " table.\n";
|
|
387
|
+
text += "\t * @type {" + column.jsType + "}\n";
|
|
396
388
|
text += "\t */\n";
|
|
397
|
-
text += "\t" + column.
|
|
398
|
-
if (column.
|
|
399
|
-
let columnDefault = column.
|
|
400
|
-
let type = column.
|
|
389
|
+
text += "\t" + column.name + ": " + column.jsType;
|
|
390
|
+
if (column.defaultValue !== null) {
|
|
391
|
+
let columnDefault = column.defaultValue.split("::")[0];
|
|
392
|
+
let type = column.defaultValue.split("::")[1];
|
|
401
393
|
if (!columnDefault.includes("nextval")) {
|
|
402
|
-
if (
|
|
394
|
+
if (column.jsType === "Date") {
|
|
403
395
|
if (columnDefault.toLowerCase() === "now()")
|
|
404
396
|
text += " = new Date()";
|
|
405
397
|
else
|
|
406
398
|
text += " = new Date(" + columnDefault.replace(" ", "T") + ")";
|
|
407
399
|
}
|
|
408
|
-
else if (
|
|
400
|
+
else if (column.jsType.includes("number") || column.jsType.includes("boolean"))
|
|
409
401
|
text += " = " + columnDefault;
|
|
410
402
|
else if (type) {
|
|
411
403
|
if (jsTypes.get(type) === "string")
|
|
@@ -419,7 +411,7 @@ function createClass(tableName, columns, primaryKey, foreignKeys) {
|
|
|
419
411
|
}
|
|
420
412
|
}
|
|
421
413
|
else
|
|
422
|
-
text += " = \"" + column.
|
|
414
|
+
text += " = \"" + column.defaultValue + "\"";
|
|
423
415
|
}
|
|
424
416
|
}
|
|
425
417
|
text += ";\n";
|
|
@@ -429,30 +421,20 @@ function createClass(tableName, columns, primaryKey, foreignKeys) {
|
|
|
429
421
|
text += "\t * Creates a new object for the " + nameBeautifier(tableName) + " table.\n";
|
|
430
422
|
text += "\t * \n";
|
|
431
423
|
for (const column of columns) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (column.is_nullable === "YES")
|
|
436
|
-
text += " | undefined";
|
|
437
|
-
text += "} " + column.column_name;
|
|
438
|
-
if (!column.column_name.toLowerCase().startsWith("is_"))
|
|
439
|
-
text += " - The " + nameBeautifier(column.column_name) + " of the " + nameBeautifier(tableName) + " table. \n";
|
|
424
|
+
text += "\t * @param {" + column.jsType + "} " + column.name;
|
|
425
|
+
if (!column.name.toLowerCase().startsWith("is_"))
|
|
426
|
+
text += " - The " + nameBeautifier(column.name) + " of the " + nameBeautifier(tableName) + " table. \n";
|
|
440
427
|
else
|
|
441
|
-
text += " - Indicates whether this record in the table " + nameBeautifier(tableName) + " is currently " + nameBeautifier(column.
|
|
428
|
+
text += " - Indicates whether this record in the table " + nameBeautifier(tableName) + " is currently " + nameBeautifier(column.name.slice(3)).toLowerCase() + ".\n";
|
|
442
429
|
}
|
|
443
430
|
text += "\t */\n";
|
|
444
431
|
text += "\tconstructor(";
|
|
445
|
-
for (const column of columns)
|
|
446
|
-
|
|
447
|
-
text += column.column_name + ": " + dataType;
|
|
448
|
-
if (column.is_nullable === "YES")
|
|
449
|
-
text += " | undefined";
|
|
450
|
-
text += ", ";
|
|
451
|
-
}
|
|
432
|
+
for (const column of columns)
|
|
433
|
+
text += column.name + ": " + column.jsType + ", ";
|
|
452
434
|
text = text.slice(0, -2);
|
|
453
435
|
text += ") {\n";
|
|
454
436
|
for (const column of columns)
|
|
455
|
-
text += "\t\tthis." + column.
|
|
437
|
+
text += "\t\tthis." + column.name + " = " + column.name + ";\n";
|
|
456
438
|
text += "\t}\n";
|
|
457
439
|
text += "}";
|
|
458
440
|
return text;
|
|
@@ -492,53 +474,32 @@ function createGet(tableSchema, tableName, columns, keys) {
|
|
|
492
474
|
text += "/**\n";
|
|
493
475
|
text += " * Gets " + className + " objects from the database by ";
|
|
494
476
|
for (const key of keys)
|
|
495
|
-
text += key + " and ";
|
|
477
|
+
text += key.name + " and ";
|
|
496
478
|
text = text.slice(0, -5) + ".\n";
|
|
497
479
|
text += " *\n";
|
|
498
|
-
for (const key of keys)
|
|
499
|
-
|
|
500
|
-
if (!column) {
|
|
501
|
-
consoleMessage("WRN", `Key ${key} was not found in the columns of table ${tableName}.`);
|
|
502
|
-
continue;
|
|
503
|
-
}
|
|
504
|
-
let dataType = getType(column.data_type, column.udt_name).replaceAll(" ", "");
|
|
505
|
-
text += " * ";
|
|
506
|
-
text += "@param {" + dataType;
|
|
507
|
-
text += "} " + column.column_name;
|
|
508
|
-
text += " - The " + nameBeautifier(column.column_name) + " of the " + nameBeautifier(tableName) + " table.\n";
|
|
509
|
-
}
|
|
480
|
+
for (const key of keys)
|
|
481
|
+
text += " * @param {" + key.jsType + "} " + key.name + " - The " + nameBeautifier(key.name) + " of the " + nameBeautifier(tableName) + " table.\n";
|
|
510
482
|
text += " * @returns {Promise<" + className + "[]>} - A Promise object returning an array of " + nameBeautifier(tableName) + ".\n";
|
|
511
483
|
text += " */\n";
|
|
512
484
|
text += "export async function get" + nameBeautifier(tableName).replaceAll(" ", "") + "By";
|
|
513
485
|
for (const key of keys)
|
|
514
|
-
text += nameBeautifier(key).replaceAll(" ", "") + "And";
|
|
486
|
+
text += nameBeautifier(key.name).replaceAll(" ", "") + "And";
|
|
515
487
|
text = text.slice(0, -3);
|
|
516
488
|
text += "(";
|
|
517
|
-
for (const key of keys)
|
|
518
|
-
|
|
519
|
-
if (!column) {
|
|
520
|
-
consoleMessage("WRN", `Key ${key} was not found in the columns of table ${tableName}.`);
|
|
521
|
-
continue;
|
|
522
|
-
}
|
|
523
|
-
text += key + ": " + getType(column.data_type, column.udt_name) + ", ";
|
|
524
|
-
}
|
|
489
|
+
for (const key of keys)
|
|
490
|
+
text += key.name + ": " + key.jsType + ", ";
|
|
525
491
|
text = text.slice(0, -2);
|
|
526
492
|
text += "): Promise<" + className + "[]> {\n";
|
|
527
493
|
text += "\tif (";
|
|
528
494
|
for (const key of keys)
|
|
529
|
-
text += key + " === undefined || ";
|
|
495
|
+
text += key.name + " === undefined || ";
|
|
530
496
|
text = text.slice(0, -4);
|
|
531
497
|
text += ")\n" + "\t\tthrow \"Missing Parameters\";\n\n";
|
|
532
498
|
let query = "SELECT * FROM " + tableSchema + "." + tableName + " WHERE ";
|
|
533
499
|
let parameters = "";
|
|
534
500
|
for (let i = 0; i < keys.length; i++) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
consoleMessage("WRN", `Key ${keys[i]} was not found in the columns of table ${tableName}.`);
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
query += keys[i] + " = " + "$" + (i + 1) + "::" + (column.data_type || column.udt_name) + " AND ";
|
|
541
|
-
parameters += keys[i] + ", ";
|
|
501
|
+
query += keys[i].name + " = " + "$" + (i + 1) + "::" + keys[i].pgType + " AND ";
|
|
502
|
+
parameters += keys[i].name + ", ";
|
|
542
503
|
}
|
|
543
504
|
query = query.slice(0, -5) + ";";
|
|
544
505
|
parameters = parameters.slice(0, -2);
|
|
@@ -549,38 +510,34 @@ function createGet(tableSchema, tableName, columns, keys) {
|
|
|
549
510
|
text += "}";
|
|
550
511
|
return text;
|
|
551
512
|
}
|
|
552
|
-
function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaults
|
|
513
|
+
function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaults) {
|
|
553
514
|
let text = "";
|
|
554
515
|
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
516
|
+
let hasForeign = false;
|
|
517
|
+
for (const column of nonDefaults.concat(softDefaults).concat(hardDefaults).sort((a, b) => a.position - b.position)) {
|
|
518
|
+
if (column.isForeign && column.foreignColumn && column.foreignTable && column.foreignSchema) {
|
|
519
|
+
hasForeign = true;
|
|
520
|
+
if ((tableSchema === column.foreignSchema) && (tableName === column.foreignTable))
|
|
558
521
|
continue;
|
|
559
|
-
text += "import {get" + nameBeautifier(
|
|
560
|
-
if (tableSchema !==
|
|
561
|
-
text += "./" +
|
|
562
|
-
text += "/" +
|
|
522
|
+
text += "import {get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "} from \".";
|
|
523
|
+
if (tableSchema !== column.foreignSchema)
|
|
524
|
+
text += "./" + column.foreignSchema;
|
|
525
|
+
text += "/" + column.foreignTable + ".js\";\n";
|
|
563
526
|
}
|
|
564
527
|
}
|
|
565
528
|
text += "/**\n";
|
|
566
529
|
text += " * Adds the provided " + className + " object to the database.\n";
|
|
567
530
|
text += " *\n";
|
|
568
531
|
let columns = nonDefaults.concat(softDefaults);
|
|
569
|
-
columns.sort((a, b) => a.
|
|
570
|
-
for (const column of columns)
|
|
571
|
-
|
|
572
|
-
text += " * ";
|
|
573
|
-
text += "@param {" + dataType;
|
|
574
|
-
if (column.is_nullable === "YES")
|
|
575
|
-
text += " | undefined";
|
|
576
|
-
text += "} " + column.column_name;
|
|
577
|
-
text += " - The " + nameBeautifier(column.column_name) + " to be inserted into the " + nameBeautifier(tableName) + " table.\n";
|
|
578
|
-
}
|
|
532
|
+
columns.sort((a, b) => a.position - b.position);
|
|
533
|
+
for (const column of columns)
|
|
534
|
+
text += " * @param {" + column.jsType + "} " + column.name + " - The " + nameBeautifier(column.name) + " to be inserted into the " + nameBeautifier(tableName) + " table.\n";
|
|
579
535
|
text += " * @returns {Promise<" + className + ">} - A Promise object returning the inserted " + nameBeautifier(tableName) + ".\n";
|
|
580
|
-
if (
|
|
536
|
+
if (hasForeign) {
|
|
581
537
|
text += " * @throws string An exception in the case of the ";
|
|
582
|
-
for (const
|
|
583
|
-
|
|
538
|
+
for (const column of columns)
|
|
539
|
+
if (column.isForeign)
|
|
540
|
+
text += nameBeautifier(column.name) + " or the ";
|
|
584
541
|
text = text.slice(0, -8);
|
|
585
542
|
text += " not existing in their table.\n";
|
|
586
543
|
}
|
|
@@ -589,54 +546,42 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
|
|
|
589
546
|
if (softDefaults.length > 0) {
|
|
590
547
|
text += "With";
|
|
591
548
|
for (const softDefault of softDefaults)
|
|
592
|
-
text += nameBeautifier(softDefault.
|
|
549
|
+
text += nameBeautifier(softDefault.name).replaceAll(" ", "") + "And";
|
|
593
550
|
text = text.slice(0, -3);
|
|
594
551
|
}
|
|
595
552
|
text += "(";
|
|
596
|
-
for (const column of columns)
|
|
597
|
-
|
|
598
|
-
text += column.column_name + ": " + dataType;
|
|
599
|
-
if (column.is_nullable === "YES")
|
|
600
|
-
text += " | undefined";
|
|
601
|
-
text += ", ";
|
|
602
|
-
}
|
|
553
|
+
for (const column of columns)
|
|
554
|
+
text += column.name + ": " + column.jsType + ", ";
|
|
603
555
|
text = text.slice(0, -2);
|
|
604
556
|
text += "): Promise<" + className + "> {\n";
|
|
605
|
-
if (
|
|
606
|
-
for (const
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
text += "\tif (verify" + nameBeautifier(foreignKey.local_column).replaceAll(" ", "") + ".length === 0)\n";
|
|
622
|
-
text += "\t\tthrow \"The " + nameBeautifier(foreignKey.local_column) + " provided does not exist.\";\n\n";
|
|
557
|
+
if (hasForeign) {
|
|
558
|
+
for (const column of columns) {
|
|
559
|
+
if (column.isForeign && column.foreignColumn && column.foreignTable && column.foreignSchema) {
|
|
560
|
+
const name = nameBeautifier(column.name).replaceAll(" ", "");
|
|
561
|
+
if (column.isNullable) {
|
|
562
|
+
text += "\tif (" + column.name + ") {\n";
|
|
563
|
+
text += "\t\tconst verify" + name + " = await get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "(" + column.name + ");\n";
|
|
564
|
+
text += "\t\tif (verify" + name + ".length === 0)\n";
|
|
565
|
+
text += "\t\t\tthrow \"The " + nameBeautifier(column.name) + " provided does not exist.\";\n";
|
|
566
|
+
text += "\t}\n\n";
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
text += "\tconst verify" + name + " = await get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "(" + column.name + ");\n";
|
|
570
|
+
text += "\tif (verify" + name + ".length === 0)\n";
|
|
571
|
+
text += "\t\tthrow \"The " + nameBeautifier(column.name) + " provided does not exist.\";\n\n";
|
|
572
|
+
}
|
|
623
573
|
}
|
|
624
574
|
}
|
|
625
575
|
}
|
|
626
576
|
let query = "INSERT INTO " + tableSchema + "." + tableName + " (";
|
|
627
577
|
for (const column of columns)
|
|
628
|
-
query += column.
|
|
578
|
+
query += column.name + ", ";
|
|
629
579
|
query = query.slice(0, -2);
|
|
630
580
|
query += ") VALUES (";
|
|
631
581
|
let parameters = "";
|
|
632
582
|
for (let i = 0; i < columns.length; i++) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
dataType = dataType.slice(1) + "[]";
|
|
636
|
-
else if (columns[i].data_type !== "USER-DEFINED")
|
|
637
|
-
dataType = columns[i].data_type;
|
|
638
|
-
query += "$" + (i + 1) + "::" + dataType + ", ";
|
|
639
|
-
parameters += columns[i].column_name + ", ";
|
|
583
|
+
query += "$" + (i + 1) + "::" + columns[i].pgType + ", ";
|
|
584
|
+
parameters += columns[i].name + ", ";
|
|
640
585
|
}
|
|
641
586
|
query = query.slice(0, -2);
|
|
642
587
|
parameters = parameters.slice(0, -2);
|
|
@@ -646,9 +591,122 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
|
|
|
646
591
|
text += "\treturn new " + className + "(\n";
|
|
647
592
|
columns = columns.concat(hardDefaults);
|
|
648
593
|
columns = [...new Set(columns)];
|
|
649
|
-
columns.sort((a, b) => a.
|
|
594
|
+
columns.sort((a, b) => a.position - b.position);
|
|
595
|
+
for (const column of columns)
|
|
596
|
+
text += "\t\tinsertQuery.rows[0]." + column.name + ",\n";
|
|
597
|
+
text = text.slice(0, -2);
|
|
598
|
+
text += "\n";
|
|
599
|
+
text += "\t);\n";
|
|
600
|
+
text += "}";
|
|
601
|
+
return text;
|
|
602
|
+
}
|
|
603
|
+
function createUpdate(tableSchema, tableName, columns, keys) {
|
|
604
|
+
const optionals = columns.filter(column => !keys.includes(column));
|
|
605
|
+
let text = "";
|
|
606
|
+
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
607
|
+
let hasForeign = false;
|
|
608
|
+
for (const column of columns) {
|
|
609
|
+
if (column.isForeign && column.foreignColumn && column.foreignTable && column.foreignSchema) {
|
|
610
|
+
hasForeign = true;
|
|
611
|
+
if ((tableSchema === column.foreignSchema) && (tableName === column.foreignTable))
|
|
612
|
+
continue;
|
|
613
|
+
text += "import {get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "} from \".";
|
|
614
|
+
if (tableSchema !== column.foreignSchema)
|
|
615
|
+
text += "./" + column.foreignSchema;
|
|
616
|
+
text += "/" + column.foreignTable + ".js\";\n";
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
text += "/**\n";
|
|
620
|
+
text += " * Updates the " + className + " objects from the database by ";
|
|
621
|
+
for (const key of keys)
|
|
622
|
+
text += key.name + " and ";
|
|
623
|
+
text = text.slice(0, -5) + ".\n";
|
|
624
|
+
text += " *\n";
|
|
625
|
+
for (const key of keys)
|
|
626
|
+
text += " * @param {" + key.jsType.replace(" | null", "") + "} " + key.name + " - The " + nameBeautifier(key.name) + " of the " + nameBeautifier(tableName) + " table to be updated.\n";
|
|
627
|
+
for (const optional of optionals)
|
|
628
|
+
text += " * @param {" + optional.jsType + " | undefined} " + optional.name + " - The value of the" + nameBeautifier(optional.name) + " of the " + nameBeautifier(tableName) + " table to be updated.\n";
|
|
629
|
+
text += " * @returns {Promise<" + className + ">} - A Promise object returning the updated " + nameBeautifier(tableName) + ".\n";
|
|
630
|
+
if (hasForeign) {
|
|
631
|
+
text += " * @throws string An exception in the case of the ";
|
|
632
|
+
for (const column of columns)
|
|
633
|
+
if (column.isForeign)
|
|
634
|
+
text += nameBeautifier(column.name) + " or the ";
|
|
635
|
+
text = text.slice(0, -8);
|
|
636
|
+
text += " not existing in their table.\n";
|
|
637
|
+
}
|
|
638
|
+
text += " */\n";
|
|
639
|
+
text += "export async function update" + className + "By";
|
|
640
|
+
for (const key of keys)
|
|
641
|
+
text += nameBeautifier(key.name).replaceAll(" ", "") + "And";
|
|
642
|
+
text = text.slice(0, -3);
|
|
643
|
+
text += "(";
|
|
644
|
+
for (const key of keys)
|
|
645
|
+
text += key.name + ": " + key.jsType.replace(" | null", "") + ", ";
|
|
646
|
+
for (const optional of optionals)
|
|
647
|
+
text += optional.name + "?: " + optional.jsType + " | undefined, ";
|
|
648
|
+
text = text.slice(0, -2);
|
|
649
|
+
text += "): Promise<" + className + "> {\n";
|
|
650
|
+
if (hasForeign) {
|
|
651
|
+
for (const column of columns) {
|
|
652
|
+
if (column.isForeign && column.foreignColumn && column.foreignTable && column.foreignSchema) {
|
|
653
|
+
const name = nameBeautifier(column.name).replaceAll(" ", "");
|
|
654
|
+
if (!keys.includes(column)) {
|
|
655
|
+
text += "\tif (" + column.name + ") {\n";
|
|
656
|
+
text += "\t\tconst verify" + name + " = await get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "(" + column.name + ");\n";
|
|
657
|
+
text += "\t\tif (verify" + name + ".length === 0)\n";
|
|
658
|
+
text += "\t\t\tthrow \"The " + nameBeautifier(column.name) + " provided does not exist.\";\n";
|
|
659
|
+
text += "\t}\n\n";
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
text += "\tconst verify" + name + " = await get" + nameBeautifier(column.foreignTable).replaceAll(" ", "") + "By" + nameBeautifier(column.foreignColumn).replaceAll(" ", "") + "(" + column.name + ");\n";
|
|
663
|
+
text += "\tif (verify" + name + ".length === 0)\n";
|
|
664
|
+
text += "\t\tthrow \"The " + nameBeautifier(column.name) + " provided does not exist.\";\n\n";
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
text += "\tlet set = \"\";\n";
|
|
670
|
+
for (let optional of optionals) {
|
|
671
|
+
text += "\tif (" + optional.name + " !== undefined)\n";
|
|
672
|
+
text += "\t\tset += \"" + optional.name + " = '\" + " + optional.name + " + \"', \";\n";
|
|
673
|
+
}
|
|
674
|
+
text += "\tset = set.slice(0, -2);\n";
|
|
675
|
+
let parameters = "";
|
|
676
|
+
let query = "UPDATE " + tableSchema + "." + tableName + ` SET \$\{set\} WHERE `;
|
|
677
|
+
for (let i = 0; i < keys.length; i++) {
|
|
678
|
+
query += keys[i].name + " = " + "$" + (i + 1) + "::" + keys[i].pgType + " AND ";
|
|
679
|
+
parameters += keys[i].name + ", ";
|
|
680
|
+
}
|
|
681
|
+
parameters = parameters.slice(0, -2);
|
|
682
|
+
query = query.slice(0, -5) + " RETURNING *;";
|
|
683
|
+
text += queryMaker(1, "update", query, parameters);
|
|
684
|
+
text += "\n\n";
|
|
685
|
+
text += "\treturn new " + className + "(\n";
|
|
686
|
+
for (const column of columns)
|
|
687
|
+
text += "\t\tupdateQuery.rows[0]." + column.name + ",\n";
|
|
688
|
+
text = text.slice(0, -2);
|
|
689
|
+
text += "\n";
|
|
690
|
+
text += "\t);\n";
|
|
691
|
+
text += "}";
|
|
692
|
+
return text;
|
|
693
|
+
}
|
|
694
|
+
function createDelete(tableSchema, tableName, column, columns) {
|
|
695
|
+
let text = "";
|
|
696
|
+
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
697
|
+
text += "/**\n";
|
|
698
|
+
text += " * Deletes the " + className + " objects from the database by the value of its " + nameBeautifier(column.name) + ".\n";
|
|
699
|
+
text += " *\n";
|
|
700
|
+
text += " * @param {" + column.jsType.replace(" | null", "") + "} " + column.name + " - The value of the" + nameBeautifier(column.name) + " of the " + nameBeautifier(tableName) + " table to be updated.\n";
|
|
701
|
+
text += " * @returns {Promise<" + className + ">} - A Promise object returning the deleted " + nameBeautifier(tableName) + ".\n";
|
|
702
|
+
text += " */\n";
|
|
703
|
+
text += "export async function delete" + className + "By" + nameBeautifier(column.name).replaceAll(" ", "") + "(" + column.name + ": " + column.jsType.replace(" | null", "") + "): Promise<" + className + "> {\n";
|
|
704
|
+
const query = "DELETE FROM " + tableSchema + "." + tableName + " WHERE " + column.name + " = $1::" + column.pgType + "RETURNING *;";
|
|
705
|
+
text += queryMaker(1, "delete", query, column.name);
|
|
706
|
+
text += "\n\n";
|
|
707
|
+
text += "\treturn new " + className + "(\n";
|
|
650
708
|
for (const column of columns)
|
|
651
|
-
text += "\t\
|
|
709
|
+
text += "\t\tdeleteQuery.rows[0]." + column.name + ",\n";
|
|
652
710
|
text = text.slice(0, -2);
|
|
653
711
|
text += "\n";
|
|
654
712
|
text += "\t);\n";
|
package/src/maps.js
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
export const jsTypes = new Map([
|
|
2
|
-
["
|
|
3
|
-
["
|
|
4
|
-
["bigserial", "number"],
|
|
5
|
-
["serial8", "number"],
|
|
6
|
-
["bit", "Array"],
|
|
7
|
-
["bit varying", "Array"],
|
|
8
|
-
["varbit", "Array"],
|
|
9
|
-
["boolean", "boolean"],
|
|
10
|
-
["bool", "boolean"],
|
|
11
|
-
["box", ""],
|
|
12
|
-
["bytea", "Array"],
|
|
13
|
-
["character", "string"],
|
|
14
|
-
["char", "string"],
|
|
15
|
-
["character varying", "string"],
|
|
16
|
-
["varchar", "string"],
|
|
17
|
-
["cidr", "string"],
|
|
18
|
-
["circle", ""],
|
|
19
|
-
["date", "Date"],
|
|
20
|
-
["double precision", "number"],
|
|
21
|
-
["float8", "number"],
|
|
22
|
-
["inet", "string"],
|
|
2
|
+
["smallint", "number"],
|
|
3
|
+
["int2", "number"],
|
|
23
4
|
["integer", "number"],
|
|
24
5
|
["int", "number"],
|
|
25
|
-
["
|
|
26
|
-
["
|
|
27
|
-
["json", "string"],
|
|
28
|
-
["jsonb", "Array"],
|
|
29
|
-
["line", ""],
|
|
30
|
-
["lseg", ""],
|
|
31
|
-
["macaddr", "string"],
|
|
32
|
-
["macaddr8", "string"],
|
|
33
|
-
["money", "number"],
|
|
34
|
-
["numeric", "number"],
|
|
35
|
-
["decimal", "number"],
|
|
36
|
-
["path", ""],
|
|
37
|
-
["pg_lsn", "number"],
|
|
38
|
-
["pg_snapshot", ""],
|
|
39
|
-
["point", ""],
|
|
40
|
-
["polygon", ""],
|
|
6
|
+
["bigint", "string"],
|
|
7
|
+
["int8", "string"],
|
|
41
8
|
["real", "number"],
|
|
42
9
|
["float4", "number"],
|
|
43
|
-
["
|
|
44
|
-
["
|
|
10
|
+
["double precision", "number"],
|
|
11
|
+
["float8", "string"],
|
|
12
|
+
["numeric", "string"],
|
|
13
|
+
["decimal", "string"],
|
|
14
|
+
["money", "string"],
|
|
45
15
|
["smallserial", "number"],
|
|
46
16
|
["serial2", "number"],
|
|
47
17
|
["serial", "number"],
|
|
48
|
-
["
|
|
18
|
+
["serial4", "number"],
|
|
19
|
+
["bigserial", "string"],
|
|
20
|
+
["serial8", "string"],
|
|
21
|
+
["character", "string"],
|
|
22
|
+
["char", "string"],
|
|
23
|
+
["character varying", "string"],
|
|
24
|
+
["varchar", "string"],
|
|
49
25
|
["text", "string"],
|
|
50
|
-
["
|
|
51
|
-
["
|
|
52
|
-
["
|
|
53
|
-
["
|
|
54
|
-
["
|
|
26
|
+
["name", "string"],
|
|
27
|
+
["bytea", "Buffer"],
|
|
28
|
+
["bit", "string"],
|
|
29
|
+
["bit varying", "string"],
|
|
30
|
+
["varbit", "string"],
|
|
31
|
+
["boolean", "boolean"],
|
|
32
|
+
["bool", "boolean"],
|
|
33
|
+
["date", "Date"],
|
|
34
|
+
["time without time zone", "string"],
|
|
35
|
+
["time", "string"],
|
|
36
|
+
["time with time zone", "string"],
|
|
37
|
+
["timetz", "string"],
|
|
55
38
|
["timestamp without time zone", "Date"],
|
|
39
|
+
["timestamp", "Date"],
|
|
56
40
|
["timestamp with time zone", "Date"],
|
|
57
41
|
["timestamptz", "Date"],
|
|
58
|
-
["
|
|
59
|
-
["
|
|
60
|
-
["
|
|
42
|
+
["interval", "object"],
|
|
43
|
+
["box", "object"],
|
|
44
|
+
["circle", "object"],
|
|
45
|
+
["line", "object"],
|
|
46
|
+
["lseg", "object"],
|
|
47
|
+
["path", "object"],
|
|
48
|
+
["point", "object"],
|
|
49
|
+
["polygon", "object"],
|
|
50
|
+
["cidr", "string"],
|
|
51
|
+
["inet", "string"],
|
|
52
|
+
["macaddr", "string"],
|
|
53
|
+
["macaddr8", "string"],
|
|
54
|
+
["json", "object"],
|
|
55
|
+
["jsonb", "object"],
|
|
61
56
|
["uuid", "string"],
|
|
57
|
+
["tsquery", "string"],
|
|
58
|
+
["tsvector", "string"],
|
|
59
|
+
["pg_lsn", "string"],
|
|
60
|
+
["pg_snapshot", "string"],
|
|
61
|
+
["txid_snapshot", "string"],
|
|
62
62
|
["xml", "string"],
|
|
63
63
|
]);
|
|
64
64
|
export const udtTypes = new Map([
|
|
@@ -83,6 +83,7 @@ export const udtTypes = new Map([
|
|
|
83
83
|
["character varying", "varchar"],
|
|
84
84
|
["varchar", "varchar"],
|
|
85
85
|
["text", "text"],
|
|
86
|
+
["name", "name"],
|
|
86
87
|
["bytea", "bytea"],
|
|
87
88
|
["bit", "bit"],
|
|
88
89
|
["bit varying", "varbit"],
|
package/src/pgAdmin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Column, PigeonError, Table, } from "./index.js";
|
|
2
|
+
import { getJSType, getPGType, getTypesByDataType } from "./utils.js";
|
|
3
3
|
function objectToArray(json) {
|
|
4
4
|
let arrayJSON = "";
|
|
5
5
|
let enteredObject = false;
|
|
@@ -52,66 +52,57 @@ export function tableProcessing(tables) {
|
|
|
52
52
|
const columns = [];
|
|
53
53
|
let ordinalPossition = 1;
|
|
54
54
|
for (const column of data.columns) {
|
|
55
|
-
|
|
56
|
-
let
|
|
57
|
-
udtType = udtTypes.get(dataType);
|
|
58
|
-
if (!udtType) {
|
|
59
|
-
if (dataType.endsWith("[]")) {
|
|
60
|
-
udtType = "_" + udtTypes.get(dataType.slice(0, -2));
|
|
61
|
-
dataType = "ARRAY";
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
udtType = dataType;
|
|
65
|
-
dataType = "USER-DEFINED";
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (dataType === "smallserial" || dataType === "serial" || dataType === "bigserial") {
|
|
69
|
-
dataType = dataType.replace("serial", "int");
|
|
70
|
-
if (dataType === "int")
|
|
71
|
-
dataType = "integer";
|
|
72
|
-
column.defval = "nextval('" + data.name + "_" + column.name + "_seq'::regclass)";
|
|
73
|
-
}
|
|
74
|
-
let isNullable;
|
|
55
|
+
const types = getTypesByDataType(column.cltype);
|
|
56
|
+
let isNullable = true;
|
|
75
57
|
if (column.attnotnull)
|
|
76
|
-
isNullable =
|
|
77
|
-
|
|
78
|
-
|
|
58
|
+
isNullable = false;
|
|
59
|
+
const jsType = getJSType(types.dataType, types.udtName, isNullable);
|
|
60
|
+
const pgType = getPGType(types.dataType);
|
|
61
|
+
if (column.cltype.includes("serial"))
|
|
62
|
+
column.defval = "nextval('" + data.name + "_" + column.name + "_seq'::regclass)";
|
|
79
63
|
let columnDefault;
|
|
80
64
|
if (column.defval !== "" && column.defval !== undefined)
|
|
81
65
|
columnDefault = column.defval;
|
|
82
66
|
else
|
|
83
67
|
columnDefault = null;
|
|
84
|
-
let identity;
|
|
68
|
+
let identity = false;
|
|
85
69
|
if (column.colconstype === "i")
|
|
86
|
-
identity =
|
|
87
|
-
else
|
|
88
|
-
identity = "NO";
|
|
70
|
+
identity = true;
|
|
89
71
|
let identityGeneration = null;
|
|
90
|
-
if (identity
|
|
72
|
+
if (identity) {
|
|
91
73
|
if (column.attidentity === "a")
|
|
92
74
|
identityGeneration = "ALWAYS";
|
|
93
75
|
if (column.attidentity === "b")
|
|
94
76
|
identityGeneration = "BY DEFAULT";
|
|
95
77
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
78
|
+
let isPrimary = false;
|
|
79
|
+
if (column.name === data.primary_key[0].columns[0].column)
|
|
80
|
+
isPrimary = true;
|
|
81
|
+
let isForeign = false;
|
|
82
|
+
let foreignSchema = undefined;
|
|
83
|
+
let foreignTable = undefined;
|
|
84
|
+
let foreignColumn = undefined;
|
|
85
|
+
for (const foreignKey of data.foreign_key) {
|
|
86
|
+
for (const foreignKeyColumn of foreignKey.columns) {
|
|
87
|
+
if (foreignKeyColumn.local_column === column.name) {
|
|
88
|
+
isForeign = true;
|
|
89
|
+
const match = foreignKeyColumn.references_table_name.match(/(?:\((.*?)\))? ?(.*)/);
|
|
90
|
+
foreignSchema = match[1] || data.schema;
|
|
91
|
+
foreignTable = match[2];
|
|
92
|
+
foreignColumn = foreignKeyColumn.referenced;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
107
95
|
}
|
|
96
|
+
let isUnique = false;
|
|
97
|
+
if (data.unique_constraint)
|
|
98
|
+
for (const uniqueConstraint of data.unique_constraint)
|
|
99
|
+
for (const uniqueColumn of uniqueConstraint.columns)
|
|
100
|
+
if (uniqueColumn.column === column.name)
|
|
101
|
+
isUnique = true;
|
|
102
|
+
columns.push(new Column(column.name, ordinalPossition, columnDefault, isNullable, jsType, pgType, identity, identityGeneration, isPrimary, isUnique, isForeign, foreignSchema, foreignTable, foreignColumn));
|
|
103
|
+
ordinalPossition++;
|
|
108
104
|
}
|
|
109
|
-
|
|
110
|
-
if (data.unique_constraint)
|
|
111
|
-
for (const uniqueConstraint of data.unique_constraint)
|
|
112
|
-
for (const column of uniqueConstraint.columns)
|
|
113
|
-
uniqueConstraints.push(column.column);
|
|
114
|
-
pigeonTables.push(new Table(data.schema, data.name, columns, primaryKey, foreignKeys, new UniqueQueryRow(uniqueConstraints)));
|
|
105
|
+
pigeonTables.push(new Table(data.name, data.schema, columns));
|
|
115
106
|
}
|
|
116
107
|
return pigeonTables;
|
|
117
108
|
}
|
package/src/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
|
-
import { jsTypes } from "./maps.js";
|
|
2
|
+
import { jsTypes, udtTypes } from "./maps.js";
|
|
3
3
|
const { Client } = pg;
|
|
4
4
|
export async function runQuery(command, parameters, db) {
|
|
5
5
|
const client = new Client({
|
|
@@ -85,7 +85,7 @@ export function queryMaker(baseTabs, variableName, command, parameters) {
|
|
|
85
85
|
return query;
|
|
86
86
|
}
|
|
87
87
|
function queryBeautifier(baseTabs, command) {
|
|
88
|
-
const regex = /(?=((?:SELECT|INSERT|FROM|WHERE|AND|VALUES|RETURNING).*?)(?:FROM|WHERE|AND|VALUES|RETURNING|;))/g;
|
|
88
|
+
const regex = /(?=((?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|AND|VALUES|RETURNING).*?)(?:FROM|WHERE|AND|VALUES|RETURNING|;))/g;
|
|
89
89
|
let match;
|
|
90
90
|
let lines = [];
|
|
91
91
|
while ((match = regex.exec(command)) !== null) {
|
|
@@ -114,7 +114,7 @@ export function arrayMaker(baseTabs, variableName, className, columns) {
|
|
|
114
114
|
array += tabsInserter(baseTabs) + "for (const row of " + variableName + "Query.rows)\n";
|
|
115
115
|
array += tabsInserter(baseTabs + 1) + variableName + ".push(new " + className + "(\n";
|
|
116
116
|
for (const column of columns)
|
|
117
|
-
array += tabsInserter(baseTabs + 2) + "row." + column.
|
|
117
|
+
array += tabsInserter(baseTabs + 2) + "row." + column.name + ",\n";
|
|
118
118
|
array = array.slice(0, -2) + "\n";
|
|
119
119
|
array += tabsInserter(baseTabs + 1) + "));";
|
|
120
120
|
return array;
|
|
@@ -146,7 +146,10 @@ export function getCombinations(valuesArray) {
|
|
|
146
146
|
combinations.sort((a, b) => a.length - b.length);
|
|
147
147
|
return combinations;
|
|
148
148
|
}
|
|
149
|
-
export function
|
|
149
|
+
export function getJSType(dataType, udtName, isNullable) {
|
|
150
|
+
dataType = dataType.replace("serial", "int");
|
|
151
|
+
if (dataType === "int")
|
|
152
|
+
dataType = "integer";
|
|
150
153
|
let isArray = false;
|
|
151
154
|
if (dataType === "ARRAY") {
|
|
152
155
|
dataType = udtName.slice(1);
|
|
@@ -157,5 +160,40 @@ export function getType(dataType, udtName) {
|
|
|
157
160
|
foundDataType = nameBeautifier(udtName).replaceAll(" ", "");
|
|
158
161
|
if (isArray)
|
|
159
162
|
foundDataType += "[]";
|
|
163
|
+
if (isNullable)
|
|
164
|
+
foundDataType += " | null";
|
|
160
165
|
return foundDataType;
|
|
161
166
|
}
|
|
167
|
+
export function getTypesByDataType(dataType) {
|
|
168
|
+
let udtName;
|
|
169
|
+
udtName = udtTypes.get(dataType);
|
|
170
|
+
if (!udtName) {
|
|
171
|
+
if (dataType.endsWith("[]")) {
|
|
172
|
+
udtName = "_" + udtTypes.get(dataType.slice(0, -2));
|
|
173
|
+
dataType = "ARRAY";
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
udtName = dataType;
|
|
177
|
+
dataType = "USER-DEFINED";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
dataType: dataType,
|
|
182
|
+
udtName: udtName
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
export function getPGType(dataType, udtName) {
|
|
186
|
+
if (!udtName) {
|
|
187
|
+
const types = getTypesByDataType(dataType);
|
|
188
|
+
udtName = types.udtName;
|
|
189
|
+
}
|
|
190
|
+
dataType = dataType.replace("serial", "int");
|
|
191
|
+
if (dataType === "int")
|
|
192
|
+
dataType = "integer";
|
|
193
|
+
let pgType = udtName;
|
|
194
|
+
if (dataType.endsWith("[]") || dataType === "ARRAY")
|
|
195
|
+
pgType = (udtTypes.get(pgType.slice(1)) || pgType.slice(1)) + "[]";
|
|
196
|
+
else if (dataType !== "USER-DEFINED")
|
|
197
|
+
pgType = dataType;
|
|
198
|
+
return pgType;
|
|
199
|
+
}
|