Skip to content

Commit

Permalink
CRUD Generator: Add support for enum arrays in input (#1454)
Browse files Browse the repository at this point in the history
Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com>
  • Loading branch information
nsams and johnnyomair authored Dec 14, 2023
1 parent af7af20 commit 8d0e3ee
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/silver-dolphins-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/cms-api": minor
---

CRUD Generator: Add support for enum arrays in input
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { BaseEntity, Entity, Enum, PrimaryKey } from "@mikro-orm/core";
import { MikroORM } from "@mikro-orm/postgresql";
import { Field, registerEnumType } from "@nestjs/graphql";
import { LazyMetadataStorage } from "@nestjs/graphql/dist/schema-builder/storages/lazy-metadata.storage";
import { v4 as uuid } from "uuid";

import { generateCrud } from "./generate-crud";
import { lintGeneratedFiles, parseSource } from "./utils/test-helper";

export enum TestEnum {
ONE = "ONE",
TWO = "TWO",
}
registerEnumType(TestEnum, {
name: "TestEnum",
});

@Entity()
class TestEntity extends BaseEntity<TestEntity, "id"> {
@PrimaryKey({ type: "uuid" })
id: string = uuid();

@Field(() => [TestEnum])
@Enum({ items: () => TestEnum, array: true })
foo?: TestEnum;
}

describe("GenerateCrudEnumArray", () => {
it("should correctly add EnumArrayType in input type", async () => {
LazyMetadataStorage.load();
const orm = await MikroORM.init({
type: "postgresql",
dbName: "test-db",
entities: [TestEntity],
});

const out = await generateCrud({ targetDirectory: __dirname }, orm.em.getMetadata().get("TestEntity"));
const lintedOut = await lintGeneratedFiles(out);
const file = lintedOut.find((file) => file.name === "dto/test-entity.input.ts");
if (!file) throw new Error("File not found");
const source = parseSource(file.content);

const classes = source.getClasses();
expect(classes.length).toBe(2);

const cls = classes[0];
const structure = cls.getStructure();
expect(structure.properties?.length).toBe(1);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const prop = structure.properties![0];
expect(prop.name).toBe("foo");
expect(prop.type).toBe("TestEnum[]");
const decorators = prop.decorators?.map((i) => i.name);
expect(decorators).toContain("Field");
expect(decorators).toContain("IsEnum");

orm.close();
});
});
13 changes: 13 additions & 0 deletions packages/api/cms-api/src/generator/generate-crud-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ export async function generateCrudInput(
decorators.push(`@IsEnum(${enumName})`);
decorators.push(`@Field(() => ${enumName}, ${fieldOptions})`);
type = enumName;
} else if (prop.type === "EnumArrayType") {
if (prop.nullable) {
console.warn(`${prop.name}: Nullable enum arrays are not supported`);
}
decorators.length = 0; //remove @IsNotEmpty
const initializer = morphTsProperty(prop.name, metadata).getInitializer()?.getText();
const fieldOptions = tsCodeRecordToString({ defaultValue: initializer });
const enumName = findEnumName(prop.name, metadata);
const importPath = findEnumImportPath(enumName, generatorOptions, metadata);
imports.push({ name: enumName, importPath });
decorators.push(`@IsEnum(${enumName}, { each: true })`);
decorators.push(`@Field(() => [${enumName}], ${fieldOptions})`);
type = `${enumName}[]`;
} else if (prop.type === "string" || prop.type === "text") {
const initializer = morphTsProperty(prop.name, metadata).getInitializer()?.getText();
const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null") ? "null" : initializer;
Expand Down
3 changes: 2 additions & 1 deletion packages/api/cms-api/src/generator/utils/ts-morph-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export function findEnumName(propertyName: string, metadata: EntityMetadata<any>
return tsProp
.getType()
.getText(tsProp)
.replace(/ ?\| ?undefined$/, "");
.replace(/ ?\| ?undefined$/, "")
.replace(/\[\]$/, "");
}

export function findEnumImportPath(enumName: string, generatorOptions: { targetDirectory: string }, metadata: EntityMetadata<any>): string {
Expand Down

0 comments on commit 8d0e3ee

Please sign in to comment.