@andymic/pigeon 1.0.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/LICENSE +190 -0
- package/README.md +68 -0
- package/bin/pigeon.js +20 -0
- package/bin/pigeon.ts +22 -0
- package/package.json +39 -0
- package/src/cli.js +82 -0
- package/src/cli.ts +88 -0
- package/src/config.js +21 -0
- package/src/config.ts +23 -0
- package/src/index.js +450 -0
- package/src/index.ts +521 -0
- package/src/maps.js +67 -0
- package/src/maps.ts +68 -0
- package/src/utils.js +151 -0
- package/src/utils.ts +168 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Andreas Michael
|
|
3
|
+
* This software is under the Apache 2.0 License
|
|
4
|
+
*/
|
|
5
|
+
import { arrayMaker, getCombinations, nameBeautifier, queryMaker, runQuery, singularize, sleep, tabsInserter } from "./utils.js";
|
|
6
|
+
import { types } from "./maps.js";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import prompt from "prompt-sync";
|
|
10
|
+
function createDir(dirPath) {
|
|
11
|
+
if (fs.existsSync(dirPath))
|
|
12
|
+
return {
|
|
13
|
+
exitCode: 1,
|
|
14
|
+
message: null,
|
|
15
|
+
error: new Error("Generation directory already exists. Add the --force flag if you want to overwrite it.")
|
|
16
|
+
};
|
|
17
|
+
else
|
|
18
|
+
fs.mkdir(dirPath, (err) => {
|
|
19
|
+
if (err)
|
|
20
|
+
return {
|
|
21
|
+
exitCode: 1,
|
|
22
|
+
message: null,
|
|
23
|
+
error: err
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
exitCode: 0,
|
|
28
|
+
message: null,
|
|
29
|
+
error: null
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function deleteDir(dirPath) {
|
|
33
|
+
if (fs.existsSync(dirPath)) {
|
|
34
|
+
const files = fs.readdirSync(dirPath);
|
|
35
|
+
for (const file of files) {
|
|
36
|
+
const dir = path.join(dirPath, file);
|
|
37
|
+
if (fs.lstatSync(dir).isDirectory())
|
|
38
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
39
|
+
else
|
|
40
|
+
fs.unlinkSync(path.join(dirPath, file));
|
|
41
|
+
}
|
|
42
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function guided() {
|
|
46
|
+
const logo = ` @@@@@@@@
|
|
47
|
+
@@@@@@@@@@@
|
|
48
|
+
%%@@@@@@@@@@
|
|
49
|
+
%%%%@@@@@@
|
|
50
|
+
%%%%%%@@@
|
|
51
|
+
%%%%%%%%%@
|
|
52
|
+
%%%%%%%%%%%%
|
|
53
|
+
%%%%%%%%%%%%%%%
|
|
54
|
+
%%%%%%%%%%%%%%%%
|
|
55
|
+
#####%%%%%%%%%%%%%
|
|
56
|
+
#######%%%%%%%%%%%%
|
|
57
|
+
**#########%%%%%%%%%%%
|
|
58
|
+
*****#########%%%%%%%%
|
|
59
|
+
*********#########%%%%%%
|
|
60
|
+
+************#########%%%
|
|
61
|
+
++++++************########%
|
|
62
|
+
+++++++++*************######
|
|
63
|
+
+++++++++++*************#
|
|
64
|
+
*******++++++++++++******
|
|
65
|
+
##********++++ `;
|
|
66
|
+
console.clear();
|
|
67
|
+
console.log(logo);
|
|
68
|
+
console.log("\n");
|
|
69
|
+
sleep(1000);
|
|
70
|
+
const input = prompt({ sigint: true });
|
|
71
|
+
const host = input("Database Host: ");
|
|
72
|
+
const port = Number(input("Database Port: "));
|
|
73
|
+
const db = input("Database Name: ");
|
|
74
|
+
const user = input("Database Username: ");
|
|
75
|
+
const pass = input("Database Password: ");
|
|
76
|
+
return { host, port, db, user, pass };
|
|
77
|
+
}
|
|
78
|
+
export async function runPigeon(dir, host, port, db, user, pass) {
|
|
79
|
+
const dirResult = createDir(dir);
|
|
80
|
+
if (dirResult.exitCode !== 0)
|
|
81
|
+
return dirResult;
|
|
82
|
+
const tableQuery = await runQuery(`SELECT table_schema, table_name
|
|
83
|
+
FROM information_schema.tables
|
|
84
|
+
WHERE table_type = 'BASE TABLE'
|
|
85
|
+
AND table_schema NOT IN
|
|
86
|
+
('pg_catalog', 'information_schema');`, [], host, port, db, user, pass);
|
|
87
|
+
if (typeof tableQuery === "undefined")
|
|
88
|
+
return {
|
|
89
|
+
exitCode: 1,
|
|
90
|
+
message: null,
|
|
91
|
+
error: new Error("An SQL error has occurred.")
|
|
92
|
+
};
|
|
93
|
+
let schemas = [];
|
|
94
|
+
for (const table of tableQuery.rows) {
|
|
95
|
+
if (schemas.includes(table.table_schema))
|
|
96
|
+
continue;
|
|
97
|
+
schemas.push(table.table_schema);
|
|
98
|
+
}
|
|
99
|
+
for (const schema of schemas)
|
|
100
|
+
createDir(path.join(dir, schema));
|
|
101
|
+
for (const table of tableQuery.rows) {
|
|
102
|
+
const columnQuery = await runQuery(`SELECT *
|
|
103
|
+
FROM information_schema.columns
|
|
104
|
+
WHERE table_name = $1::varchar
|
|
105
|
+
AND table_schema = $2::varchar;`, [table.table_name, table.table_schema], host, port, db, user, pass);
|
|
106
|
+
if (typeof columnQuery === "undefined")
|
|
107
|
+
return {
|
|
108
|
+
exitCode: 1,
|
|
109
|
+
message: null,
|
|
110
|
+
error: new Error("An SQL error has occurred.")
|
|
111
|
+
};
|
|
112
|
+
const pKeyQuery = await runQuery(`SELECT ku.column_name
|
|
113
|
+
FROM information_schema.table_constraints AS tc
|
|
114
|
+
INNER JOIN information_schema.key_column_usage AS ku
|
|
115
|
+
ON tc.constraint_type = 'PRIMARY KEY'
|
|
116
|
+
AND tc.constraint_name = ku.constraint_name
|
|
117
|
+
WHERE tc.table_schema = $1::varchar
|
|
118
|
+
AND tc.table_name = $2::varchar;`, [table.table_schema, table.table_name], host, port, db, user, pass);
|
|
119
|
+
if (typeof pKeyQuery === "undefined")
|
|
120
|
+
return {
|
|
121
|
+
exitCode: 1,
|
|
122
|
+
message: null,
|
|
123
|
+
error: new Error("An SQL error has occurred.")
|
|
124
|
+
};
|
|
125
|
+
let pKeys = [];
|
|
126
|
+
for (let pKey of pKeyQuery.rows)
|
|
127
|
+
pKeys.push(pKey.column_name);
|
|
128
|
+
const fKeyQuery = await runQuery(`SELECT kcu1.table_schema AS local_schema,
|
|
129
|
+
kcu1.table_name AS local_table,
|
|
130
|
+
kcu1.column_name AS local_column,
|
|
131
|
+
kcu2.table_schema AS referenced_schema,
|
|
132
|
+
kcu2.table_name AS referenced_table,
|
|
133
|
+
kcu2.column_name AS referenced_column
|
|
134
|
+
FROM information_schema.referential_constraints AS rc
|
|
135
|
+
INNER JOIN information_schema.key_column_usage AS kcu1
|
|
136
|
+
ON kcu1.constraint_catalog = rc.constraint_catalog
|
|
137
|
+
AND kcu1.constraint_schema = rc.constraint_schema
|
|
138
|
+
AND kcu1.constraint_name = rc.constraint_name
|
|
139
|
+
INNER JOIN information_schema.key_column_usage AS kcu2
|
|
140
|
+
ON kcu2.constraint_catalog = rc.unique_constraint_catalog
|
|
141
|
+
AND
|
|
142
|
+
kcu2.constraint_schema = rc.unique_constraint_schema
|
|
143
|
+
AND kcu2.constraint_name = rc.unique_constraint_name
|
|
144
|
+
AND kcu2.ordinal_position = kcu1.ordinal_position
|
|
145
|
+
WHERE kcu1.table_schema = $1::varchar
|
|
146
|
+
AND kcu1.table_name = $2::varchar;`, [table.table_schema, table.table_name], host, port, db, user, pass);
|
|
147
|
+
if (typeof fKeyQuery === "undefined")
|
|
148
|
+
return {
|
|
149
|
+
exitCode: 1,
|
|
150
|
+
message: null,
|
|
151
|
+
error: new Error("An SQL error has occurred.")
|
|
152
|
+
};
|
|
153
|
+
let ts = clientMaker(0, host, port, db, user, pass);
|
|
154
|
+
ts += "\n\n";
|
|
155
|
+
ts += createClass(table.table_name, columnQuery.rows, pKeys, fKeyQuery.rows);
|
|
156
|
+
ts += "\n\n";
|
|
157
|
+
ts += createGetAll(table.table_schema, table.table_name, columnQuery.rows);
|
|
158
|
+
ts += "\n\n";
|
|
159
|
+
let keys = [...pKeys];
|
|
160
|
+
for (let fKey of fKeyQuery.rows)
|
|
161
|
+
keys.push(fKey.local_column.replaceAll(" ", ""));
|
|
162
|
+
for (const keyCombination of getCombinations(keys)) {
|
|
163
|
+
ts += createGet(table.table_schema, table.table_name, columnQuery.rows, keyCombination);
|
|
164
|
+
ts += "\n\n";
|
|
165
|
+
}
|
|
166
|
+
let nonDefaults = [];
|
|
167
|
+
let softDefaults = [];
|
|
168
|
+
let hardDefaults = [];
|
|
169
|
+
for (const column of columnQuery.rows) {
|
|
170
|
+
if (column.column_default === null && column.is_identity === "NO")
|
|
171
|
+
nonDefaults.push(column);
|
|
172
|
+
if ((column.column_default !== null && !column.column_default.includes("nextval")) || (column.is_identity === "YES" && column.identity_generation === "BY DEFAULT"))
|
|
173
|
+
softDefaults.push(column);
|
|
174
|
+
if ((column.column_default !== null && column.column_default.includes("nextval")) || (column.is_identity === "YES" && column.identity_generation === "ALWAYS"))
|
|
175
|
+
hardDefaults.push(column);
|
|
176
|
+
}
|
|
177
|
+
ts += createAdd(table.table_schema, table.table_name, nonDefaults, [], hardDefaults, fKeyQuery.rows) + "\n\n";
|
|
178
|
+
for (const softCombination of getCombinations(softDefaults))
|
|
179
|
+
ts += createAdd(table.table_schema, table.table_name, nonDefaults, softCombination, hardDefaults, fKeyQuery.rows) + "\n\n";
|
|
180
|
+
const regex = /import ({?.*?}?) from "(.*?)";\n/g;
|
|
181
|
+
let match;
|
|
182
|
+
let importObjects = [];
|
|
183
|
+
while ((match = regex.exec(ts)) !== null) {
|
|
184
|
+
ts = ts.replace(match[0], "");
|
|
185
|
+
let fileExists = false;
|
|
186
|
+
for (const object of importObjects) {
|
|
187
|
+
const isBrackets = match[1][0] === "{";
|
|
188
|
+
if (object.file === match[2] && isBrackets === object.brackets) {
|
|
189
|
+
fileExists = true;
|
|
190
|
+
object.functions.push(match[1]);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (!fileExists) {
|
|
194
|
+
importObjects.push({
|
|
195
|
+
file: match[2],
|
|
196
|
+
functions: [match[1]],
|
|
197
|
+
brackets: match[1][0] === "{"
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
let importString = "";
|
|
202
|
+
for (const object of importObjects) {
|
|
203
|
+
importString += "import ";
|
|
204
|
+
if (object.brackets)
|
|
205
|
+
importString += "{";
|
|
206
|
+
for (const fun of object.functions) {
|
|
207
|
+
if (object.brackets)
|
|
208
|
+
importString += fun.slice(1, -1) + ", ";
|
|
209
|
+
else
|
|
210
|
+
importString += fun + ", ";
|
|
211
|
+
}
|
|
212
|
+
importString = importString.slice(0, -2);
|
|
213
|
+
if (object.brackets)
|
|
214
|
+
importString += "}";
|
|
215
|
+
importString += " from \"" + object.file + "\";\n";
|
|
216
|
+
}
|
|
217
|
+
importString += "import pg from \"pg\";\n\n";
|
|
218
|
+
importString += "const {Client} = pg;\n\n";
|
|
219
|
+
ts = importString + ts;
|
|
220
|
+
fs.writeFileSync(path.join(dir, table.table_schema, table.table_name + ".ts"), ts);
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
exitCode: 0,
|
|
224
|
+
message: "Generation Completed Successfully",
|
|
225
|
+
error: null
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function createClass(tableName, columns, primaryKeys, foreignKeys) {
|
|
229
|
+
let text = "";
|
|
230
|
+
text += "export class " + singularize(nameBeautifier(tableName)).replaceAll(" ", "") + " {\n";
|
|
231
|
+
for (const column of columns) {
|
|
232
|
+
let dataType = types.get(column.data_type);
|
|
233
|
+
if (column.is_nullable == "YES")
|
|
234
|
+
dataType += " | undefined";
|
|
235
|
+
let isPrimaryKey = false;
|
|
236
|
+
for (const pKey of primaryKeys)
|
|
237
|
+
if (pKey === column.column_name)
|
|
238
|
+
isPrimaryKey = true;
|
|
239
|
+
let foreignKeyIndex = -1;
|
|
240
|
+
for (let i = 0; i < foreignKeys.length; i++)
|
|
241
|
+
if (foreignKeys[i].local_column === column.column_name)
|
|
242
|
+
foreignKeyIndex = i;
|
|
243
|
+
text += "\t/**\n";
|
|
244
|
+
if (isPrimaryKey)
|
|
245
|
+
text += "\t * A primary key representing the " + nameBeautifier(column.column_name) + " for the " + nameBeautifier(tableName) + " table.\n";
|
|
246
|
+
else if (foreignKeyIndex !== -1)
|
|
247
|
+
text += "\t * A foreign key representing the " + nameBeautifier(column.column_name) + " for the " + nameBeautifier(tableName) + " table and referencing the " + nameBeautifier(foreignKeys[foreignKeyIndex].referenced_column) + " in the " + nameBeautifier(foreignKeys[foreignKeyIndex].referenced_table) + " table in the " + nameBeautifier(foreignKeys[foreignKeyIndex].referenced_schema) + " schema.\n";
|
|
248
|
+
else
|
|
249
|
+
text += "\t * The " + nameBeautifier(column.column_name) + " for the " + nameBeautifier(tableName) + " table.\n";
|
|
250
|
+
text += "\t * @type {" + dataType + "}\n";
|
|
251
|
+
text += "\t */\n";
|
|
252
|
+
text += "\t" + column.column_name + ": " + dataType;
|
|
253
|
+
if (column.column_default !== null) {
|
|
254
|
+
if (!column.column_default.includes("nextval")) {
|
|
255
|
+
if (types.get(column.data_type) === "Date") {
|
|
256
|
+
if (column.column_default)
|
|
257
|
+
text += " = new Date()";
|
|
258
|
+
else
|
|
259
|
+
text += " = new Date(" + column.column_default.replace(' ', 'T') + ")";
|
|
260
|
+
}
|
|
261
|
+
else if (types.get(column.data_type) === "number")
|
|
262
|
+
text += " = " + column.column_default;
|
|
263
|
+
else
|
|
264
|
+
text += " = \"" + column.column_default + "\"";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
text += ";\n";
|
|
268
|
+
}
|
|
269
|
+
text += "\n";
|
|
270
|
+
text += "\t/**\n";
|
|
271
|
+
text += "\t * Creates a new object for the " + nameBeautifier(tableName) + " table.\n";
|
|
272
|
+
text += "\t * \n";
|
|
273
|
+
for (const column of columns) {
|
|
274
|
+
text += "\t * ";
|
|
275
|
+
text += "@param {" + types.get(column.data_type);
|
|
276
|
+
if (column.is_nullable == "YES")
|
|
277
|
+
text += " | undefined";
|
|
278
|
+
text += "} " + column.column_name;
|
|
279
|
+
text += " - The " + nameBeautifier(column.column_name) + " of the " + nameBeautifier(tableName) + " table. \n";
|
|
280
|
+
}
|
|
281
|
+
text += "\t */\n";
|
|
282
|
+
text += "\tconstructor(";
|
|
283
|
+
for (const column of columns) {
|
|
284
|
+
text += column.column_name + ": " + types.get(column.data_type);
|
|
285
|
+
if (column.is_nullable == "YES")
|
|
286
|
+
text += " | undefined";
|
|
287
|
+
text += ", ";
|
|
288
|
+
}
|
|
289
|
+
text = text.slice(0, -2);
|
|
290
|
+
text += ") {\n";
|
|
291
|
+
for (const column of columns)
|
|
292
|
+
text += "\t\tthis." + column.column_name + " = " + column.column_name + ";\n";
|
|
293
|
+
text += "\t}\n";
|
|
294
|
+
text += "}";
|
|
295
|
+
return text;
|
|
296
|
+
}
|
|
297
|
+
export function clientMaker(baseTabs, host, port, db, user, pass) {
|
|
298
|
+
let text = "";
|
|
299
|
+
text += tabsInserter(baseTabs) + "const client = new Client({\n";
|
|
300
|
+
text += tabsInserter(baseTabs + 1) + "host: \"" + host + "\",\n";
|
|
301
|
+
text += tabsInserter(baseTabs + 1) + "port: " + port + ",\n";
|
|
302
|
+
text += tabsInserter(baseTabs + 1) + "database: \"" + db + "\",\n";
|
|
303
|
+
text += tabsInserter(baseTabs + 1) + "user: \"" + user + "\",\n";
|
|
304
|
+
text += tabsInserter(baseTabs + 1) + "password: \"" + pass + "\"\n";
|
|
305
|
+
text += tabsInserter(baseTabs) + "});\n";
|
|
306
|
+
return text;
|
|
307
|
+
}
|
|
308
|
+
function createGetAll(tableSchema, tableName, columns) {
|
|
309
|
+
let text = "";
|
|
310
|
+
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
311
|
+
const varName = nameBeautifier(tableName).replaceAll(" ", "")[0].toLowerCase() + nameBeautifier(tableName).replaceAll(" ", "").substring(1);
|
|
312
|
+
text += "/**\n";
|
|
313
|
+
text += " * Gets all " + className + " objects from the database.\n";
|
|
314
|
+
text += " *\n";
|
|
315
|
+
text += " * @returns {Promise<" + className + "[]>} - A Promise object returning an array of " + nameBeautifier(tableName) + ".\n";
|
|
316
|
+
text += " */\n";
|
|
317
|
+
text += "export async function getAll" + nameBeautifier(tableName).replaceAll(" ", "") + "(): Promise<" + className + "[]> {\n";
|
|
318
|
+
text += queryMaker(1, varName, "SELECT * FROM " + tableSchema + "." + tableName + ";", "");
|
|
319
|
+
text += "\n\n";
|
|
320
|
+
text += arrayMaker(1, varName, className, columns) + "\n";
|
|
321
|
+
text += "\treturn " + varName + ";\n";
|
|
322
|
+
text += "}";
|
|
323
|
+
return text;
|
|
324
|
+
}
|
|
325
|
+
function createGet(tableSchema, tableName, columns, keys) {
|
|
326
|
+
let text = "";
|
|
327
|
+
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
328
|
+
const varName = nameBeautifier(tableName).replaceAll(" ", "")[0].toLowerCase() + nameBeautifier(tableName).replaceAll(" ", "").substring(1);
|
|
329
|
+
text += "/**\n";
|
|
330
|
+
text += " * Gets " + className + " objects from the database by ";
|
|
331
|
+
for (const key of keys)
|
|
332
|
+
text += key + " and ";
|
|
333
|
+
text = text.slice(0, -5) + ".\n";
|
|
334
|
+
text += " *\n";
|
|
335
|
+
for (const key of keys) {
|
|
336
|
+
const column = columns.find(column => column.column_name == key);
|
|
337
|
+
text += " * ";
|
|
338
|
+
text += "@param {" + types.get(column.data_type);
|
|
339
|
+
text += "} " + column.column_name;
|
|
340
|
+
text += " - The " + nameBeautifier(column.column_name) + " of the " + nameBeautifier(tableName) + " table.\n";
|
|
341
|
+
}
|
|
342
|
+
text += " * @returns {Promise<" + className + "[]>} - A Promise object returning an array of " + nameBeautifier(tableName) + ".\n";
|
|
343
|
+
text += " */\n";
|
|
344
|
+
text += "export async function get" + nameBeautifier(tableName).replaceAll(" ", "") + "By";
|
|
345
|
+
for (const key of keys)
|
|
346
|
+
text += nameBeautifier(key).replaceAll(" ", "") + "And";
|
|
347
|
+
text = text.slice(0, -3);
|
|
348
|
+
text += "(";
|
|
349
|
+
for (const key of keys)
|
|
350
|
+
text += key + ": " + types.get(columns.find(column => column.column_name == key).data_type) + ", ";
|
|
351
|
+
text = text.slice(0, -2);
|
|
352
|
+
text += "): Promise<" + className + "[]> {\n";
|
|
353
|
+
text += "\tif (";
|
|
354
|
+
for (const key of keys)
|
|
355
|
+
text += key + " === undefined || ";
|
|
356
|
+
text = text.slice(0, -4);
|
|
357
|
+
text += ")\n" + "\t\tthrow \"Missing Parameters\";\n\n";
|
|
358
|
+
let query = "SELECT * FROM " + tableSchema + "." + tableName + " WHERE ";
|
|
359
|
+
let parameters = "";
|
|
360
|
+
for (let i = 0; i < keys.length; i++) {
|
|
361
|
+
query += keys[i] + " = " + "$" + (i + 1) + "::" + columns.find(column => column.column_name == keys[i]).data_type + " AND ";
|
|
362
|
+
parameters += keys[i] + ", ";
|
|
363
|
+
}
|
|
364
|
+
query = query.slice(0, -5) + ";";
|
|
365
|
+
parameters = parameters.slice(0, -2);
|
|
366
|
+
text += queryMaker(1, varName, query, parameters);
|
|
367
|
+
text += "\n\n";
|
|
368
|
+
text += arrayMaker(1, varName, className, columns) + "\n";
|
|
369
|
+
text += "\treturn " + varName + ";\n";
|
|
370
|
+
text += "}";
|
|
371
|
+
return text;
|
|
372
|
+
}
|
|
373
|
+
function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaults, foreignKeys) {
|
|
374
|
+
let text = "";
|
|
375
|
+
const className = singularize(nameBeautifier(tableName)).replaceAll(" ", "");
|
|
376
|
+
for (const foreignKey of foreignKeys) {
|
|
377
|
+
text += "import {get" + nameBeautifier(foreignKey.referenced_table).replaceAll(" ", "") + "By" + nameBeautifier(foreignKey.referenced_column).replaceAll(" ", "") + "} from \".";
|
|
378
|
+
if (tableSchema !== foreignKey.referenced_schema)
|
|
379
|
+
text += "./" + foreignKey.referenced_schema;
|
|
380
|
+
text += "/" + foreignKey.referenced_table + ".js\";\n";
|
|
381
|
+
}
|
|
382
|
+
text += "/**\n";
|
|
383
|
+
text += " * Adds the provided " + className + " object to the database.\n";
|
|
384
|
+
text += " *\n";
|
|
385
|
+
let columns = nonDefaults.concat(softDefaults);
|
|
386
|
+
columns.sort((a, b) => a.ordinal_position - b.ordinal_position);
|
|
387
|
+
for (const column of columns) {
|
|
388
|
+
text += " * ";
|
|
389
|
+
text += "@param {" + types.get(column.data_type);
|
|
390
|
+
if (column.is_nullable === "YES")
|
|
391
|
+
text += " | undefined";
|
|
392
|
+
text += "} " + column.column_name;
|
|
393
|
+
text += " - The " + nameBeautifier(column.column_name) + " to be inserted into the " + nameBeautifier(tableName) + " table.\n";
|
|
394
|
+
}
|
|
395
|
+
text += " * @returns {Promise<" + className + ">} - A Promise object returning the inserted " + nameBeautifier(tableName) + ".\n";
|
|
396
|
+
if (foreignKeys.length > 0) {
|
|
397
|
+
text += " * @throws string An exception in the case of the ";
|
|
398
|
+
for (const foreignKey of foreignKeys)
|
|
399
|
+
text += nameBeautifier(foreignKey.local_column) + " or the ";
|
|
400
|
+
text = text.slice(0, -8);
|
|
401
|
+
text += " not existing in their table.\n";
|
|
402
|
+
}
|
|
403
|
+
text += " */\n";
|
|
404
|
+
text += "export async function add" + className;
|
|
405
|
+
if (softDefaults.length > 0) {
|
|
406
|
+
text += "With";
|
|
407
|
+
for (const softDefault of softDefaults)
|
|
408
|
+
text += nameBeautifier(softDefault.column_name).replaceAll(" ", "") + "And";
|
|
409
|
+
text = text.slice(0, -3);
|
|
410
|
+
}
|
|
411
|
+
text += "(";
|
|
412
|
+
for (const column of columns) {
|
|
413
|
+
text += column.column_name + ": " + types.get(column.data_type);
|
|
414
|
+
if (column.is_nullable === "YES")
|
|
415
|
+
text += " | undefined";
|
|
416
|
+
text += ", ";
|
|
417
|
+
}
|
|
418
|
+
text = text.slice(0, -2);
|
|
419
|
+
text += "): Promise<" + className + "> {\n";
|
|
420
|
+
for (const foreignKey of foreignKeys) {
|
|
421
|
+
text += "\tconst verify" + nameBeautifier(foreignKey.local_column).replaceAll(" ", "") + " = await get" + nameBeautifier(foreignKey.referenced_table).replaceAll(" ", "") + "By" + nameBeautifier(foreignKey.referenced_column).replaceAll(" ", "") + "(" + foreignKey.local_column + ");\n";
|
|
422
|
+
text += "\tif (verify" + nameBeautifier(foreignKey.local_column).replaceAll(" ", "") + ".length === 0)\n";
|
|
423
|
+
text += "\t\tthrow \"The " + nameBeautifier(foreignKey.local_column) + " provided does not exist.\";\n\n";
|
|
424
|
+
}
|
|
425
|
+
let query = "INSERT INTO " + tableSchema + "." + tableName + " (";
|
|
426
|
+
for (const column of columns)
|
|
427
|
+
query += column.column_name + ", ";
|
|
428
|
+
query = query.slice(0, -2);
|
|
429
|
+
query += ") VALUES (";
|
|
430
|
+
let parameters = "";
|
|
431
|
+
for (let i = 0; i < columns.length; i++) {
|
|
432
|
+
query += "$" + (i + 1) + "::" + columns[i].data_type + ", ";
|
|
433
|
+
parameters += columns[i].column_name + ", ";
|
|
434
|
+
}
|
|
435
|
+
query = query.slice(0, -2);
|
|
436
|
+
parameters = parameters.slice(0, -2);
|
|
437
|
+
query += ") RETURNING *;";
|
|
438
|
+
text += queryMaker(1, "insert", query, parameters);
|
|
439
|
+
text += "\n\n";
|
|
440
|
+
text += "\treturn new " + className + "(\n";
|
|
441
|
+
columns = columns.concat(hardDefaults);
|
|
442
|
+
columns.sort((a, b) => a.ordinal_position - b.ordinal_position);
|
|
443
|
+
for (const column of columns)
|
|
444
|
+
text += "\t\tinsertQuery.rows[0]." + column.column_name + ",\n";
|
|
445
|
+
text = text.slice(0, -2);
|
|
446
|
+
text += "\n";
|
|
447
|
+
text += "\t);\n";
|
|
448
|
+
text += "}";
|
|
449
|
+
return text;
|
|
450
|
+
}
|