From 1f6c58e8afe370c9be14355211bfb13dd175061c Mon Sep 17 00:00:00 2001 From: Niko Sams Date: Mon, 19 Feb 2024 09:48:52 +0100 Subject: [PATCH] API Generator: support GraphQLJSONObject input for fields that are not a InputType class (#1688) Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com> --- .changeset/twenty-cobras-cough.md | 5 ++ .../generate-crud-input-json.spec.ts | 47 +++++++++++++++++++ .../src/generator/generate-crud-input.ts | 10 +++- 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 .changeset/twenty-cobras-cough.md diff --git a/.changeset/twenty-cobras-cough.md b/.changeset/twenty-cobras-cough.md new file mode 100644 index 0000000000..466d8dd5b2 --- /dev/null +++ b/.changeset/twenty-cobras-cough.md @@ -0,0 +1,5 @@ +--- +"@comet/cms-api": patch +--- + +API Generator: support GraphQLJSONObject input for fields that are not a InputType class diff --git a/packages/api/cms-api/src/generator/generate-crud-input-json.spec.ts b/packages/api/cms-api/src/generator/generate-crud-input-json.spec.ts index 61b5a5a00e..6a72923b2a 100644 --- a/packages/api/cms-api/src/generator/generate-crud-input-json.spec.ts +++ b/packages/api/cms-api/src/generator/generate-crud-input-json.spec.ts @@ -51,6 +51,15 @@ export class TestEntityWithEmbedded extends BaseEntity TestEmbedded) foo: TestEmbedded; } + +@Entity() +export class TestEntityWithRecord extends BaseEntity { + @PrimaryKey({ type: "uuid" }) + id: string = uuid(); + + @Property({ type: "json" }) + foo: Record; +} describe("GenerateCrudInputJson", () => { describe("input class literal array", () => { it("should be a valid generated ts file", async () => { @@ -163,4 +172,42 @@ describe("GenerateCrudInputJson", () => { orm.close(); }); }); + + describe("input class record", () => { + it("should be a valid generated ts file", async () => { + LazyMetadataStorage.load(); + const orm = await MikroORM.init({ + type: "postgresql", + dbName: "test-db", + entities: [TestEntityWithRecord], + }); + + const out = await generateCrudInput({ targetDirectory: __dirname }, orm.em.getMetadata().get("TestEntityWithRecord")); + const lintedOutput = await lintSource(out[0].content); + const source = parseSource(lintedOutput); + + const classes = source.getClasses(); + expect(classes.length).toBe(2); + + { + const cls = classes[0]; + const structure = cls.getStructure(); + + expect(structure.properties?.length).toBe(1); + expect(structure.properties?.[0].name).toBe("foo"); + expect(structure.properties?.[0].type).toBe("Record"); + expect(structure.properties?.[0].decorators?.[0].name).toBe("IsNotEmpty"); + expect(structure.properties?.[0].decorators?.[1].name).toBe("Field"); + expect(structure.properties?.[0].decorators?.[1].arguments).toStrictEqual(["() => GraphQLJSONObject"]); + } + { + const cls = classes[1]; //update dto + const structure = cls.getStructure(); + + expect(structure.properties?.length).toBe(0); + } + + 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 4af6057777..6eb9e50dd8 100644 --- a/packages/api/cms-api/src/generator/generate-crud-input.ts +++ b/packages/api/cms-api/src/generator/generate-crud-input.ts @@ -274,21 +274,27 @@ export async function generateCrudInput( } else if (type == "boolean[]") { decorators.push(`@Field(() => [Boolean], ${fieldOptions})`); decorators.push("@IsBoolean({ each: true })"); - } else { + } else if (tsType.getArrayElementTypeOrThrow().isClass()) { const nestedClassName = tsType.getArrayElementTypeOrThrow().getText(tsProp); const importPath = findInputClassImportPath(nestedClassName, generatorOptions, metadata); imports.push({ name: nestedClassName, importPath }); decorators.push(`@ValidateNested()`); decorators.push(`@Type(() => ${nestedClassName})`); decorators.push(`@Field(() => [${nestedClassName}], ${fieldOptions})`); + } else { + decorators.push(`@Field(() => [GraphQLJSONObject], ${fieldOptions}) // Warning: this input is not validated properly`); } - } else { + } else if (tsType.isClass()) { const nestedClassName = tsType.getText(tsProp); const importPath = findInputClassImportPath(nestedClassName, generatorOptions, metadata); imports.push({ name: nestedClassName, importPath }); decorators.push(`@ValidateNested()`); decorators.push(`@Type(() => ${nestedClassName})`); decorators.push(`@Field(() => ${nestedClassName}${prop.nullable ? ", { nullable: true }" : ""})`); + } else { + decorators.push( + `@Field(() => GraphQLJSONObject${prop.nullable ? ", { nullable: true }" : ""}) // Warning: this input is not validated properly`, + ); } } else if (prop.type == "uuid") { const initializer = morphTsProperty(prop.name, metadata).getInitializer()?.getText();