Skip to content

Issue: Recursive Type Generates Incorrect Schema Options #39

@inspire-man

Description

@inspire-man

​​Problem Description:​​
When generating Where input types for models with recursive queries (e.g., AND/OR conditions), the generated TypeBox schema does not correctly propagate the $id option to the outer t.Partial() wrapper. This causes TypeBox's recursive type resolution to fail with the error: Unable to dereference schema with $id 'Article'.

Current Behavior
Prismabox generates this problematic structure:

export const ArticleWhere = t.Partial(
  t.Recursive(
    (Self) => t.Object(...),
    { $id: "Article" }  // ✅ $id only added to inner Recursive()
  ),
  // ❌ Missing $id for Partial()
);

Expected Behavior
For recursive Where types to work correctly, the $id must be applied to the outer Partial() wrapper:

export const ArticleWhere = t.Partial(
  t.Recursive(
    (Self) => t.Object(...),
    { $id: "Article_Where_Inner" }  // Unique inner ID
  ),
  { $id: "ArticleWhere" }  // ✅ Critical: $id applied to Partial()
);

Minimal Reproduction
​​prisma/schema.prisma:​

model Article {
  id          String  @id @default(nanoid(32))
  title       String
  content     String
  // ... other fields
}

prismabox config:​

generator prismabox {
  provider = "prismabox"
  output = "./generated"
  inputModel = "true"
  typeboxImportDependencyName = "elysia"
  typeboxImportVariableName = "t"
}

Generated article.ts:​

// Notice the missing $id for t.Partial
export const ArticleWhere = t.Partial(
  t.Recursive(
    (Self) => t.Object(...),
    { $id: "Article" }
  )
);

Error Details

1 | export class TypeBoxError extends Error {
   | ^
error: Unable to dereference schema with $id 'Article'
 schema: {
  $ref: "Article",
  [Symbol(TypeBox.Kind)]: "This",
}

Proposed Solution
Modify the generator logic to:

  1. Add $id to the outer t.Partial() wrapper
  2. Ensure unique naming conventions to avoid conflicts:
export const ArticleWhere = t.Partial(
  t.Recursive(
    (Self) => t.Object(...),
    { $id: `Article_BaseWhere` } // Unique inner ID
  ),
  { $id: `ArticleWhere` } // Outer partial gets main ID
);
  1. For nested types, use predictable naming:
{ $id: `${ModelName}Where` }         // Top-level where
{ $id: `${ModelName}WhereCondition` } // For nested conditions

Environment
Prismabox version: [e.g., 0.4.2]
Bun version: [e.g., 1.1.4]
TypeBox version: [e.g., 0.32.15]
Why This Matters
Recursive query types are essential for complex filtering operations. This bug prevents the use of AND/OR/NOT query logic in generated APIs, significantly limiting Prisma's advanced query capabilities in TypeBox-based projects.

This issue was filed by: pwaner

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions