-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
API Generator: Fix imports in generated code for more than one level …
…deep relations (#2091) Fix two related issues: - input class: for more than one level deep nested impouts use the last entry from nestedInputFiles as that is the correct file - resolver imports: collect injectRepositories not only for generating constructor injects but also generate imports from it --------- Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com>
- Loading branch information
1 parent
696aefd
commit ebdd108
Showing
4 changed files
with
155 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@comet/cms-api": patch | ||
--- | ||
|
||
API Generator: Fix imports in generated code for more than one level deep relations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
packages/api/cms-api/src/generator/generate-crud-relations-two-levels.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import { BaseEntity, Collection, Entity, ManyToOne, OneToMany, OneToOne, PrimaryKey, Property, Ref } from "@mikro-orm/core"; | ||
import { MikroORM } from "@mikro-orm/postgresql"; | ||
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"; | ||
|
||
@Entity() | ||
class ProductVariant extends BaseEntity<ProductVariant, "id"> { | ||
@PrimaryKey({ type: "uuid" }) | ||
id: string = uuid(); | ||
|
||
@Property() | ||
title: string; | ||
|
||
@ManyToOne(() => ProductData, { ref: true }) | ||
productData: Ref<ProductData>; | ||
} | ||
|
||
@Entity() | ||
class ProductData extends BaseEntity<ProductData, "id"> { | ||
@PrimaryKey({ type: "uuid" }) | ||
id: string = uuid(); | ||
|
||
@OneToOne(() => Product, { ref: true }) | ||
product: Ref<Product>; | ||
|
||
@OneToMany(() => ProductVariant, (variant) => variant.productData, { orphanRemoval: true }) | ||
variants = new Collection<ProductVariant>(this); | ||
} | ||
|
||
@Entity() | ||
class Product extends BaseEntity<Product, "id"> { | ||
@PrimaryKey({ type: "uuid" }) | ||
id: string = uuid(); | ||
|
||
@Property() | ||
title: string; | ||
|
||
@OneToOne(() => ProductData, { ref: true }) | ||
data: Ref<ProductData>; | ||
} | ||
|
||
describe("generate-crud relations two levels", () => { | ||
it("should be a valid generated ts file", async () => { | ||
LazyMetadataStorage.load(); | ||
const orm = await MikroORM.init({ | ||
type: "postgresql", | ||
dbName: "test-db", | ||
entities: [Product, ProductData, ProductVariant], | ||
}); | ||
|
||
const out = await generateCrud({ targetDirectory: __dirname }, orm.em.getMetadata().get("Product")); | ||
const lintedOut = await lintGeneratedFiles(out); | ||
|
||
{ | ||
const file = lintedOut.find((file) => file.name === "product.resolver.ts"); | ||
if (!file) throw new Error("File not found"); | ||
const source = parseSource(file.content); | ||
|
||
const classes = source.getClasses(); | ||
expect(classes.length).toBe(1); | ||
|
||
const cls = classes[0]; | ||
expect(cls.getName()).toBe("ProductResolver"); | ||
const structure = cls.getStructure(); | ||
|
||
expect(structure.properties?.length).toBe(0); | ||
expect(structure.methods?.length).toBe(6); | ||
|
||
const imports: string[] = []; | ||
for (const tsImport of source.getImportDeclarations()) { | ||
for (const namedImport of tsImport.getNamedImports()) { | ||
imports.push(namedImport.getNameNode().getText()); | ||
} | ||
} | ||
expect(imports).toContain("ProductData"); //import for repository | ||
expect(imports).toContain("ProductVariant"); //import for repository | ||
} | ||
|
||
{ | ||
const file = lintedOut.find((file) => file.name === "dto/product.input.ts"); | ||
if (!file) throw new Error("File not found"); | ||
const source = parseSource(file.content); | ||
|
||
const classes = source.getClasses(); | ||
expect(classes.length).toBe(2); | ||
|
||
expect(classes[0].getName()).toBe("ProductInput"); | ||
expect(classes[1].getName()).toBe("ProductUpdateInput"); | ||
|
||
const structure = classes[0].getStructure(); | ||
|
||
expect(structure.properties?.length).toBe(2); | ||
expect(structure.properties?.[1].type).toBe("ProductNestedProductDataInput"); | ||
|
||
const imports: Record<string, string> = {}; | ||
for (const tsImport of source.getImportDeclarations()) { | ||
for (const namedImport of tsImport.getNamedImports()) { | ||
imports[namedImport.getNameNode().getText()] = tsImport.getModuleSpecifierValue(); | ||
} | ||
} | ||
expect(imports["ProductNestedProductDataInput"]).toBe("./product-nested-product-data.input"); | ||
} | ||
|
||
{ | ||
const file = lintedOut.find((file) => file.name === "dto/product-data-nested-product-variant.input.ts"); | ||
if (!file) throw new Error("File not found"); | ||
const source = parseSource(file.content); | ||
|
||
const classes = source.getClasses(); | ||
expect(classes.length).toBe(1); | ||
|
||
expect(classes[0].getName()).toBe("ProductDataNestedProductVariantInput"); | ||
|
||
const structure = classes[0].getStructure(); | ||
|
||
expect(structure.properties?.length).toBe(1); | ||
} | ||
|
||
{ | ||
const file = lintedOut.find((file) => file.name === "dto/product-data-nested-product-variant.input.ts"); | ||
if (!file) throw new Error("File not found"); | ||
const source = parseSource(file.content); | ||
|
||
const classes = source.getClasses(); | ||
expect(classes.length).toBe(1); | ||
|
||
expect(classes[0].getName()).toBe("ProductDataNestedProductVariantInput"); | ||
|
||
const structure = classes[0].getStructure(); | ||
|
||
expect(structure.properties?.length).toBe(1); | ||
} | ||
|
||
orm.close(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters