From d20b322f80e066e7f974772251e35983375be520 Mon Sep 17 00:00:00 2001 From: Vasil Rangelov Date: Fri, 19 Jul 2019 15:49:18 +0300 Subject: [PATCH 1/3] Adds "?" to property names, to make the generated code compatible with "strictPropertyInitialization" TS setting. Also adds a call to super() when in active record mode, to make tslint play nice. --- src/entity.mst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/entity.mst b/src/entity.mst index 634a2bb..c918696 100644 --- a/src/entity.mst +++ b/src/entity.mst @@ -24,21 +24,23 @@ import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne array:{{array}},{{/array}} name:"{{name}}" }){{/options}} - {{printPropertyVisibility}}{{toPropertyName tsName}}:{{tsType}}{{#options/nullable}} | null{{/options/nullable}}; + {{printPropertyVisibility}}{{toPropertyName tsName}}?:{{tsType}}{{#options/nullable}} | null{{/options/nullable}}; {{/relations}}{{#relations}} - @{{relationType}}(()=>{{toEntityName relatedTable}}, {{tolowerCaseFirst relatedTable}}=>{{tolowerCaseFirst relatedTable}}.{{#if isOwner}}{{toPropertyName ownerColumn}},{ {{#../options/primary}}primary:true,{{/../options/primary}}{{^../options/nullable}} nullable:false,{{/../options/nullable}}{{#actionOnDelete}}onDelete: '{{.}}',{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{else}}{{toPropertyName relatedColumn}}{{#if (or actionOnDelete actionOnUpdate ) }},{ {{#actionOnDelete}}onDelete: '{{.}}' ,{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{/if}}{{/if}}){{#isOwner}} + @{{relationType}}(()=>{{toEntityName relatedTable}}, ({{toPropertyName relatedTable}}: {{toEntityName relatedTable}})=>{{toPropertyName relatedTable}}.{{#if isOwner}}{{toPropertyName ownerColumn}},{ {{#../options/primary}}primary:true,{{/../options/primary}}{{^../options/nullable}} nullable:false,{{/../options/nullable}}{{#actionOnDelete}}onDelete: '{{.}}',{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{else}}{{toPropertyName relatedColumn}}{{#if (or actionOnDelete actionOnUpdate ) }},{ {{#actionOnDelete}}onDelete: '{{.}}' ,{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{/if}}{{/if}}){{#isOwner}} {{#if isManyToMany}}@JoinTable({ name:'{{ ../options/name}}'}){{else}}@JoinColumn({ name:'{{ ../options/name}}'}){{/if}}{{/isOwner}} - {{#if (or isOneToMany isManyToMany)}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}:{{toLazy (concat (toEntityName relatedTable) "[]")}}; - {{else}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}:{{toLazy (concat (toEntityName relatedTable) ' | null')}}; + {{#if (or isOneToMany isManyToMany)}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}?:{{toLazy (concat (toEntityName relatedTable) "[]")}}; + {{else}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}?:{{toLazy (concat (toEntityName relatedTable) ' | null')}}; {{/if}} {{#if relationIdField }} @RelationId(({{toPropertyName ../../tsEntityName}}: {{toEntityName ../../tsEntityName}}) => {{toEntityName ../../tsEntityName}}.{{toPropertyName ../tsName}}) - {{printPropertyVisibility}}{{toPropertyName ../tsName}}Id: {{#if isOneToOne}}{{toLazy ../tsType}}{{else}}{{toLazy (concat ../tsType "[]")}}{{/if}};{{/if}}{{/relations}} + {{printPropertyVisibility}}{{toPropertyName ../tsName}}Id?: {{#if isOneToOne}}{{toLazy ../tsType}}{{else}}{{toLazy (concat ../tsType "[]")}}{{/if}};{{/if}}{{/relations}} {{/Columns}} {{#if GenerateConstructor}} - constructor(init?: Partial<{{toEntityName tsEntityName}}>) { - Object.assign(this, init); + + public constructor(init?: Partial<{{toEntityName tsEntityName}}>) { + {{#IsActiveRecord}}super(); + {{/IsActiveRecord}}Object.assign(this, init); } {{/if}} } From 14feb68cca6a7ac2dffe78f11ce96991ae92af0f Mon Sep 17 00:00:00 2001 From: Kononnable Date: Wed, 21 Aug 2019 23:04:47 +0200 Subject: [PATCH 2/3] add strictMode generation option --- src/Engine.ts | 3 +++ src/IGenerationOptions.ts | 2 ++ src/drivers/AbstractDriver.ts | 24 ++++-------------------- src/drivers/MssqlDriver.ts | 6 +----- src/drivers/MysqlDriver.ts | 6 +----- src/drivers/OracleDriver.ts | 8 ++------ src/drivers/PostgresDriver.ts | 12 ++---------- src/drivers/SqliteDriver.ts | 6 +----- src/entity.mst | 8 ++++---- src/index.ts | 19 +++++++++++++++++++ 10 files changed, 39 insertions(+), 55 deletions(-) diff --git a/src/Engine.ts b/src/Engine.ts index e477e6f..61f1036 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -284,6 +284,9 @@ function createHandlebarsHelpers(generationOptions: IGenerationOptions) { Handlebars.registerHelper("tolowerCaseFirst", str => changeCase.lowerCaseFirst(str) ); + Handlebars.registerHelper("strictMode", () => + generationOptions.strictMode ? generationOptions.strictMode : "" + ); Handlebars.registerHelper("toLazy", str => { if (generationOptions.lazy) { return `Promise<${str}>`; diff --git a/src/IGenerationOptions.ts b/src/IGenerationOptions.ts index 9a825f4..9478321 100644 --- a/src/IGenerationOptions.ts +++ b/src/IGenerationOptions.ts @@ -21,4 +21,6 @@ export default class IGenerationOptions { public customNamingStrategyPath: string = ""; public relationIds: boolean = false; + + public strictMode: false | "?" | "!" = false; } diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index c5ee74f..9bb27cf 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -221,9 +221,7 @@ export default abstract class AbstractDriver { ); if (!ownerEntity) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.ownerTable}.` + `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.` ); return; } @@ -233,9 +231,7 @@ export default abstract class AbstractDriver { ); if (!referencedEntity) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity model ${relationTmp.referencedTable}.` + `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.` ); return; } @@ -251,13 +247,7 @@ export default abstract class AbstractDriver { ); if (!ownerColumn) { TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` + `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.` ); return; } @@ -268,13 +258,7 @@ export default abstract class AbstractDriver { ); if (!relatedColumn) { TomgUtils.LogError( - `Relation between tables ${ - relationTmp.ownerTable - } and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` + `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.` ); return; } diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 9070c7a..2aed97b 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -191,11 +191,7 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG break; default: TomgUtils.LogError( - `Unknown column type: ${ - resp.DATA_TYPE - } table name: ${ - resp.TABLE_NAME - } column name: ${resp.COLUMN_NAME}` + `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` ); break; } diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 317cf1a..28ee666 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -208,11 +208,7 @@ export default class MysqlDriver extends AbstractDriver { break; default: TomgUtils.LogError( - `Unknown column type: ${ - resp.DATA_TYPE - } table name: ${ - resp.TABLE_NAME - } column name: ${resp.COLUMN_NAME}` + `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` ); break; } diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 658db35..2c7a208 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -309,9 +309,7 @@ export default class OracleDriver extends AbstractDriver { let config: any; if (connectionOptons.user === String(process.env.ORACLE_UsernameSys)) { config /* Oracle.IConnectionAttributes */ = { - connectString: `${connectionOptons.host}:${ - connectionOptons.port - }/${connectionOptons.databaseName}`, + connectString: `${connectionOptons.host}:${connectionOptons.port}/${connectionOptons.databaseName}`, externalAuth: connectionOptons.ssl, password: connectionOptons.password, privilege: this.Oracle.SYSDBA, @@ -319,9 +317,7 @@ export default class OracleDriver extends AbstractDriver { }; } else { config /* Oracle.IConnectionAttributes */ = { - connectString: `${connectionOptons.host}:${ - connectionOptons.port - }/${connectionOptons.databaseName}`, + connectString: `${connectionOptons.host}:${connectionOptons.port}/${connectionOptons.databaseName}`, externalAuth: connectionOptons.ssl, password: connectionOptons.password, user: connectionOptons.user diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 82168ba..5ed4b6c 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -102,19 +102,11 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name resp.data_type === "ARRAY" ) { TomgUtils.LogError( - `Unknown ${resp.data_type} column type: ${ - resp.udt_name - } table name: ${ - resp.table_name - } column name: ${resp.column_name}` + `Unknown ${resp.data_type} column type: ${resp.udt_name} table name: ${resp.table_name} column name: ${resp.column_name}` ); } else { TomgUtils.LogError( - `Unknown column type: ${ - resp.data_type - } table name: ${ - resp.table_name - } column name: ${resp.column_name}` + `Unknown column type: ${resp.data_type} table name: ${resp.table_name} column name: ${resp.column_name}` ); } return; diff --git a/src/drivers/SqliteDriver.ts b/src/drivers/SqliteDriver.ts index 1f36721..5dbadc5 100644 --- a/src/drivers/SqliteDriver.ts +++ b/src/drivers/SqliteDriver.ts @@ -163,11 +163,7 @@ export default class SqliteDriver extends AbstractDriver { break; default: TomgUtils.LogError( - `Unknown column type: ${ - colInfo.options.type - } table name: ${ - ent.tsEntityName - } column name: ${resp.name}` + `Unknown column type: ${colInfo.options.type} table name: ${ent.tsEntityName} column name: ${resp.name}` ); break; } diff --git a/src/entity.mst b/src/entity.mst index a6579a0..40ba07d 100644 --- a/src/entity.mst +++ b/src/entity.mst @@ -24,17 +24,17 @@ import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne array:{{array}},{{/array}} name:"{{name}}" }){{/options}} - {{printPropertyVisibility}}{{toPropertyName tsName}}?:{{tsType}}{{#options/nullable}} | null{{/options/nullable}}; + {{printPropertyVisibility}}{{toPropertyName tsName}}{{strictMode}}:{{tsType}}{{#options/nullable}} | null{{/options/nullable}}; {{/relations}}{{#relations}} @{{relationType}}(()=>{{toEntityName relatedTable}}, ({{toPropertyName relatedTable}}: {{toEntityName relatedTable}})=>{{toPropertyName relatedTable}}.{{#if isOwner}}{{toPropertyName ownerColumn}},{ {{#../options/primary}}primary:true,{{/../options/primary}}{{^../options/nullable}} nullable:false,{{/../options/nullable}}{{#actionOnDelete}}onDelete: '{{.}}',{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{else}}{{toPropertyName relatedColumn}}{{#if (or actionOnDelete actionOnUpdate ) }},{ {{#actionOnDelete}}onDelete: '{{.}}' ,{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{/if}}{{/if}}){{#isOwner}} {{#if isManyToMany}}@JoinTable({ name:'{{ ../options/name}}'}){{else}}@JoinColumn({ name:'{{ ../options/name}}'}){{/if}}{{/isOwner}} - {{#if (or isOneToMany isManyToMany)}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}?:{{toLazy (concat (toEntityName relatedTable) "[]")}}; - {{else}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}?:{{toLazy (concat (toEntityName relatedTable) ' | null')}}; + {{#if (or isOneToMany isManyToMany)}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}{{strictMode}}:{{toLazy (concat (toEntityName relatedTable) "[]")}}; + {{else}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}{{strictMode}}:{{toLazy (concat (toEntityName relatedTable) ' | null')}}; {{/if}} {{#if relationIdField }} @RelationId(({{toPropertyName ../../tsEntityName}}: {{toEntityName ../../tsEntityName}}) => {{toEntityName ../../tsEntityName}}.{{toPropertyName ../tsName}}) - {{printPropertyVisibility}}{{toPropertyName ../tsName}}Id?: {{#if isOneToOne}}{{toLazy ../tsType}}{{else}}{{toLazy (concat ../tsType "[]")}}{{/if}};{{/if}}{{/relations}} + {{printPropertyVisibility}}{{toPropertyName ../tsName}}Id{{strictMode}}: {{#if isOneToOne}}{{toLazy ../tsType}}{{else}}{{toLazy (concat ../tsType "[]")}}{{/if}};{{/if}}{{/relations}} {{/Columns}} {{#if GenerateConstructor}} {{printPropertyVisibility}}constructor(init?: Partial<{{toEntityName tsEntityName}}>) { diff --git a/src/index.ts b/src/index.ts index ba1bf2c..7ea1277 100644 --- a/src/index.ts +++ b/src/index.ts @@ -158,6 +158,11 @@ function GetUtilParametersByArgs() { default: false, describe: "Generate constructor allowing partial initialization" }) + .option("strictMode", { + choices: ["none", "?", "!"], + default: "none", + describe: "Mark fields as optional(?) or non-null(!)" + }) .option("timeout", { describe: "SQL Query timeout(ms)", number: true @@ -195,6 +200,8 @@ function GetUtilParametersByArgs() { generationOptions.propertyVisibility = argv.pv; generationOptions.relationIds = argv.relationIds; generationOptions.resultsPath = argv.o ? argv.o.toString() : null; + generationOptions.strictMode = + argv.strictMode === "none" ? false : argv.strictMode; return { driver, connectionOptions, generationOptions }; } @@ -390,6 +397,18 @@ async function GetUtilParametersByInquirer() { } ])) as any).propertyVisibility; + const { strictModeRaw } = (await inquirer.prompt([ + { + choices: ["none", "?", "!"], + message: "Mark fields as optional(?) or non-null(!)", + name: "strictModeRaw", + default: "none", + type: "list" + } + ])) as any; + + generationOptions.strictMode = + strictModeRaw === "none" ? false : strictModeRaw; generationOptions.noConfigs = !customizations.includes("config"); generationOptions.lazy = customizations.includes("lazy"); generationOptions.activeRecord = customizations.includes( From f9b4f560b9ad4280e4b4a641fd7d6acb14be415a Mon Sep 17 00:00:00 2001 From: Kononnable Date: Wed, 21 Aug 2019 23:27:26 +0200 Subject: [PATCH 3/3] fix test compilation error --- test/utils/GeneralTestUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/utils/GeneralTestUtils.ts b/test/utils/GeneralTestUtils.ts index c3981d9..8c4af84 100644 --- a/test/utils/GeneralTestUtils.ts +++ b/test/utils/GeneralTestUtils.ts @@ -24,7 +24,8 @@ export function getGenerationOptions(resultsPath: string): IGenerationOptions { customNamingStrategyPath: "", relationIds: false, skipSchema: false, - activeRecord: false + activeRecord: false, + strictMode: false }; }