diff --git a/.changeset/silver-dolphins-hide.md b/.changeset/silver-dolphins-hide.md new file mode 100644 index 0000000000..7e5df8685d --- /dev/null +++ b/.changeset/silver-dolphins-hide.md @@ -0,0 +1,5 @@ +--- +"@comet/cms-api": minor +--- + +CRUD Generator: Add support for enum arrays in input diff --git a/packages/api/cms-api/src/generator/generate-crud-enum-array.spec.ts b/packages/api/cms-api/src/generator/generate-crud-enum-array.spec.ts new file mode 100644 index 0000000000..68fd002afa --- /dev/null +++ b/packages/api/cms-api/src/generator/generate-crud-enum-array.spec.ts @@ -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 { + @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(); + }); +}); diff --git a/packages/api/cms-api/src/generator/generate-crud-input.ts b/packages/api/cms-api/src/generator/generate-crud-input.ts index b12d4bc772..80d47c89c4 100644 --- a/packages/api/cms-api/src/generator/generate-crud-input.ts +++ b/packages/api/cms-api/src/generator/generate-crud-input.ts @@ -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; diff --git a/packages/api/cms-api/src/generator/utils/ts-morph-helper.ts b/packages/api/cms-api/src/generator/utils/ts-morph-helper.ts index 8748f9b592..21b60a074b 100644 --- a/packages/api/cms-api/src/generator/utils/ts-morph-helper.ts +++ b/packages/api/cms-api/src/generator/utils/ts-morph-helper.ts @@ -62,7 +62,8 @@ export function findEnumName(propertyName: string, metadata: EntityMetadata return tsProp .getType() .getText(tsProp) - .replace(/ ?\| ?undefined$/, ""); + .replace(/ ?\| ?undefined$/, "") + .replace(/\[\]$/, ""); } export function findEnumImportPath(enumName: string, generatorOptions: { targetDirectory: string }, metadata: EntityMetadata): string {