@andymic/pigeon 1.0.1 → 1.1.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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/index.js +82 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andymic/pigeon",
3
- "version": "1.0.1",
3
+ "version": "1.1.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": [
@@ -35,5 +35,5 @@
35
35
  "pg": "^8.13.1",
36
36
  "prompt-sync": "^4.2.0"
37
37
  },
38
- "gitHead": "d782348579c93dd5df6f54dd7fb6f56d8bc71275"
38
+ "gitHead": "6da3fed7416ff254af875d4efbb5fc0f66e1f553"
39
39
  }
package/src/index.js CHANGED
@@ -98,6 +98,38 @@ export async function runPigeon(dir, host, port, db, user, pass) {
98
98
  }
99
99
  for (const schema of schemas)
100
100
  createDir(path.join(dir, schema));
101
+ const customTypeQuery = await runQuery(`SELECT t.oid, t.typname
102
+ FROM pg_type t
103
+ WHERE (t.typrelid = 0 OR t.typrelid IN (SELECT oid FROM pg_class WHERE relkind = 'c'))
104
+ AND t.typelem = 0
105
+ AND t.typnamespace NOT IN
106
+ (SELECT oid FROM pg_namespace WHERE nspname IN ('pg_catalog', 'information_schema'));`, [], host, port, db, user, pass);
107
+ if (typeof customTypeQuery === "undefined")
108
+ return {
109
+ exitCode: 1,
110
+ message: null,
111
+ error: new Error("An SQL error has occurred.")
112
+ };
113
+ const customTypes = [];
114
+ for (const type of customTypeQuery.rows) {
115
+ const enumQuery = await runQuery(`SELECT enumlabel
116
+ FROM pg_enum
117
+ WHERE enumtypid = $1::oid
118
+ ORDER BY enumsortorder;`, [type.oid], host, port, db, user, pass);
119
+ if (typeof enumQuery === "undefined")
120
+ return {
121
+ exitCode: 1,
122
+ message: null,
123
+ error: new Error("An SQL error has occurred.")
124
+ };
125
+ let labels = [];
126
+ for (const enumLabel of enumQuery.rows)
127
+ labels.push(enumLabel.enumlabel);
128
+ customTypes.push({
129
+ name: type.typname,
130
+ labels: labels
131
+ });
132
+ }
101
133
  for (const table of tableQuery.rows) {
102
134
  const columnQuery = await runQuery(`SELECT *
103
135
  FROM information_schema.columns
@@ -152,6 +184,24 @@ export async function runPigeon(dir, host, port, db, user, pass) {
152
184
  };
153
185
  let ts = clientMaker(0, host, port, db, user, pass);
154
186
  ts += "\n\n";
187
+ for (const customType of customTypes) {
188
+ for (const column of columnQuery.rows) {
189
+ if (customType.name === column.udt_name) {
190
+ const enumName = nameBeautifier(customType.name).replaceAll(" ", "");
191
+ ts += "/**\n An Enum representing the " + nameBeautifier(customType.name).toLowerCase() + ".\n * @readonly\n * @enum {string}\n */\n";
192
+ ts += "class " + enumName + "{\n";
193
+ let longestLabel = 0;
194
+ for (const label of customType.labels)
195
+ if (label.length > longestLabel)
196
+ longestLabel = label.length;
197
+ for (const label of customType.labels)
198
+ ts += "\tstatic " + label.toUpperCase().replaceAll(/[^a-zA-Z0-9$]/g, "_") + ": string" + " ".repeat(longestLabel - label.length + 1) + "= \"" + label + "\";\n";
199
+ ts += "}\n";
200
+ }
201
+ }
202
+ }
203
+ if (ts.slice(-2) !== "\n\n")
204
+ ts += "\n";
155
205
  ts += createClass(table.table_name, columnQuery.rows, pKeys, fKeyQuery.rows);
156
206
  ts += "\n\n";
157
207
  ts += createGetAll(table.table_schema, table.table_name, columnQuery.rows);
@@ -174,9 +224,9 @@ export async function runPigeon(dir, host, port, db, user, pass) {
174
224
  if ((column.column_default !== null && column.column_default.includes("nextval")) || (column.is_identity === "YES" && column.identity_generation === "ALWAYS"))
175
225
  hardDefaults.push(column);
176
226
  }
177
- ts += createAdd(table.table_schema, table.table_name, nonDefaults, [], hardDefaults, fKeyQuery.rows) + "\n\n";
227
+ ts += createAdd(table.table_schema, table.table_name, nonDefaults, [], hardDefaults.concat(softDefaults), fKeyQuery.rows) + "\n\n";
178
228
  for (const softCombination of getCombinations(softDefaults))
179
- ts += createAdd(table.table_schema, table.table_name, nonDefaults, softCombination, hardDefaults, fKeyQuery.rows) + "\n\n";
229
+ ts += createAdd(table.table_schema, table.table_name, nonDefaults, softCombination, hardDefaults.concat(softDefaults.filter(n => !getCombinations(softDefaults).includes(n))), fKeyQuery.rows) + "\n\n";
180
230
  const regex = /import ({?.*?}?) from "(.*?)";\n/g;
181
231
  let match;
182
232
  let importObjects = [];
@@ -200,6 +250,7 @@ export async function runPigeon(dir, host, port, db, user, pass) {
200
250
  }
201
251
  let importString = "";
202
252
  for (const object of importObjects) {
253
+ object.functions = [...new Set(object.functions)];
203
254
  importString += "import ";
204
255
  if (object.brackets)
205
256
  importString += "{";
@@ -230,6 +281,8 @@ function createClass(tableName, columns, primaryKeys, foreignKeys) {
230
281
  text += "export class " + singularize(nameBeautifier(tableName)).replaceAll(" ", "") + " {\n";
231
282
  for (const column of columns) {
232
283
  let dataType = types.get(column.data_type);
284
+ if (dataType === undefined)
285
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
233
286
  if (column.is_nullable == "YES")
234
287
  dataType += " | undefined";
235
288
  let isPrimaryKey = false;
@@ -252,13 +305,13 @@ function createClass(tableName, columns, primaryKeys, foreignKeys) {
252
305
  text += "\t" + column.column_name + ": " + dataType;
253
306
  if (column.column_default !== null) {
254
307
  if (!column.column_default.includes("nextval")) {
255
- if (types.get(column.data_type) === "Date") {
308
+ if (dataType === "Date") {
256
309
  if (column.column_default)
257
310
  text += " = new Date()";
258
311
  else
259
312
  text += " = new Date(" + column.column_default.replace(' ', 'T') + ")";
260
313
  }
261
- else if (types.get(column.data_type) === "number")
314
+ else if (dataType === "number")
262
315
  text += " = " + column.column_default;
263
316
  else
264
317
  text += " = \"" + column.column_default + "\"";
@@ -271,8 +324,11 @@ function createClass(tableName, columns, primaryKeys, foreignKeys) {
271
324
  text += "\t * Creates a new object for the " + nameBeautifier(tableName) + " table.\n";
272
325
  text += "\t * \n";
273
326
  for (const column of columns) {
327
+ let dataType = types.get(column.data_type);
328
+ if (dataType === undefined)
329
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
274
330
  text += "\t * ";
275
- text += "@param {" + types.get(column.data_type);
331
+ text += "@param {" + dataType;
276
332
  if (column.is_nullable == "YES")
277
333
  text += " | undefined";
278
334
  text += "} " + column.column_name;
@@ -281,7 +337,10 @@ function createClass(tableName, columns, primaryKeys, foreignKeys) {
281
337
  text += "\t */\n";
282
338
  text += "\tconstructor(";
283
339
  for (const column of columns) {
284
- text += column.column_name + ": " + types.get(column.data_type);
340
+ let dataType = types.get(column.data_type);
341
+ if (dataType === undefined)
342
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
343
+ text += column.column_name + ": " + dataType;
285
344
  if (column.is_nullable == "YES")
286
345
  text += " | undefined";
287
346
  text += ", ";
@@ -334,8 +393,11 @@ function createGet(tableSchema, tableName, columns, keys) {
334
393
  text += " *\n";
335
394
  for (const key of keys) {
336
395
  const column = columns.find(column => column.column_name == key);
396
+ let dataType = types.get(column.data_type);
397
+ if (dataType === undefined)
398
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
337
399
  text += " * ";
338
- text += "@param {" + types.get(column.data_type);
400
+ text += "@param {" + dataType;
339
401
  text += "} " + column.column_name;
340
402
  text += " - The " + nameBeautifier(column.column_name) + " of the " + nameBeautifier(tableName) + " table.\n";
341
403
  }
@@ -385,8 +447,11 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
385
447
  let columns = nonDefaults.concat(softDefaults);
386
448
  columns.sort((a, b) => a.ordinal_position - b.ordinal_position);
387
449
  for (const column of columns) {
450
+ let dataType = types.get(column.data_type);
451
+ if (dataType === undefined)
452
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
388
453
  text += " * ";
389
- text += "@param {" + types.get(column.data_type);
454
+ text += "@param {" + dataType;
390
455
  if (column.is_nullable === "YES")
391
456
  text += " | undefined";
392
457
  text += "} " + column.column_name;
@@ -410,7 +475,10 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
410
475
  }
411
476
  text += "(";
412
477
  for (const column of columns) {
413
- text += column.column_name + ": " + types.get(column.data_type);
478
+ let dataType = types.get(column.data_type);
479
+ if (dataType === undefined)
480
+ dataType = nameBeautifier(column.udt_name).replaceAll(" ", "");
481
+ text += column.column_name + ": " + dataType;
414
482
  if (column.is_nullable === "YES")
415
483
  text += " | undefined";
416
484
  text += ", ";
@@ -429,7 +497,10 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
429
497
  query += ") VALUES (";
430
498
  let parameters = "";
431
499
  for (let i = 0; i < columns.length; i++) {
432
- query += "$" + (i + 1) + "::" + columns[i].data_type + ", ";
500
+ let dataType = columns[i].data_type;
501
+ if (dataType === "USER-DEFINED")
502
+ dataType = "character varying";
503
+ query += "$" + (i + 1) + "::" + dataType + ", ";
433
504
  parameters += columns[i].column_name + ", ";
434
505
  }
435
506
  query = query.slice(0, -2);
@@ -439,6 +510,7 @@ function createAdd(tableSchema, tableName, nonDefaults, softDefaults, hardDefaul
439
510
  text += "\n\n";
440
511
  text += "\treturn new " + className + "(\n";
441
512
  columns = columns.concat(hardDefaults);
513
+ columns = [...new Set(columns)];
442
514
  columns.sort((a, b) => a.ordinal_position - b.ordinal_position);
443
515
  for (const column of columns)
444
516
  text += "\t\tinsertQuery.rows[0]." + column.column_name + ",\n";