midway-model-gen 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.idea/codeStyles/Project.xml +57 -0
  2. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  3. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/prettier.xml +6 -0
  6. package/.idea/test.iml +8 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/CHANGELOG.md +161 -0
  9. package/CONTRIBUTING.md +51 -0
  10. package/DEVELOPER.md +30 -0
  11. package/LICENSE +21 -0
  12. package/README.md +94 -0
  13. package/USECASES.md +53 -0
  14. package/bin/typeorm-model-generator +6 -0
  15. package/dist/package.json +106 -0
  16. package/dist/src/Engine.d.ts +7 -0
  17. package/dist/src/Engine.js +47 -0
  18. package/dist/src/IConnectionOptions.d.ts +14 -0
  19. package/dist/src/IConnectionOptions.js +22 -0
  20. package/dist/src/IGenerationOptions.d.ts +24 -0
  21. package/dist/src/IGenerationOptions.js +33 -0
  22. package/dist/src/ModelCustomization.d.ts +4 -0
  23. package/dist/src/ModelCustomization.js +256 -0
  24. package/dist/src/ModelGeneration.d.ts +4 -0
  25. package/dist/src/ModelGeneration.js +247 -0
  26. package/dist/src/NamingStrategy.d.ts +10 -0
  27. package/dist/src/NamingStrategy.js +61 -0
  28. package/dist/src/Utils.d.ts +6 -0
  29. package/dist/src/Utils.js +68 -0
  30. package/dist/src/drivers/AbstractDriver.d.ts +30 -0
  31. package/dist/src/drivers/AbstractDriver.js +258 -0
  32. package/dist/src/drivers/MariaDbDriver.d.ts +4 -0
  33. package/dist/src/drivers/MariaDbDriver.js +11 -0
  34. package/dist/src/drivers/MssqlDriver.d.ts +25 -0
  35. package/dist/src/drivers/MssqlDriver.js +408 -0
  36. package/dist/src/drivers/MysqlDriver.d.ts +27 -0
  37. package/dist/src/drivers/MysqlDriver.js +439 -0
  38. package/dist/src/drivers/OracleDriver.d.ts +25 -0
  39. package/dist/src/drivers/OracleDriver.js +316 -0
  40. package/dist/src/drivers/PostgresDriver.d.ts +31 -0
  41. package/dist/src/drivers/PostgresDriver.js +542 -0
  42. package/dist/src/drivers/SqliteDriver.d.ts +28 -0
  43. package/dist/src/drivers/SqliteDriver.js +308 -0
  44. package/dist/src/index.d.ts +1 -0
  45. package/dist/src/index.js +667 -0
  46. package/dist/src/library.d.ts +11 -0
  47. package/dist/src/library.js +14 -0
  48. package/dist/src/models/Column.d.ts +24 -0
  49. package/dist/src/models/Column.js +3 -0
  50. package/dist/src/models/Entity.d.ts +21 -0
  51. package/dist/src/models/Entity.js +3 -0
  52. package/dist/src/models/Index.d.ts +9 -0
  53. package/dist/src/models/Index.js +3 -0
  54. package/dist/src/models/Relation.d.ts +11 -0
  55. package/dist/src/models/Relation.js +3 -0
  56. package/dist/src/models/RelationId.d.ts +5 -0
  57. package/dist/src/models/RelationId.js +3 -0
  58. package/dist/src/models/RelationInternal.d.ts +11 -0
  59. package/dist/src/models/RelationInternal.js +3 -0
  60. package/dist/src/templates/entity.mst +47 -0
  61. package/dist/src/templates/index.mst +5 -0
  62. package/dist/src/templates/ormconfig.mst +17 -0
  63. package/dist/src/templates/tsconfig.mst +10 -0
  64. package/npminstall-debug.log +175 -0
  65. package/package.json +106 -0
@@ -0,0 +1,439 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const TypeormDriver = require("typeorm/driver/mysql/MysqlDriver");
4
+ const TomgUtils = require("../Utils");
5
+ const AbstractDriver_1 = require("./AbstractDriver");
6
+ class MysqlDriver extends AbstractDriver_1.default {
7
+ constructor() {
8
+ super();
9
+ this.defaultValues = new TypeormDriver.MysqlDriver({
10
+ options: { replication: undefined },
11
+ }).dataTypeDefaults;
12
+ this.EngineName = "MySQL";
13
+ this.standardPort = 3306;
14
+ this.standardUser = "root";
15
+ this.standardSchema = "";
16
+ try {
17
+ // eslint-disable-next-line import/no-extraneous-dependencies, global-require, import/no-unresolved
18
+ this.MYSQL = require("mysql2");
19
+ }
20
+ catch (error) {
21
+ TomgUtils.LogError("", false, error);
22
+ throw error;
23
+ }
24
+ }
25
+ async GetAllTables(schemas, dbNames) {
26
+ const response = await this.ExecQuery(`SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_SCHEMA as DB_NAME
27
+ FROM information_schema.tables
28
+ WHERE table_type='BASE TABLE'
29
+ AND table_schema IN (${MysqlDriver.buildEscapedObjectList(dbNames)})`);
30
+ // const response = await this.GetAllTablesQuery(schemas, dbNames);
31
+ const ret = [];
32
+ response.forEach((val) => {
33
+ ret.push({
34
+ columns: [],
35
+ indices: [],
36
+ relations: [],
37
+ relationIds: [],
38
+ sqlName: val.TABLE_NAME,
39
+ tscName: val.TABLE_NAME,
40
+ fileName: val.TABLE_NAME,
41
+ database: dbNames.length > 1 ? val.DB_NAME : "",
42
+ schema: val.TABLE_SCHEMA,
43
+ fileImports: [],
44
+ });
45
+ });
46
+ return ret;
47
+ }
48
+ async GetCoulmnsFromEntity(entities, schemas, dbNames) {
49
+ const response = await this.ExecQuery(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
50
+ DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
51
+ CASE WHEN EXTRA like '%auto_increment%' THEN 1 ELSE 0 END IsIdentity, COLUMN_TYPE, COLUMN_KEY, COLUMN_COMMENT
52
+ FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA IN (${MysqlDriver.buildEscapedObjectList(dbNames)})
53
+ order by ordinal_position`);
54
+ entities.forEach((ent) => {
55
+ response
56
+ .filter((filterVal) => filterVal.TABLE_NAME === ent.tscName)
57
+ .forEach((resp) => {
58
+ const tscName = resp.COLUMN_NAME;
59
+ let tscType = "";
60
+ const options = {
61
+ name: resp.COLUMN_NAME,
62
+ };
63
+ const generated = resp.IsIdentity === 1 ? true : undefined;
64
+ const defaultValue = MysqlDriver.ReturnDefaultValueFunction(resp.COLUMN_DEFAULT, resp.DATA_TYPE);
65
+ let columnType = resp.DATA_TYPE;
66
+ if (resp.IS_NULLABLE === "YES")
67
+ options.nullable = true;
68
+ if (resp.COLUMN_KEY === "UNI")
69
+ options.unique = true;
70
+ if (resp.COLUMN_COMMENT)
71
+ options.comment = resp.COLUMN_COMMENT;
72
+ if (resp.COLUMN_TYPE.endsWith(" unsigned"))
73
+ options.unsigned = true;
74
+ switch (resp.DATA_TYPE) {
75
+ case "int":
76
+ tscType = "number";
77
+ break;
78
+ case "bit":
79
+ if (resp.COLUMN_TYPE === "bit(1)") {
80
+ tscType = "boolean";
81
+ }
82
+ else {
83
+ tscType = "number";
84
+ }
85
+ break;
86
+ case "tinyint":
87
+ if (resp.COLUMN_TYPE === "tinyint(1)") {
88
+ options.width = 1;
89
+ tscType = "boolean";
90
+ }
91
+ else {
92
+ tscType = "number";
93
+ }
94
+ break;
95
+ case "smallint":
96
+ tscType = "number";
97
+ break;
98
+ case "mediumint":
99
+ tscType = "number";
100
+ break;
101
+ case "bigint":
102
+ tscType = "string";
103
+ break;
104
+ case "float":
105
+ tscType = "number";
106
+ break;
107
+ case "double":
108
+ tscType = "number";
109
+ break;
110
+ case "decimal":
111
+ tscType = "string";
112
+ break;
113
+ case "date":
114
+ tscType = "string";
115
+ break;
116
+ case "datetime":
117
+ tscType = "Date";
118
+ break;
119
+ case "timestamp":
120
+ tscType = "Date";
121
+ break;
122
+ case "time":
123
+ tscType = "string";
124
+ break;
125
+ case "year":
126
+ tscType = "number";
127
+ break;
128
+ case "char":
129
+ tscType = "string";
130
+ break;
131
+ case "varchar":
132
+ tscType = "string";
133
+ break;
134
+ case "blob":
135
+ tscType = "Buffer";
136
+ break;
137
+ case "text":
138
+ tscType = "string";
139
+ break;
140
+ case "tinyblob":
141
+ tscType = "Buffer";
142
+ break;
143
+ case "tinytext":
144
+ tscType = "string";
145
+ break;
146
+ case "mediumblob":
147
+ tscType = "Buffer";
148
+ break;
149
+ case "mediumtext":
150
+ tscType = "string";
151
+ break;
152
+ case "longblob":
153
+ tscType = "Buffer";
154
+ break;
155
+ case "longtext":
156
+ tscType = "string";
157
+ break;
158
+ case "enum":
159
+ tscType = resp.COLUMN_TYPE.substring(5, resp.COLUMN_TYPE.length - 1)
160
+ .replace(/'/gi, '"')
161
+ .replace(/","/gi, '" | "');
162
+ options.enum = resp.COLUMN_TYPE.substring(5, resp.COLUMN_TYPE.length - 1)
163
+ .replace(/'/gi, "")
164
+ .split(",");
165
+ break;
166
+ case "set":
167
+ tscType = `(${resp.COLUMN_TYPE.substring(4, resp.COLUMN_TYPE.length - 1)
168
+ .replace(/'/gi, '"')
169
+ .replace(/","/gi, '" | "')})[]`;
170
+ options.enum = resp.COLUMN_TYPE.substring(4, resp.COLUMN_TYPE.length - 1)
171
+ .replace(/'/gi, "")
172
+ .split(",");
173
+ break;
174
+ case "json":
175
+ tscType = "object";
176
+ break;
177
+ case "binary":
178
+ tscType = "Buffer";
179
+ break;
180
+ case "varbinary":
181
+ tscType = "Buffer";
182
+ break;
183
+ case "geometry":
184
+ tscType = "string";
185
+ break;
186
+ case "point":
187
+ tscType = "string";
188
+ break;
189
+ case "linestring":
190
+ tscType = "string";
191
+ break;
192
+ case "polygon":
193
+ tscType = "string";
194
+ break;
195
+ case "multipoint":
196
+ tscType = "string";
197
+ break;
198
+ case "multilinestring":
199
+ tscType = "string";
200
+ break;
201
+ case "multipolygon":
202
+ tscType = "string";
203
+ break;
204
+ case "geometrycollection":
205
+ case "geomcollection":
206
+ columnType = "geometrycollection";
207
+ tscType = "string";
208
+ break;
209
+ default:
210
+ tscType = "NonNullable<unknown>";
211
+ TomgUtils.LogError(`Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}`);
212
+ break;
213
+ }
214
+ if (this.ColumnTypesWithPrecision.some((v) => v === columnType)) {
215
+ if (resp.NUMERIC_PRECISION !== null) {
216
+ options.precision = resp.NUMERIC_PRECISION;
217
+ }
218
+ if (resp.NUMERIC_SCALE !== null) {
219
+ options.scale = resp.NUMERIC_SCALE;
220
+ }
221
+ }
222
+ if (this.ColumnTypesWithLength.some((v) => v === columnType)) {
223
+ options.length =
224
+ resp.CHARACTER_MAXIMUM_LENGTH > 0
225
+ ? resp.CHARACTER_MAXIMUM_LENGTH
226
+ : undefined;
227
+ }
228
+ if (this.ColumnTypesWithWidth.some((v) => v === columnType && tscType !== "boolean")) {
229
+ options.width =
230
+ resp.CHARACTER_MAXIMUM_LENGTH > 0
231
+ ? resp.CHARACTER_MAXIMUM_LENGTH
232
+ : undefined;
233
+ }
234
+ ent.columns.push({
235
+ generated,
236
+ type: columnType,
237
+ default: defaultValue,
238
+ options,
239
+ tscName,
240
+ tscType,
241
+ });
242
+ });
243
+ });
244
+ return entities;
245
+ }
246
+ async GetIndexesFromEntity(entities, schemas, dbNames) {
247
+ /* eslint-disable camelcase */
248
+ const response = await this.ExecQuery(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
249
+ CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key, CASE WHEN INDEX_TYPE="FULLTEXT" THEN 1 ELSE 0 END is_fulltext
250
+ FROM information_schema.statistics sta
251
+ WHERE table_schema IN (${MysqlDriver.buildEscapedObjectList(dbNames)})`);
252
+ /* eslint-enable camelcase */
253
+ entities.forEach((ent) => {
254
+ const entityIndices = response.filter((filterVal) => filterVal.TableName === ent.tscName);
255
+ const indexNames = new Set(entityIndices.map((v) => v.IndexName));
256
+ indexNames.forEach((indexName) => {
257
+ const records = entityIndices.filter((v) => v.IndexName === indexName);
258
+ const indexInfo = {
259
+ name: indexName,
260
+ columns: [],
261
+ options: {},
262
+ };
263
+ if (records[0].is_primary_key === 1)
264
+ indexInfo.primary = true;
265
+ if (records[0].is_fulltext === 1)
266
+ indexInfo.options.fulltext = true;
267
+ if (records[0].is_unique === 1)
268
+ indexInfo.options.unique = true;
269
+ records.forEach((record) => {
270
+ indexInfo.columns.push(record.ColumnName);
271
+ });
272
+ ent.indices.push(indexInfo);
273
+ });
274
+ });
275
+ return entities;
276
+ }
277
+ async GetRelations(entities, schemas, dbNames, generationOptions) {
278
+ const response = await this.ExecQuery(`SELECT
279
+ CU.TABLE_NAME TableWithForeignKey,
280
+ CU.ORDINAL_POSITION FK_PartNo,
281
+ CU.COLUMN_NAME ForeignKeyColumn,
282
+ CU.REFERENCED_TABLE_NAME TableReferenced,
283
+ CU.REFERENCED_COLUMN_NAME ForeignKeyColumnReferenced,
284
+ RC.DELETE_RULE onDelete,
285
+ RC.UPDATE_RULE onUpdate,
286
+ CU.CONSTRAINT_NAME object_id
287
+ FROM
288
+ INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
289
+ JOIN
290
+ INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
291
+ ON CU.CONSTRAINT_NAME=RC.CONSTRAINT_NAME AND CU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
292
+ WHERE
293
+ TABLE_SCHEMA IN (${MysqlDriver.buildEscapedObjectList(dbNames)})
294
+ AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
295
+ `);
296
+ const relationsTemp = [];
297
+ const relationKeys = new Set(response.map((v) => v.object_id));
298
+ relationKeys.forEach((relationId) => {
299
+ const rows = response.filter((v) => v.object_id === relationId);
300
+ const ownerTable = entities.find((v) => v.sqlName === rows[0].TableWithForeignKey);
301
+ const relatedTable = entities.find((v) => v.sqlName === rows[0].TableReferenced);
302
+ if (!ownerTable || !relatedTable) {
303
+ TomgUtils.LogError(`Relation between tables ${rows[0].TableWithForeignKey} and ${rows[0].TableReferenced} wasn't found in entity model.`, true);
304
+ return;
305
+ }
306
+ const internal = {
307
+ ownerColumns: [],
308
+ relatedColumns: [],
309
+ ownerTable,
310
+ relatedTable,
311
+ };
312
+ if (rows[0].onDelete !== "NO_ACTION") {
313
+ internal.onDelete = rows[0].onDelete;
314
+ }
315
+ if (rows[0].onUpdate !== "NO_ACTION") {
316
+ internal.onUpdate = rows[0].onUpdate;
317
+ }
318
+ rows.forEach((row) => {
319
+ internal.ownerColumns.push(row.ForeignKeyColumn);
320
+ internal.relatedColumns.push(row.ForeignKeyColumnReferenced);
321
+ });
322
+ relationsTemp.push(internal);
323
+ });
324
+ const retVal = MysqlDriver.GetRelationsFromRelationTempInfo(relationsTemp, entities, generationOptions);
325
+ return retVal;
326
+ }
327
+ async DisconnectFromServer() {
328
+ const promise = new Promise((resolve, reject) => {
329
+ this.Connection.end((err) => {
330
+ if (!err) {
331
+ resolve(true);
332
+ }
333
+ else {
334
+ TomgUtils.LogError(`Error disconnecting from ${this.EngineName} Server.`, false, err.message);
335
+ reject(err);
336
+ }
337
+ });
338
+ });
339
+ if (this.Connection) {
340
+ await promise;
341
+ }
342
+ }
343
+ async ConnectToServer(connectionOptons) {
344
+ const databaseName = connectionOptons.databaseNames[0];
345
+ let config;
346
+ if (connectionOptons.ssl) {
347
+ config = {
348
+ database: databaseName,
349
+ host: connectionOptons.host,
350
+ password: connectionOptons.password,
351
+ port: connectionOptons.port,
352
+ ssl: {
353
+ rejectUnauthorized: false,
354
+ },
355
+ connectTimeout: 60 * 60 * 1000,
356
+ user: connectionOptons.user,
357
+ };
358
+ }
359
+ else {
360
+ config = {
361
+ database: databaseName,
362
+ host: connectionOptons.host,
363
+ password: connectionOptons.password,
364
+ port: connectionOptons.port,
365
+ connectTimeout: 60 * 60 * 1000,
366
+ user: connectionOptons.user,
367
+ };
368
+ }
369
+ config.typeCast = (field, next) => {
370
+ switch (field.type) {
371
+ case "VAR_STRING":
372
+ return field.string();
373
+ case "BLOB":
374
+ return field.string();
375
+ default:
376
+ return next();
377
+ }
378
+ };
379
+ const promise = new Promise((resolve, reject) => {
380
+ this.Connection = this.MYSQL.createConnection(config);
381
+ this.Connection.connect((err) => {
382
+ if (!err) {
383
+ resolve(true);
384
+ }
385
+ else {
386
+ TomgUtils.LogError(`Error connecting to ${this.EngineName} Server.`, false, err.message);
387
+ reject(err);
388
+ }
389
+ });
390
+ });
391
+ await promise;
392
+ }
393
+ async CreateDB(dbName) {
394
+ await this.ExecQuery(`CREATE DATABASE \`${dbName}\`; `);
395
+ }
396
+ async UseDB(dbName) {
397
+ await this.ExecQuery(`USE \`${dbName}\`; `);
398
+ }
399
+ async DropDB(dbName) {
400
+ await this.ExecQuery(`DROP DATABASE \`${dbName}\`; `);
401
+ }
402
+ async CheckIfDBExists(dbName) {
403
+ const resp = await this.ExecQuery(`SHOW DATABASES LIKE "${dbName}" `);
404
+ return resp.length > 0;
405
+ }
406
+ async ExecQuery(sql) {
407
+ const ret = [];
408
+ const query = this.Connection.query(sql);
409
+ const stream = query.stream({});
410
+ const promise = new Promise((resolve, reject) => {
411
+ stream.on("data", (chunk) => {
412
+ ret.push(chunk);
413
+ });
414
+ stream.on("error", (err) => reject(err));
415
+ stream.on("end", () => resolve(true));
416
+ });
417
+ await promise;
418
+ return ret;
419
+ }
420
+ static ReturnDefaultValueFunction(defVal, dataType) {
421
+ let defaultValue = defVal;
422
+ if (!defaultValue || defaultValue === "NULL") {
423
+ return undefined;
424
+ }
425
+ if (defaultValue.toLowerCase() === "current_timestamp()") {
426
+ defaultValue = "CURRENT_TIMESTAMP";
427
+ }
428
+ if (defaultValue === "CURRENT_TIMESTAMP" ||
429
+ defaultValue.startsWith(`'`)) {
430
+ return `() => "${defaultValue}"`;
431
+ }
432
+ if (dataType === "set") {
433
+ return `() => ['${defaultValue.split(",").join("','")}']`;
434
+ }
435
+ return `() => "'${defaultValue}'"`;
436
+ }
437
+ }
438
+ exports.default = MysqlDriver;
439
+ //# sourceMappingURL=MysqlDriver.js.map
@@ -0,0 +1,25 @@
1
+ import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults";
2
+ import AbstractDriver from "./AbstractDriver";
3
+ import IConnectionOptions from "../IConnectionOptions";
4
+ import { Entity } from "../models/Entity";
5
+ import IGenerationOptions from "../IGenerationOptions";
6
+ export default class OracleDriver extends AbstractDriver {
7
+ defaultValues: DataTypeDefaults;
8
+ readonly standardPort = 1521;
9
+ readonly standardUser = "SYS";
10
+ readonly standardSchema = "";
11
+ private Oracle;
12
+ private Connection;
13
+ constructor();
14
+ GetAllTables(schemas: string[], dbNames: string[]): Promise<Entity[]>;
15
+ GetCoulmnsFromEntity(entities: Entity[]): Promise<Entity[]>;
16
+ GetIndexesFromEntity(entities: Entity[]): Promise<Entity[]>;
17
+ GetRelations(entities: Entity[], schemas: string[], dbNames: string[], generationOptions: IGenerationOptions): Promise<Entity[]>;
18
+ DisconnectFromServer(): Promise<void>;
19
+ ConnectToServer(connectionOptions: IConnectionOptions): Promise<void>;
20
+ CreateDB(dbName: string): Promise<void>;
21
+ UseDB(): Promise<void>;
22
+ DropDB(dbName: string): Promise<void>;
23
+ CheckIfDBExists(dbName: string): Promise<boolean>;
24
+ private static ReturnDefaultValueFunction;
25
+ }