-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
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-662—generateFindUniqueArgsTypeandgenerateFindManyArgsType- Any downstream
generateCreateArgsType,generateUpdateArgsTypethat 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)generateCreateArgsTypeandgenerateUpdateArgsTypeif the runtime supportsqueryon 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
- 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)- Use it with
context.db.*:
const bills = await context.db.bill.findMany({
where: { account: { id: accountId } },
query: billFragment, // ← TypeScript error here
})- 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.