Skip to content

Commit

Permalink
API Generator: support GraphQLJSONObject input for fields that are no…
Browse files Browse the repository at this point in the history
…t a InputType class (#1688)

Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com>
  • Loading branch information
nsams and johnnyomair authored Feb 19, 2024
1 parent c6d55b5 commit 1f6c58e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-cobras-cough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/cms-api": patch
---

API Generator: support GraphQLJSONObject input for fields that are not a InputType class
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ export class TestEntityWithEmbedded extends BaseEntity<TestEntityWithEmbedded, "
@Embedded(() => TestEmbedded)
foo: TestEmbedded;
}

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

@Property({ type: "json" })
foo: Record<string, string>;
}
describe("GenerateCrudInputJson", () => {
describe("input class literal array", () => {
it("should be a valid generated ts file", async () => {
Expand Down Expand Up @@ -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<string, string>");
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();
});
});
});
10 changes: 8 additions & 2 deletions packages/api/cms-api/src/generator/generate-crud-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 1f6c58e

Please sign in to comment.