Option to disable column name pluralization (#142)
This commit is contained in:
parent
7679ef2b77
commit
ff637721ed
@ -5,6 +5,7 @@ import path = require("path");
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
export default interface IGenerationOptions {
|
||||
resultsPath: string;
|
||||
pluralizeNames: boolean;
|
||||
noConfigs: boolean;
|
||||
convertCaseFile: "pascal" | "param" | "camel" | "none";
|
||||
convertCaseEntity: "pascal" | "camel" | "none";
|
||||
@ -21,6 +22,7 @@ export default interface IGenerationOptions {
|
||||
export function getDefaultGenerationOptions(): IGenerationOptions {
|
||||
const generationOptions: IGenerationOptions = {
|
||||
resultsPath: path.resolve(process.cwd(), "output"),
|
||||
pluralizeNames: true,
|
||||
noConfigs: false,
|
||||
convertCaseFile: "pascal",
|
||||
convertCaseEntity: "pascal",
|
||||
|
@ -9,6 +9,7 @@ import { RelationId } from "./models/RelationId";
|
||||
import { Column } from "./models/Column";
|
||||
|
||||
type NamingStrategy = {
|
||||
enablePluralization: (value: boolean) => void;
|
||||
relationIdName: (
|
||||
relationId: RelationId,
|
||||
relation: Relation,
|
||||
@ -25,6 +26,7 @@ export default function modelCustomizationPhase(
|
||||
defaultValues: DataTypeDefaults
|
||||
): Entity[] {
|
||||
const namingStrategy: NamingStrategy = {
|
||||
enablePluralization: NamingStrategy.enablePluralization,
|
||||
columnName: NamingStrategy.columnName,
|
||||
entityName: NamingStrategy.entityName,
|
||||
relationIdName: NamingStrategy.relationIdName,
|
||||
@ -78,7 +80,18 @@ export default function modelCustomizationPhase(
|
||||
`[${new Date().toLocaleTimeString()}] Using standard naming strategy for relation field names.`
|
||||
);
|
||||
}
|
||||
if (req.enablePluralization) {
|
||||
console.log(
|
||||
`[${new Date().toLocaleTimeString()}] Using custom pluralization method for OneToMany, ManyToMany relation field names.`
|
||||
);
|
||||
namingStrategy.enablePluralization = req.enablePluralization;
|
||||
} else {
|
||||
console.log(
|
||||
`[${new Date().toLocaleTimeString()}] Using custom pluralization method for OneToMany, ManyToMany relation field names.`
|
||||
);
|
||||
}
|
||||
}
|
||||
namingStrategy.enablePluralization(generationOptions.pluralizeNames);
|
||||
let retVal = removeIndicesGeneratedByTypeorm(dbModel);
|
||||
retVal = removeColumnsInRelation(dbModel);
|
||||
retVal = applyNamingStrategy(namingStrategy, dbModel);
|
||||
|
@ -3,6 +3,12 @@ import * as changeCase from "change-case";
|
||||
import { Relation } from "./models/Relation";
|
||||
import { RelationId } from "./models/RelationId";
|
||||
|
||||
let pluralize: boolean;
|
||||
|
||||
export function enablePluralization(value: boolean) {
|
||||
pluralize = value;
|
||||
}
|
||||
|
||||
export function relationIdName(
|
||||
relationId: RelationId,
|
||||
relation: Relation
|
||||
@ -22,7 +28,7 @@ export function relationIdName(
|
||||
if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) {
|
||||
newColumnName = newColumnName.substring(0, newColumnName.length - 1);
|
||||
}
|
||||
if (isRelationToMany) {
|
||||
if (isRelationToMany && pluralize) {
|
||||
newColumnName = plural(newColumnName);
|
||||
}
|
||||
|
||||
@ -54,7 +60,7 @@ export function relationName(relation: Relation): string {
|
||||
if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) {
|
||||
newColumnName = newColumnName.substring(0, newColumnName.length - 1);
|
||||
}
|
||||
if (isRelationToMany) {
|
||||
if (isRelationToMany && pluralize) {
|
||||
newColumnName = plural(newColumnName);
|
||||
}
|
||||
return newColumnName;
|
||||
|
26
src/index.ts
26
src/index.ts
@ -239,6 +239,12 @@ function checkYargsParameters(options: options): options {
|
||||
default: options.generationOptions.generateConstructor,
|
||||
describe: "Generate constructor allowing partial initialization"
|
||||
},
|
||||
disablePluralization: {
|
||||
boolean: true,
|
||||
default: !options.generationOptions.pluralizeNames,
|
||||
describe:
|
||||
"Disable pluralization of OneToMany, ManyToMany relation names."
|
||||
},
|
||||
strictMode: {
|
||||
choices: ["none", "?", "!"],
|
||||
default: options.generationOptions.strictMode,
|
||||
@ -272,6 +278,7 @@ function checkYargsParameters(options: options): options {
|
||||
options.generationOptions.relationIds = argv.relationIds;
|
||||
options.generationOptions.skipSchema = argv.skipSchema;
|
||||
options.generationOptions.resultsPath = argv.o;
|
||||
options.generationOptions.pluralizeNames = !argv.disablePluralization;
|
||||
options.generationOptions.strictMode = argv.strictMode as IGenerationOptions["strictMode"];
|
||||
|
||||
return options;
|
||||
@ -399,6 +406,7 @@ async function useInquirer(options: options): Promise<options> {
|
||||
}
|
||||
]);
|
||||
if (customizeGeneration) {
|
||||
const defaultGenerationOptions = getDefaultGenerationOptions();
|
||||
const customizations: string[] = (
|
||||
await inquirer.prompt([
|
||||
{
|
||||
@ -446,7 +454,20 @@ async function useInquirer(options: options): Promise<options> {
|
||||
{
|
||||
name: "Use specific naming convention",
|
||||
value: "namingConvention",
|
||||
checked: options.generationOptions.lazy
|
||||
checked:
|
||||
options.generationOptions.convertCaseEntity !==
|
||||
defaultGenerationOptions.convertCaseEntity ||
|
||||
options.generationOptions
|
||||
.convertCaseProperty !==
|
||||
defaultGenerationOptions.convertCaseProperty ||
|
||||
options.generationOptions.convertCaseFile !==
|
||||
defaultGenerationOptions.convertCaseFile
|
||||
},
|
||||
{
|
||||
name:
|
||||
"Pluralize OneToMany, ManyToMany relation names.",
|
||||
value: "pluralize",
|
||||
checked: options.generationOptions.pluralizeNames
|
||||
}
|
||||
],
|
||||
message: "Available customizations",
|
||||
@ -484,6 +505,9 @@ async function useInquirer(options: options): Promise<options> {
|
||||
options.generationOptions.noConfigs = !customizations.includes(
|
||||
"config"
|
||||
);
|
||||
options.generationOptions.pluralizeNames = customizations.includes(
|
||||
"pluralize"
|
||||
);
|
||||
options.generationOptions.lazy = customizations.includes("lazy");
|
||||
options.generationOptions.activeRecord = customizations.includes(
|
||||
"activeRecord"
|
||||
|
@ -47,7 +47,7 @@ describe("Model customization phase", async () => {
|
||||
fieldName: "Post",
|
||||
relatedField: "authorId",
|
||||
relatedTable: "Post",
|
||||
relationType: "OneToOne"
|
||||
relationType: "OneToMany"
|
||||
}
|
||||
],
|
||||
relationIds: [],
|
||||
@ -101,7 +101,7 @@ describe("Model customization phase", async () => {
|
||||
{ name: "authorId", referencedColumnName: "id" }
|
||||
],
|
||||
relatedTable: "PostAuthor",
|
||||
relationType: "OneToOne"
|
||||
relationType: "ManyToOne"
|
||||
}
|
||||
],
|
||||
relationIds: [],
|
||||
@ -252,7 +252,7 @@ describe("Model customization phase", async () => {
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postContent).to.contain("Title: string;");
|
||||
expect(postAuthorContent).to.contain("Post: Post;");
|
||||
expect(postAuthorContent).to.contain("Posts: Post[];");
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -280,7 +280,7 @@ describe("Model customization phase", async () => {
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postContent).to.contain("title: string;");
|
||||
expect(postAuthorContent).to.contain("post: Post;");
|
||||
expect(postAuthorContent).to.contain("posts: Post[];");
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -310,7 +310,7 @@ describe("Model customization phase", async () => {
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postContent).to.have.string(" public title: string");
|
||||
expect(postAuthorContent).to.have.string(" public post: Post;");
|
||||
expect(postAuthorContent).to.have.string(" public posts: Post[];");
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -338,7 +338,7 @@ describe("Model customization phase", async () => {
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postContent).to.have.string(" title: string");
|
||||
expect(postAuthorContent).to.have.string(" post: Post;");
|
||||
expect(postAuthorContent).to.have.string(" posts: Post[];");
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -349,6 +349,7 @@ describe("Model customization phase", async () => {
|
||||
clearGenerationDir();
|
||||
|
||||
generationOptions.lazy = true;
|
||||
generationOptions.pluralizeNames = false;
|
||||
const customizedModel = modelCustomizationPhase(
|
||||
data,
|
||||
generationOptions,
|
||||
@ -369,7 +370,7 @@ describe("Model customization phase", async () => {
|
||||
expect(postContent).to.have.string("lazy: true");
|
||||
expect(postContent).to.have.string("Promise<PostAuthor>;");
|
||||
expect(postAuthorContent).to.have.string("lazy: true");
|
||||
expect(postAuthorContent).to.have.string("Promise<Post>");
|
||||
expect(postAuthorContent).to.have.string("Promise<Post[]>");
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -530,7 +531,7 @@ describe("Model customization phase", async () => {
|
||||
expect(postContent).to.have.string(`author!: PostAuthor;`);
|
||||
expect(postAuthorContent).to.have.string(`id!: number;`);
|
||||
expect(postAuthorContent).to.have.string(`name!: string;`);
|
||||
expect(postAuthorContent).to.have.string(`post!: Post;`);
|
||||
expect(postAuthorContent).to.have.string(`posts!: Post[];`);
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -563,7 +564,7 @@ describe("Model customization phase", async () => {
|
||||
expect(postContent).to.have.string(`author?: PostAuthor;`);
|
||||
expect(postAuthorContent).to.have.string(`id?: number;`);
|
||||
expect(postAuthorContent).to.have.string(`name?: string;`);
|
||||
expect(postAuthorContent).to.have.string(`post?: Post;`);
|
||||
expect(postAuthorContent).to.have.string(`posts?: Post[];`);
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
@ -612,4 +613,54 @@ describe("Model customization phase", async () => {
|
||||
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
});
|
||||
describe("pluralization", () => {
|
||||
it("enabled", async () => {
|
||||
|
||||
const data = generateSampleData();
|
||||
const generationOptions = generateGenerationOptions();
|
||||
generationOptions.pluralizeNames = true;
|
||||
clearGenerationDir();
|
||||
|
||||
const customizedModel = modelCustomizationPhase(
|
||||
data,
|
||||
generationOptions,
|
||||
{}
|
||||
);
|
||||
modelGenerationPhase(
|
||||
getDefaultConnectionOptions(),
|
||||
generationOptions,
|
||||
customizedModel
|
||||
);
|
||||
const filesGenPath = path.resolve(resultsPath, "entities");
|
||||
const postAuthorContent = fs
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postAuthorContent).to.contain("posts: 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");
|
||||
const postAuthorContent = fs
|
||||
.readFileSync(path.resolve(filesGenPath, "PostAuthor.ts"))
|
||||
.toString();
|
||||
expect(postAuthorContent).to.contain("post: Post[];");
|
||||
compileGeneratedModel(generationOptions.resultsPath, [""]);
|
||||
})
|
||||
})
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ConnectionOptions, createConnection } from "typeorm";
|
||||
import * as ts from "typescript";
|
||||
import * as yn from "yn";
|
||||
import IGenerationOptions from "../../src/IGenerationOptions";
|
||||
import IGenerationOptions, { getDefaultGenerationOptions } from "../../src/IGenerationOptions";
|
||||
import IConnectionOptions from "../../src/IConnectionOptions";
|
||||
import MssqlDriver from "../../src/drivers/MssqlDriver";
|
||||
import MariaDbDriver from "../../src/drivers/MariaDbDriver";
|
||||
@ -12,21 +12,9 @@ import MysqlDriver from "../../src/drivers/MysqlDriver";
|
||||
import path = require("path");
|
||||
|
||||
export function getGenerationOptions(resultsPath: string): IGenerationOptions {
|
||||
return {
|
||||
resultsPath,
|
||||
noConfigs: false,
|
||||
convertCaseEntity: "pascal",
|
||||
convertCaseFile: "pascal",
|
||||
convertCaseProperty: "camel",
|
||||
propertyVisibility: "none",
|
||||
lazy: false,
|
||||
generateConstructor: false,
|
||||
customNamingStrategyPath: "",
|
||||
relationIds: false,
|
||||
skipSchema: false,
|
||||
activeRecord: false,
|
||||
strictMode: "none"
|
||||
};
|
||||
const retVal = getDefaultGenerationOptions();
|
||||
retVal.resultsPath = resultsPath;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
export async function createMSSQLModels(
|
||||
@ -316,7 +304,7 @@ export function compileTsFiles(
|
||||
);
|
||||
console.log(
|
||||
`${diagnostic.file!.fileName} (${lineAndCharacter.line +
|
||||
1},${lineAndCharacter.character + 1}): ${message}`
|
||||
1},${lineAndCharacter.character + 1}): ${message}`
|
||||
);
|
||||
compiledWithoutErrors = false;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user