Merge branch 'next' into pr/arimus/233

This commit is contained in:
Kononnable 2019-12-28 12:16:26 +01:00
commit 986ae97410
22 changed files with 408 additions and 63 deletions

View File

@ -36,7 +36,7 @@ module.exports = {
settings: {
"import/resolver": {
node: {
extensions: [".js", ".jsx", ".ts", ".tsx"]
extensions: [".ts"]
}
}
}

16
package-lock.json generated
View File

@ -274,12 +274,28 @@
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/eslint": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-6.1.3.tgz",
"integrity": "sha512-llYf1QNZaDweXtA7uY6JczcwHmFwJL9TpK3E6sY0B18l6ulDT6VWNMAdEjYccFHiDfxLPxffd8QmSDV4QUUspA==",
"dev": true,
"requires": {
"@types/estree": "*",
"@types/json-schema": "*"
}
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
"@types/estree": {
"version": "0.0.41",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.41.tgz",
"integrity": "sha512-rIAmXyJlqw4KEBO7+u9gxZZSQHaCNnIzYrnNmYVpgfJhxTqO0brCX0SYpqUTkVI5mwwUwzmtspLBGBKroMeynA==",
"dev": true
},
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",

View File

@ -11,7 +11,7 @@
"prepare": "npm run build",
"pretest": "tsc --noEmit",
"test": "nyc --reporter=lcov ts-node ./node_modules/mocha/bin/_mocha test/**/*.test.ts -- --bail",
"posttest": "eslint ./**/*.ts ./src/**/*.ts ./test/**/*.ts",
"posttest": "eslint ./src/**/*.ts ./test/**/*.ts",
"clean": "rimraf coverage output dist",
"prettier": "prettier --write ./src/*.ts ./src/**/*.ts"
},
@ -47,6 +47,7 @@
"@types/chai": "^4.2.7",
"@types/chai-as-promised": "^7.1.2",
"@types/chai-subset": "^1.3.3",
"@types/eslint": "^6.1.3",
"@types/fs-extra": "^8.0.1",
"@types/handlebars": "^4.1.0",
"@types/inquirer": "^6.5.0",

View File

@ -16,6 +16,7 @@ export default interface IConnectionOptions {
| "sqlite";
schemaName: string;
ssl: boolean;
skipTables: string[];
}
export function getDefaultConnectionOptions(): IConnectionOptions {
@ -27,7 +28,8 @@ export function getDefaultConnectionOptions(): IConnectionOptions {
password: "",
databaseType: undefined as any,
schemaName: "",
ssl: false
ssl: false,
skipTables: []
};
return connectionOptions;
}

View File

@ -18,6 +18,8 @@ export default interface IGenerationOptions {
relationIds: boolean;
strictMode: "none" | "?" | "!";
skipSchema: boolean;
indexFile: boolean;
exportType: "named" | "default";
}
export function getDefaultGenerationOptions(): IGenerationOptions {
const generationOptions: IGenerationOptions = {
@ -34,7 +36,9 @@ export function getDefaultGenerationOptions(): IGenerationOptions {
customNamingStrategyPath: "",
relationIds: false,
strictMode: "none",
skipSchema: false
skipSchema: false,
indexFile: false,
exportType: "named"
};
return generationOptions;
}

View File

@ -14,8 +14,7 @@ export default function modelGenerationPhase(
databaseModel: Entity[]
): void {
createHandlebarsHelpers(generationOptions);
const templatePath = path.resolve(__dirname, "templates", "entity.mst");
const template = fs.readFileSync(templatePath, "UTF-8");
const resultPath = generationOptions.resultsPath;
if (!fs.existsSync(resultPath)) {
fs.mkdirSync(resultPath);
@ -29,7 +28,24 @@ export default function modelGenerationPhase(
fs.mkdirSync(entitiesPath);
}
}
const compliedTemplate = Handlebars.compile(template, {
if (generationOptions.indexFile) {
createIndexFile(databaseModel, generationOptions, entitiesPath);
}
generateModels(databaseModel, generationOptions, entitiesPath);
}
function generateModels(
databaseModel: Entity[],
generationOptions: IGenerationOptions,
entitiesPath: string
) {
const entityTemplatePath = path.resolve(
__dirname,
"templates",
"entity.mst"
);
const entityTemplate = fs.readFileSync(entityTemplatePath, "UTF-8");
const entityCompliedTemplate = Handlebars.compile(entityTemplate, {
noEscape: true
});
databaseModel.forEach(element => {
@ -54,7 +70,7 @@ export default function modelGenerationPhase(
entitiesPath,
`${casedFileName}.ts`
);
const rendered = compliedTemplate(element);
const rendered = entityCompliedTemplate(element);
const withImportStatements = removeUnusedImports(rendered);
const formatted = Prettier.format(withImportStatements, {
parser: "typescript"
@ -65,6 +81,41 @@ export default function modelGenerationPhase(
});
});
}
function createIndexFile(
databaseModel: Entity[],
generationOptions: IGenerationOptions,
entitiesPath: string
) {
const templatePath = path.resolve(__dirname, "templates", "index.mst");
const template = fs.readFileSync(templatePath, "UTF-8");
const compliedTemplate = Handlebars.compile(template, {
noEscape: true
});
const rendered = compliedTemplate({ entities: databaseModel });
const formatted = Prettier.format(rendered, {
parser: "typescript"
});
let fileName = "index";
switch (generationOptions.convertCaseFile) {
case "camel":
fileName = changeCase.camelCase(fileName);
break;
case "param":
fileName = changeCase.paramCase(fileName);
break;
case "pascal":
fileName = changeCase.pascalCase(fileName);
break;
default:
}
const resultFilePath = path.resolve(entitiesPath, `${fileName}.ts`);
fs.writeFileSync(resultFilePath, formatted, {
encoding: "UTF-8",
flag: "w"
});
}
function removeUnusedImports(rendered: string) {
const openBracketIndex = rendered.indexOf("{") + 1;
const closeBracketIndex = rendered.indexOf("}");
@ -160,6 +211,14 @@ function createHandlebarsHelpers(generationOptions: IGenerationOptions): void {
return retVal;
}
);
Handlebars.registerHelper("defaultExport", () =>
generationOptions.exportType === "default" ? "default" : ""
);
Handlebars.registerHelper("localImport", (entityName: string) =>
generationOptions.exportType === "default"
? entityName
: `{${entityName}}`
);
Handlebars.registerHelper("strictMode", () =>
generationOptions.strictMode !== "none"
? generationOptions.strictMode

View File

@ -69,7 +69,8 @@ export default abstract class AbstractDriver {
public abstract GetAllTablesQuery: (
schema: string,
dbNames: string
dbNames: string,
tableNames: string[]
) => Promise<
{
TABLE_SCHEMA: string;
@ -186,7 +187,8 @@ export default abstract class AbstractDriver {
);
dbModel = await this.GetAllTables(
sqlEscapedSchema,
connectionOptions.databaseName
connectionOptions.databaseName,
connectionOptions.skipTables
);
await this.GetCoulmnsFromEntity(
dbModel,
@ -214,9 +216,14 @@ export default abstract class AbstractDriver {
public async GetAllTables(
schema: string,
dbNames: string
dbNames: string,
tableNames: string[]
): Promise<Entity[]> {
const response = await this.GetAllTablesQuery(schema, dbNames);
const response = await this.GetAllTablesQuery(
schema,
dbNames,
tableNames
);
const ret: Entity[] = [] as Entity[];
response.forEach(val => {
ret.push({

View File

@ -24,8 +24,16 @@ export default class MssqlDriver extends AbstractDriver {
private Connection: MSSQL.ConnectionPool;
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
public GetAllTablesQuery = async (
schema: string,
dbNames: string,
tableNames: string[]
) => {
const request = new MSSQL.Request(this.Connection);
const tableCondition =
tableNames.length > 0
? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')`
: "";
const response: {
TABLE_SCHEMA: string;
TABLE_NAME: string;
@ -35,7 +43,7 @@ export default class MssqlDriver extends AbstractDriver {
`SELECT TABLE_SCHEMA,TABLE_NAME, table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList(
dbNames
)})`
)}) ${tableCondition}`
)
).recordset;
return response;

View File

@ -26,7 +26,15 @@ export default class MysqlDriver extends AbstractDriver {
private Connection: MYSQL.Connection;
public GetAllTablesQuery = async (schema: string, dbNames: string) => {
public GetAllTablesQuery = async (
schema: string,
dbNames: string,
tableNames: string[]
) => {
const tableCondition =
tableNames.length > 0
? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')`
: "";
const response = this.ExecQuery<{
TABLE_SCHEMA: string;
TABLE_NAME: string;
@ -36,7 +44,7 @@ export default class MysqlDriver extends AbstractDriver {
WHERE table_type='BASE TABLE'
AND table_schema IN (${MysqlDriver.escapeCommaSeparatedList(
dbNames
)})`);
)}) ${tableCondition}`);
return response;
};

View File

@ -36,14 +36,22 @@ export default class OracleDriver extends AbstractDriver {
}
}
public GetAllTablesQuery = async () => {
public GetAllTablesQuery = async (
schema: string,
dbNames: string,
tableNames: string[]
) => {
const tableCondition =
tableNames.length > 0
? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')`
: "";
const response: {
TABLE_SCHEMA: string;
TABLE_NAME: string;
DB_NAME: string;
}[] = (
await this.Connection.execute(
`SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual)`
`SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual) ${tableCondition}`
)
).rows!;
return response;

View File

@ -24,14 +24,22 @@ export default class PostgresDriver extends AbstractDriver {
private Connection: PG.Client;
public GetAllTablesQuery = async (schema: string) => {
public GetAllTablesQuery = async (
schema: string,
dbNames: string,
tableNames: string[]
) => {
const tableCondition =
tableNames.length > 0
? ` AND NOT table_name IN ('${tableNames.join("','")}')`
: "";
const response: {
TABLE_SCHEMA: string;
TABLE_NAME: string;
DB_NAME: string;
}[] = (
await this.Connection.query(
`SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME", table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) `
`SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME", table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) ${tableCondition}`
)
).rows;
return response;

View File

@ -30,10 +30,18 @@ export default class SqliteDriver extends AbstractDriver {
public GetAllTablesQuery: any;
public async GetAllTables(): Promise<Entity[]> {
public async GetAllTables(
schema: string,
dbNames: string,
tableNames: string[]
): Promise<Entity[]> {
const ret: Entity[] = [] as Entity[];
const tableCondition =
tableNames.length > 0
? ` AND NOT tbl_name IN ('${tableNames.join("','")}')`
: "";
const rows = await this.ExecQuery<{ tbl_name: string; sql: string }>(
`SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%'`
`SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%' ${tableCondition}`
);
rows.forEach(val => {
if (val.sql.includes("AUTOINCREMENT")) {

View File

@ -243,12 +243,28 @@ function checkYargsParameters(options: options): options {
boolean: true,
default: !options.generationOptions.pluralizeNames,
describe:
"Disable pluralization of OneToMany, ManyToMany relation names."
"Disable pluralization of OneToMany, ManyToMany relation names"
},
skipTables: {
string: true,
default: options.connectionOptions.skipTables.join(","),
describe:
"Skip schema generation for specific tables. You can pass multiple values separated by comma"
},
strictMode: {
choices: ["none", "?", "!"],
default: options.generationOptions.strictMode,
describe: "Mark fields as optional(?) or non-null(!)"
},
index: {
boolean: true,
default: options.generationOptions.indexFile,
describe: "Generate index file"
},
defaultExport: {
boolean: true,
default: options.generationOptions.exportType === "default",
describe: "Generate index file"
}
});
@ -266,6 +282,7 @@ function checkYargsParameters(options: options): options {
: standardSchema;
options.connectionOptions.ssl = argv.ssl;
options.connectionOptions.user = argv.u || standardUser;
options.connectionOptions.skipTables = argv.skipTables.split(",");
options.generationOptions.activeRecord = argv.a;
options.generationOptions.generateConstructor = argv.generateConstructor;
options.generationOptions.convertCaseEntity = argv.ce as IGenerationOptions["convertCaseEntity"];
@ -280,6 +297,10 @@ function checkYargsParameters(options: options): options {
options.generationOptions.resultsPath = argv.o;
options.generationOptions.pluralizeNames = !argv.disablePluralization;
options.generationOptions.strictMode = argv.strictMode as IGenerationOptions["strictMode"];
options.generationOptions.indexFile = argv.index;
options.generationOptions.exportType = argv.defaultExport
? "default"
: "named";
return options;
}
@ -387,6 +408,33 @@ async function useInquirer(options: options): Promise<options> {
])
).dbName;
}
const ignoreSpecyficTables = (
await inquirer.prompt([
{
default:
options.connectionOptions.skipTables.length === 0
? "All of them"
: "Ignore specific tables",
message: "Generate schema for tables:",
choices: ["All of them", "Ignore specific tables"],
name: "specyficTables",
type: "list"
}
])
).specyficTables;
if (ignoreSpecyficTables === "Ignore specific tables") {
const { tableNames } = await inquirer.prompt({
default: options.connectionOptions.skipTables.join(","),
message: "Table names(separated by comma)",
name: "tableNames",
type: "input"
});
options.connectionOptions.skipTables = tableNames.split(",");
} else {
options.connectionOptions.skipTables = [];
}
options.generationOptions.resultsPath = (
await inquirer.prompt([
{
@ -465,9 +513,21 @@ async function useInquirer(options: options): Promise<options> {
},
{
name:
"Pluralize OneToMany, ManyToMany relation names.",
"Pluralize OneToMany, ManyToMany relation names",
value: "pluralize",
checked: options.generationOptions.pluralizeNames
},
{
name: "Generate index file",
value: "index",
checked: options.generationOptions.indexFile
},
{
name: "Prefer default exports",
value: "defaultExport",
checked:
options.generationOptions.exportType ===
"default"
}
],
message: "Available customizations",
@ -521,6 +581,12 @@ async function useInquirer(options: options): Promise<options> {
options.generationOptions.generateConstructor = customizations.includes(
"constructor"
);
options.generationOptions.indexFile = customizations.includes("index");
options.generationOptions.exportType = customizations.includes(
"defaultExport"
)
? "default"
: "named";
if (customizations.includes("namingStrategy")) {
const namingStrategyPath = (

View File

@ -2,7 +2,7 @@
@Index("{{name}}",[{{#columns}}"{{toPropertyName .}}",{{/columns~}}],{ {{json options}} })
{{/inline}}
{{#*inline "Import"}}
import { {{toEntityName .}} } from './{{toFileName .}}'
import {{localImport (toEntityName .)}} from './{{toFileName .}}'
{{/inline}}
{{#*inline "Column"}}
{{#generated}}@PrimaryGeneratedColumn({ type:"{{type}}", {{/generated}}{{^generated}}@Column("{{type}}",{ {{#primary}}primary:{{primary}},{{/primary}}{{/generated}}{{json options}}{{#default}},default: {{.}},{{/default}} })
@ -13,7 +13,7 @@ import { {{toEntityName .}} } from './{{toFileName .}}'
{ name: "{{name}}", referencedColumnName: "{{toPropertyName referencedColumnName}}" },
{{/inline}}
{{#*inline "Relation"}}
@{{relationType}}(()=>{{toEntityName relatedTable}},{{toEntityName relatedTable}}=>{{toEntityName relatedTable}}.{{toPropertyName relatedField}}{{#if relationOptions}},{ {{json relationOptions}} }{{/if}})
@{{relationType}}(()=>{{toEntityName relatedTable}},{{toEntityName relatedTable}}_=>{{toEntityName relatedTable}}_.{{toPropertyName relatedField}}{{#if relationOptions}},{ {{json relationOptions}} }{{/if}})
{{#if joinColumnOptions}}@JoinColumn([{{#joinColumnOptions}}{{> JoinColumnOptions}}{{/joinColumnOptions}}]){{/if}}
{{#joinTableOptions}}@JoinTable({ name:"{{name}}", joinColumns:[{{#joinColumns}}{{> JoinColumnOptions}}{{/joinColumns}}],inverseJoinColumns:[{{#inverseJoinColumns}}{{> JoinColumnOptions}}{{/inverseJoinColumns}}],{{#database}}database:"{{.}}",{{/database}}{{#schema}}schema:"{{.}}"{{/schema}} }){{/joinTableOptions}}
{{printPropertyVisibility}}{{toPropertyName fieldName}}{{strictMode}}:{{toRelation (toEntityName relatedTable) relationType}};
@ -33,7 +33,7 @@ import { {{toEntityName .}} } from './{{toFileName .}}'
{{#*inline "Entity"}}
{{#indices}}{{> Index}}{{/indices~}}
@Entity("{{sqlName}}"{{#schema}} ,{schema:"{{.}}"{{#if ../database}}, database:"{{../database}}"{{/if}} } {{/schema}})
export class {{toEntityName tscName}}{{#activeRecord}} extends BaseEntity{{/activeRecord}} {
export {{defaultExport}} class {{toEntityName tscName}}{{#activeRecord}} extends BaseEntity{{/activeRecord}} {
{{#columns}}{{> Column}}{{/columns~}}
{{#relations}}{{> Relation}}{{/relations~}}

5
src/templates/index.mst Normal file
View File

@ -0,0 +1,5 @@
{{#entities~}}
import {{localImport (toEntityName tscName)}} from './{{toFileName tscName}}'
{{/entities}}
export { {{#entities}}{{toEntityName tscName}},{{/entities~}} }

30
test/configs/.eslintrc.js Normal file
View File

@ -0,0 +1,30 @@
module.exports = {
env: {
node: true,
},
extends: [
"airbnb-base",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "test/configs/tsconfig.json"
},
plugins: ["@typescript-eslint"],
rules: { // TODO: remove some rule overrides after disabling eslint on model customization tests(?)
"import/extensions": ["off"],
"import/prefer-default-export": ["off"],
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/camelcase": ["off"],
"@typescript-eslint/class-name-casing": ["off"]
},
settings: {
"import/resolver": {
node: {
extensions: [".ts"]
}
}
}
};

View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"newLine": "LF",
"typeRoots": [
"../../node_modules/@types"
],
"resolveJsonModule": true,
},
"include": [
"../../output"
]
}

View File

@ -47,7 +47,7 @@ describe("MssqlDriver", () => {
return response;
}
});
const result = await driver.GetAllTables("schema", "db");
const result = await driver.GetAllTables("schema", "db", []);
const expectedResult = [] as Entity[];
const y: Entity = {
columns: [],

View File

@ -6,6 +6,7 @@ import * as path from "path";
import * as chaiSubset from "chai-subset";
import * as flatMap from "array.prototype.flatmap";
import yn from "yn";
import { CLIEngine } from "eslint";
import EntityFileToJson from "../utils/EntityFileToJson";
import { createDriver, dataCollectionPhase } from "../../src/Engine";
import * as GTU from "../utils/GeneralTestUtils";
@ -277,6 +278,15 @@ export function compileGeneratedModel(filesGenPath: string, drivers: string[]) {
compiledWithoutErrors,
"Errors detected while compiling generated model"
).to.equal(true);
const cli = new CLIEngine({ configFile: "test/configs/.eslintrc.js" });
const lintReport = cli.executeOnFiles(currentDirectoryFiles)
lintReport.results.forEach(result => result.messages.forEach(message => {
console.error(`${result.filePath}:${message.line} - ${message.message}`)
}))
expect(lintReport.errorCount).to.equal(0)
expect(lintReport.warningCount).to.equal(0)
}
async function prepareTestRuns(
@ -320,7 +330,8 @@ async function prepareTestRuns(
password: String(process.env.MYSQL_Password),
databaseType: "mysql",
schemaName: "ignored",
ssl: yn(process.env.MYSQL_SSL, { default: false })
ssl: yn(process.env.MYSQL_SSL, { default: false }),
skipTables: []
};
break;
case "mariadb":
@ -332,7 +343,8 @@ async function prepareTestRuns(
password: String(process.env.MARIADB_Password),
databaseType: "mariadb",
schemaName: "ignored",
ssl: yn(process.env.MARIADB_SSL, { default: false })
ssl: yn(process.env.MARIADB_SSL, { default: false }),
skipTables: []
};
break;

View File

@ -15,6 +15,8 @@ import { compileGeneratedModel } from "../integration/runTestsFromPath.test";
chai.use(chaiSubset);
const { expect } = chai;
// TODO: test for connectionOptions.specyficTables
describe("Model customization phase", async () => {
const generateSampleData: () => Entity[] = () => [
{
@ -663,4 +665,81 @@ describe("Model customization phase", async () => {
compileGeneratedModel(generationOptions.resultsPath, [""]);
})
})
describe("index file generation", () => {
it("named export", async () => {
const data = generateSampleData();
const generationOptions = generateGenerationOptions();
generationOptions.indexFile = true;
clearGenerationDir();
const customizedModel = modelCustomizationPhase(
data,
generationOptions,
{}
);
modelGenerationPhase(
getDefaultConnectionOptions(),
generationOptions,
customizedModel
);
const filesGenPath = path.resolve(resultsPath, "entities");
const indexFileContent = fs
.readFileSync(path.resolve(filesGenPath, "Index.ts"))
.toString();
expect(indexFileContent).to.contain('import { PostAuthor } from "./PostAuthor');
expect(indexFileContent).to.contain('import { Post } from "./Post');
expect(indexFileContent).to.contain('export { PostAuthor, Post }');
compileGeneratedModel(generationOptions.resultsPath, [""]);
})
it("default export", async () => {
const data = generateSampleData();
const generationOptions = generateGenerationOptions();
generationOptions.indexFile = true;
generationOptions.exportType = "default"
clearGenerationDir();
const customizedModel = modelCustomizationPhase(
data,
generationOptions,
{}
);
modelGenerationPhase(
getDefaultConnectionOptions(),
generationOptions,
customizedModel
);
const filesGenPath = path.resolve(resultsPath, "entities");
const indexFileContent = fs
.readFileSync(path.resolve(filesGenPath, "Index.ts"))
.toString();
expect(indexFileContent).to.contain('import PostAuthor from "./PostAuthor');
expect(indexFileContent).to.contain('import Post from "./Post');
expect(indexFileContent).to.contain('export { PostAuthor, Post }');
compileGeneratedModel(generationOptions.resultsPath, [""]);
})
it("disabled", async () => {
const data = generateSampleData();
const generationOptions = generateGenerationOptions();
generationOptions.pluralizeNames = false;
clearGenerationDir();
const customizedModel = modelCustomizationPhase(
data,
generationOptions,
{}
);
modelGenerationPhase(
getDefaultConnectionOptions(),
generationOptions,
customizedModel
);
const filesGenPath = path.resolve(resultsPath, "entities");
expect(fs.existsSync(path.resolve(filesGenPath, "Index.ts"))).to.equal(false);
compileGeneratedModel(generationOptions.resultsPath, [""]);
})
})
});

View File

@ -29,7 +29,8 @@ export async function createMSSQLModels(
password: String(process.env.MSSQL_Password),
databaseType: "mssql",
schemaName: "dbo,sch1,sch2",
ssl: yn(process.env.MSSQL_SSL, { default: false })
ssl: yn(process.env.MSSQL_SSL, { default: false }),
skipTables: []
};
await driver.ConnectToServer(connectionOptions);
connectionOptions.databaseName = String(process.env.MSSQL_Database);
@ -80,7 +81,8 @@ export async function createPostgresModels(
password: String(process.env.POSTGRES_Password),
databaseType: "postgres",
schemaName: "public,sch1,sch2",
ssl: yn(process.env.POSTGRES_SSL, { default: false })
ssl: yn(process.env.POSTGRES_SSL, { default: false }),
skipTables: []
};
await driver.ConnectToServer(connectionOptions);
connectionOptions.databaseName = String(process.env.POSTGRES_Database);
@ -130,7 +132,8 @@ export async function createSQLiteModels(
password: "",
databaseType: "sqlite",
schemaName: "",
ssl: false
ssl: false,
skipTables: []
};
const connOpt: ConnectionOptions = {
@ -164,7 +167,8 @@ export async function createMysqlModels(
password: String(process.env.MYSQL_Password),
databaseType: "mysql",
schemaName: "ignored",
ssl: yn(process.env.MYSQL_SSL, { default: false })
ssl: yn(process.env.MYSQL_SSL, { default: false }),
skipTables: []
};
await driver.ConnectToServer(connectionOptions);
@ -206,7 +210,8 @@ export async function createMariaDBModels(
password: String(process.env.MARIADB_Password),
databaseType: "mariadb",
schemaName: "ignored",
ssl: yn(process.env.MARIADB_SSL, { default: false })
ssl: yn(process.env.MARIADB_SSL, { default: false }),
skipTables: []
};
await driver.ConnectToServer(connectionOptions);
@ -250,7 +255,8 @@ export async function createOracleDBModels(
password: String(process.env.ORACLE_PasswordSys),
databaseType: "oracle",
schemaName: String(process.env.ORACLE_Username),
ssl: yn(process.env.ORACLE_SSL, { default: false })
ssl: yn(process.env.ORACLE_SSL, { default: false }),
skipTables: []
};
await driver.ConnectToServer(connectionOptions);
connectionOptions.user = String(process.env.ORACLE_Username);

View File

@ -1,29 +1,30 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"noImplicitAny": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"declaration": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"stripInternal": true,
"strictNullChecks": true,
"moduleResolution": "node",
"newLine": "LF",
"outDir": "dist",
"lib": [
"es2019","es2019.array"
],
"typeRoots": [
"./node_modules/@types"
],
"resolveJsonModule": true,
},
"include": [
"src",
"test"
]
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"noImplicitAny": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"declaration": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"stripInternal": true,
"strictNullChecks": true,
"moduleResolution": "node",
"newLine": "LF",
"outDir": "dist",
"lib": [
"es2019",
"es2019.array"
],
"typeRoots": [
"./node_modules/@types"
],
"resolveJsonModule": true,
},
"include": [
"src",
"test",
]
}