Skip to content

Generated args types missing query parameter for fragment-based queries #380

@borisno2

Description

@borisno2

Summary

The OpenSaaS generator emits FindManyArgs, FindUniqueArgs, FindFirstArgs, CreateArgs, and UpdateArgs types that include only select and include — but not the query parameter that the runtime context methods accept for fragment-based queries. Attempting to pass a Fragment to any context.db.* method produces a TypeScript error (Type 'Fragment<...>' is not assignable to type 'never'), even though the runtime handles it correctly.

Expected Behavior

Generated args types should include the query parameter so that the documented fragment pattern compiles without error:

const bills = await context.db.bill.findMany({
  where: { account: { id: accountId } },
  query: billFragment, // ✅ should be valid
})

Current Behavior

TypeScript rejects the query parameter because it is absent from the generated type:

Argument of type '{ where: ...; query: Fragment<BillOutput, ...> }' is not assignable
to parameter of type 'Prisma.SelectSubset<..., BillFindManyArgs>'.
  Object literal may only specify known properties, and 'query' does not exist
  in type 'BillFindManyArgs'.

Root Cause

The generator functions in packages/cli/src/generator/types.ts at lines 623–662 produce the args types but omit query:

Affected files:

  • packages/cli/src/generator/types.ts:623-662generateFindUniqueArgsType and generateFindManyArgsType
  • Any downstream generateCreateArgsType, generateUpdateArgsType that follow the same pattern

Generated output (current):

// ❌ packages/cli/src/generator/types.ts:647-660
export type BillFindManyArgs = Omit<Prisma.BillFindManyArgs, 'select' | 'include'> & {
  select?: BillSelect | null
  include?: BillInclude | null
  // ← query is absent; TypeScript rejects fragment usage
}

The runtime createFindMany (in packages/core/src/context/index.ts:710) correctly accepts query?: any and calls isFragment(args?.query) to build the include. The disconnect is purely between the generated TypeScript types and the runtime implementation.

Proposed Solution

Add query?: Fragment<{ListName}Output, FieldSelection<{ListName}Output>> to every generated args type that the runtime accepts a fragment on.

// ✅ packages/cli/src/generator/types.ts — generateFindManyArgsType
import type { Fragment, FieldSelection } from '@opensaas/stack-core'

export type ${listName}FindManyArgs = Omit<Prisma.${listName}FindManyArgs, 'select' | 'include'> & {
  select?: ${listName}Select | null
  include?: ${listName}Include | null
  query?: Fragment<${listName}Output, FieldSelection<${listName}Output>>
}

The same change applies to:

  • generateFindUniqueArgsType (packages/cli/src/generator/types.ts:623)
  • generateFindManyArgsType (packages/cli/src/generator/types.ts:647)
  • generateCreateArgsType and generateUpdateArgsType if the runtime supports query on those methods too

The Fragment and FieldSelection types are already exported from @opensaas/stack-core (see packages/core/src/query/index.ts), so no new exports are needed — just the import in the generated file header.

Reproduction

  1. Define a fragment:
import { defineFragment } from '@opensaas/stack-core'
import type { BillOutput } from './.opensaas/types'

const billFragment = defineFragment<BillOutput>()({
  id: true,
  amount: true,
  status: true,
} as const)
  1. Use it with context.db.*:
const bills = await context.db.bill.findMany({
  where: { account: { id: accountId } },
  query: billFragment, // ← TypeScript error here
})
  1. TypeScript error:
Object literal may only specify known properties, and 'query' does not exist in type 'BillFindManyArgs'.

Priority

High — the query/fragment pattern is documented as the preferred approach for typed query results (ResultOf<typeof fragment> vs the more verbose BillGetPayload<{ select: typeof billSelect }>). The missing type forces developers to abandon the documented pattern or use as any casts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions