Skip to content

Prevent self-referential imports in code generation - #25

Open
kac-axelor wants to merge 2 commits into
axelor:devfrom
kac-axelor:fix-self-import
Open

kac-axelor wants to merge 2 commits into
axelor:devfrom
kac-axelor:fix-self-import

Conversation

@kac-axelor

@kac-axelor kac-axelor commented May 22, 2026 •

Copy link
Copy Markdown
Contributor

Reopens the fix from #20 (closed as superseded, but the cases it covers are still broken on dev).

What this fixes

Self-referential relation imports. A tree-shaped entity like:

defineEntity({
  name: "Category",
  fields: [
    { name: "parent",   type: "ManyToOne", target: "Category" },
    { name: "children", type: "OneToMany", target: "Category", mappedBy: "parent" },
  ],
});

…causes RelationalField.actualType (src/schema/schema-generator.ts:232-236) to register import { Category } from "./Category" in the generated Category.ts, producing:

TS2440: Import declaration conflicts with local declaration of 'Category'.
TS2395: Individual declarations in merged declaration 'Category' must be all exported or all local.

Relationship to d2ce123

d2ce123 ("Drop self-referential extends/implements at the source") fixes a different layer — the extends / implements clauses in the class declaration. It does not touch relation imports, so this PR is complementary, not redundant.

Approach

Filter self-referential imports at the CodeFile level — a single choke point that covers any generator that happens to emit import { X } from "./X" for the file currently being written. Cheap, local, and future-proof against new generators.

Test

Added a regression test (schema-generator.test.ts) using a self-referencing Category entity with parent: ManyToOne(target: "Category") and children: OneToMany(target: "Category", mappedBy: "parent"). The test asserts:

  • No import { Category } from "./Category" line in the generated file.
  • The relation type still renders correctly as Relation<Category> and Relation<Category>[].

The test fails on dev without this PR's CodeFile filter and passes with it.

@kac-axelor

Copy link
Copy Markdown
Contributor Author

Merge coordination with #33 — no git conflict, but a test interaction: should not emit self-imports for relations targeting the entity itself asserts children?: Relation<Category>[], while #33's generator emits OneToMany collections as ToMany<Category, "parent"> (mappedBy is required on OneToMany in the schema types, so every OneToMany takes this form; Relation<T>[] remains the shape of ManyToMany collections). The no-self-import guarantee holds for both forms.

Whichever lands second should update the test to cover both collection shapes, e.g. add a ManyToMany self-relation:

// entity fields: + { name: "related", type: "ManyToMany", target: "Category" }
expect(code).not.toMatch(/from "\.\/Category"/);
expect(code).toMatch(/parent\?:\s*Relation<Category>/);
expect(code).toMatch(/children\?:\s*ToMany<Category, "parent">/);
expect(code).toMatch(/related\?:\s*Relation<Category>\[\]/);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant