fix: Improve data operations DX by renaming ModelQuery to ModelInclude and use intermediate variable for commit results#809
Conversation
…ations by omitting query spread from execute callbacks when the model has no include support
…`, fix `GetPayload` to eliminate `Payload | {}` union, and use intermediate variable for commit results. Fix type error for relation-less models by omitting query spread from execute callbacks.
|
| Name | Type |
|---|---|
| @baseplate-dev/fastify-generators | Patch |
| @baseplate-dev/project-builder-server | Patch |
| @baseplate-dev/plugin-auth | Patch |
| @baseplate-dev/plugin-email | Patch |
| @baseplate-dev/plugin-queue | Patch |
| @baseplate-dev/plugin-rate-limit | Patch |
| @baseplate-dev/plugin-storage | Patch |
| @baseplate-dev/create-project | Patch |
| @baseplate-dev/project-builder-cli | Patch |
| @baseplate-dev/project-builder-common | Patch |
| @baseplate-dev/project-builder-dev | Patch |
| @baseplate-dev/project-builder-web | Patch |
| @baseplate-dev/project-builder-test | Patch |
| @baseplate-dev/code-morph | Patch |
| @baseplate-dev/core-generators | Patch |
| @baseplate-dev/project-builder-lib | Patch |
| @baseplate-dev/react-generators | Patch |
| @baseplate-dev/sync | Patch |
| @baseplate-dev/tools | Patch |
| @baseplate-dev/ui-components | Patch |
| @baseplate-dev/utils | Patch |
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR migrates public Prisma query types from select-or-include to include-only: renames Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (1)
583-617:⚠️ Potential issue | 🟡 MinorDocument the fields on these exported input interfaces.
These interfaces are part of the changed public surface, but their fields are still undocumented. Please add field-level JSDoc for
data/where,query, andcontext.Example shape
export interface DataCreateInput< TModelName extends ModelPropName, TFields extends Record<string, AnyFieldDefinition>, TIncludeArgs extends ModelInclude<TModelName> = ModelInclude<TModelName>, > { + /** Input data for the create operation. */ data: InferInput<TFields>; + /** Optional Prisma include arguments used to shape the returned payload. */ query?: TIncludeArgs; + /** Request-scoped service context. */ context: ServiceContext; }As per coding guidelines, "Add JSDocs to all exported functions, interfaces, and classes with documentation of parameters, return values, and all fields".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts` around lines 583 - 617, Add JSDoc comments to the exported interfaces DataCreateInput, DataUpdateInput, and DataDeleteInput documenting each field: for DataCreateInput document the `data` (shape and purpose), optional `query` (what include/relations it accepts), and `context` (ServiceContext purpose and usage); for DataUpdateInput document `where` (unique identifier semantics), `data` (partial update payload), optional `query`, and `context`; for DataDeleteInput document `where`, optional `query`, and `context`. Keep each field description concise, mention types (e.g., InferInput<TFields>, WhereUniqueInput<TModelName>, ModelInclude) and whether the field is optional, and place the JSDoc immediately above each interface declaration (DataCreateInput, DataUpdateInput, DataDeleteInput).packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (1)
631-655:⚠️ Potential issue | 🟠 MajorMake
query.includeoptional in all threeCommit*Configexecute callbacks.
CommitCreateConfig,CommitUpdateConfig, andCommitDeleteConfigcan all invokeexecutewith{}when no include relations are requested, but the current type signature requiresargs.query.includeto always be present. This contract violation allows code to type-check but fail at runtime if a callback implementation accessesquery.includedirectly.Proposed fix
Change
query: { include: NonNullable<TIncludeArgs['include']> }toquery: { include?: NonNullable<TIncludeArgs['include']> }in theexecutecallback argument type for all three interfaces.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts` around lines 631 - 655, The execute callback argument types in CommitCreateConfig, CommitUpdateConfig, and CommitDeleteConfig currently require query.include to always be present; change the execute signature for each (the execute: (args: { tx: PrismaTransaction; ...; query: { include: NonNullable<TIncludeArgs['include']> }; serviceContext: ServiceContext; }) => ...) so that query.include is optional by replacing query: { include: NonNullable<TIncludeArgs['include']> } with query: { include?: NonNullable<TIncludeArgs['include']> } in all three interfaces (CommitCreateConfig, CommitUpdateConfig, CommitDeleteConfig) so callers can pass {} when no includes are requested.packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts (1)
32-37:⚠️ Potential issue | 🟠 MajorAllow
select: undefinedto match theModelIncludetype contract.
ModelInclude<TModelName>explicitly permitsselect?: undefined, but this validation throws whenever theselectkey exists, causing any typed callers that preserveselect: undefinedto fail at runtime. This is a type/runtime mismatch.Proposed fix
function validateQuery(query: unknown, operation: string): void { - if (query && typeof query === 'object' && 'select' in query) { + if ( + query && + typeof query === 'object' && + 'select' in query && + (query as { select?: unknown }).select !== undefined + ) { throw new Error( `Query select is not supported for ${operation} operations. Use include instead.`, ); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts` around lines 32 - 37, The validateQuery function currently rejects any query object that contains a select key; change the check in validateQuery(query: unknown, operation: string) so it only throws when select is present and not strictly undefined (i.e., the property exists with a defined value), allowing select?: undefined per the ModelInclude<TModelName> contract; update the condition to test that (query as any).select !== undefined before throwing and keep the error message and operation reference intact.
🧹 Nitpick comments (4)
examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list-share.data-service.ts (1)
41-52: Add JSDoc for the exported todo-list-share service functions.
createTodoListShare,updateTodoListShare, anddeleteTodoListSharewere updated here, but they still have no JSDoc blocks. Please document parameters and returned payloads on these exports.As per coding guidelines: Add JSDoc comments to all exported functions, interfaces, and classes documenting the function/type, parameters, return value, and all fields.
Also applies to: 83-95, 124-133
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list-share.data-service.ts` around lines 41 - 52, Add JSDoc blocks to the exported service functions createTodoListShare, updateTodoListShare, and deleteTodoListShare: for each function document what it does, describe the parameters (data/input, query, context) including their types (DataCreateInput/DataUpdateInput/DataDeleteInput for 'todoListShare' and TIncludeArgs), and document the returned payload type (Promise<GetPayload<'todoListShare', TIncludeArgs>>). Place the JSDoc immediately above each function export (e.g., above the createTodoListShare declaration and the corresponding updateTodoListShare and deleteTodoListShare declarations) and include brief descriptions for any important fields on input and the structure of the returned GetPayload.examples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user.data-service.ts (1)
105-113: Add JSDoc for the exported data-service functions.
createUser,updateUser, anddeleteUserwere modified here, but they still have no JSDoc blocks. Please document the parameters and returned payloads on these exported entry points.As per coding guidelines: Add JSDoc comments to all exported functions, interfaces, and classes documenting the function/type, parameters, return value, and all fields.
Also applies to: 138-147, 172-180
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user.data-service.ts` around lines 105 - 113, Add JSDoc blocks for the exported data-service functions createUser, updateUser, and deleteUser: document the function purpose, each parameter (e.g., the destructured data/input, query, and context parameters typed via DataCreateInput/DataUpdateInput/DataDeleteInput and ModelInclude), and the returned payload type (GetPayload<'user', TIncludeArgs> or equivalent). Place the JSDoc immediately above each exported function declaration (createUser, updateUser, deleteUser), include `@param` entries for input/data, query, and context, and an `@returns` describing the resolved payload shape and generic TIncludeArgs behavior.examples/blog-with-auth/apps/backend/src/modules/blogs/services/blog.data-service.ts (1)
31-40: Document the exported service functions.
updateBloganddeleteBlogare modified exported entry points and still have no JSDoc. Please add docs for inputs and returned payload shapes here.As per coding guidelines: Add JSDocs to all exported functions, interfaces, and classes with documentation of parameters, return values, and all fields.
Also applies to: 65-73
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/blog-with-auth/apps/backend/src/modules/blogs/services/blog.data-service.ts` around lines 31 - 40, Add JSDoc comments for the exported service functions updateBlog and deleteBlog: document each parameter (where, data/input, query, context) including their types (DataUpdateInput<'blog', typeof blogInputFields, TIncludeArgs> and corresponding delete input), explain the generic TIncludeArgs and what it controls, and describe the returned payload shape (GetPayload<'blog', TIncludeArgs>) and any possible throws/errors; place these comments immediately above the exported functions (updateBlog and deleteBlog) and ensure parameter names, generic type usage, and return type are explicitly described so IDEs and generated docs show inputs and the payload structure.examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-item.data-service.ts (1)
66-76: Add JSDoc for the exported todo-item service API.
createTodoItem,updateTodoItem, anddeleteTodoItemwere touched in this PR, but they still have no JSDoc blocks. Please document parameters and returned payloads on these exports.As per coding guidelines: Add JSDoc comments to all exported functions, interfaces, and classes documenting the function/type, parameters, return value, and all fields.
Also applies to: 109-120, 153-160
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-item.data-service.ts` around lines 66 - 76, Add JSDoc blocks for the exported service functions createTodoItem, updateTodoItem, and deleteTodoItem: describe each function's purpose, document the generic type parameter TIncludeArgs, and annotate the parameters (data/input, query, context) including their shapes/types (e.g., DataCreateInput/DataUpdateInput/DataDeleteInput for 'todoItem') and the returned Promise payload (Promise<GetPayload<'todoItem', TIncludeArgs>>), making sure the docs mention what fields are included in the payload when different include args are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@examples/blog-with-auth/apps/backend/src/modules/accounts/services/user.data-service.ts`:
- Around line 37-45: The generic default for TIncludeArgs causes omitted query
parameters to still infer a ModelInclude type; update the type constraints so
TIncludeArgs can be undefined and defaults to undefined: change the generic
constraint in the shared input types (DataCreateInput, DataUpdateInput,
DataDeleteInput) from "TIncludeArgs extends ModelInclude<TModelName> =
ModelInclude<TModelName>" to "TIncludeArgs extends ModelInclude<TModelName> |
undefined = undefined", and update the service method signatures (createUser,
updateUser, deleteUser) to use the same TIncludeArgs extends
ModelInclude<'user'> | undefined = undefined so that when query is omitted the
return type becomes GetPayload<'user', undefined>.
In
`@examples/blog-with-auth/apps/backend/src/modules/articles/services/article.data-service.ts`:
- Around line 34-44: Add JSDoc blocks for the exported service functions
createArticle and updateArticle: for each function document the purpose,
describe each parameter (data/input, query, context and the generic
TIncludeArgs), list the return type (Promise<GetPayload<'article',
TIncludeArgs>>), and note any thrown errors or side effects; place the JSDoc
immediately above the function declarations (createArticle and updateArticle)
and include `@param` and `@returns` tags and brief descriptions of the data shape
based on articleInputFields.
In
`@examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts`:
- Around line 57-72: The refetchResult function currently casts the callback
return to include relations because refetchWithQuery is typed as
Promise<GetPayload<TModelName>); update the refetchWithQuery signature in
CommitCreateConfig and CommitUpdateConfig (types.ts) to return
Promise<GetPayload<TModelName, TIncludeArgs>> so the callback is required to
include the relations from query, then remove the forced cast in refetchResult
and return the callback result directly (i.e., have refetchResult return the
Promise<GetPayload<TModelName, TIncludeArgs>> returned by refetchWithQuery).
In
`@examples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user-image.data-service.ts`:
- Around line 24-31: Add a JSDoc comment above the exported async function
deleteUserImage that documents the function purpose, each parameter (where,
query, context from the DataDeleteInput<'userImage', TIncludeArgs> object), the
generic TIncludeArgs type constraint, and the return value
(Promise<GetPayload<'userImage', TIncludeArgs>>); include brief descriptions for
the DataDeleteInput properties and mention that it deletes a userImage and
returns the deleted userImage payload (including any included relations), and
annotate thrown errors or exceptions if applicable.
In
`@examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list.data-service.ts`:
- Around line 49-59: Add JSDoc comments for the exported service functions
createTodoList, updateTodoList, and deleteTodoList: for each function document
the purpose, each parameter (data/input, query, context with types like
DataCreateInput/DataUpdateInput/DataDeleteInput and generic TIncludeArgs), and
the Promise return type (GetPayload<'todoList', TIncludeArgs>). Place the JSDoc
immediately above the function declarations (e.g., above createTodoList,
updateTodoList, deleteTodoList) and include descriptions of the generic
TIncludeArgs and any important behavior/side-effects (errors thrown or DB
interactions) per the coding guidelines.
In
`@examples/todo-with-better-auth/apps/backend/src/utils/data-operations/prisma-types.ts`:
- Around line 62-67: The ModelInclude type currently permits a select key via
"select?: undefined" which conflicts with validateQuery() in
commit-operations.ts (and therefore breaks queryFromInfo() at runtime); remove
the "select?: undefined" clause from ModelInclude in prisma-types.ts so the type
no longer allows a select property, or alternatively make validateQuery()
explicitly accept select: undefined — pick the former to align types with
runtime validation by editing the ModelInclude definition (symbol: ModelInclude)
in prisma-types.ts and ensure queryFromInfo()/validateQuery() (symbols:
queryFromInfo, validateQuery in commit-operations.ts) continue to operate
without needing to strip select.
In
`@examples/todo-with-better-auth/apps/backend/src/utils/data-operations/prisma-utils.ts`:
- Around line 24-27: The findUnique signature currently defines TIncludeArgs
only in the return type so TypeScript cannot infer payload shape from the passed
include; change the signature so TIncludeArgs is bound to the args.include
parameter (i.e., make include use the generic type TIncludeArgs instead of a
separate NonNullable<ModelInclude<...>['include']>), and keep the return type as
Promise<GetPayload<TModelName, TIncludeArgs> | null>; update the same pattern
for any sibling methods using GetPayload so callers in commit-operations.ts and
field-definitions.ts no longer need manual casts.
In
`@examples/todo-with-better-auth/apps/backend/src/utils/data-operations/types.ts`:
- Around line 641-644: The refetchWithQuery callback currently uses the loose
type Promise<GetPayload<TModelName>> and accepts result: GetPayload<TModelName>,
which lets implementations ignore the include args; update the signature of
refetchWithQuery to accept result: GetPayload<TModelName, TIncludeArgs> and
return Promise<GetPayload<TModelName, TIncludeArgs>> (keeping the query:
TIncludeArgs param) so implementations must produce the include-shaped payload;
adjust any call sites of refetchWithQuery/refetchWithQuery implementations to
match the tightened signature.
In
`@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.ts`:
- Around line 47-68: The runtime validator currently treats any presence of a
'select' key as an error even when its value is undefined (contradicting the
ModelInclude<TModelName> JSDoc), so update the validator (function
validateQuery) to treat select: undefined as acceptable by checking the value
rather than only the key; replace the check "'select' in query" with a check
like "('select' in query && query.select !== undefined)" (or equivalently
"typeof query.select !== 'undefined'") so only non-undefined select values
trigger the runtime error while preserving ModelInclude's allowance for select?:
undefined.
In
`@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.ts`:
- Around line 26-29: The findUnique signature's generic TIncludeArgs defaults to
object and isn't inferred from the include parameter, so update the generic to
be tied to the include arg: replace the current TIncludeArgs definition with one
constrained to ModelInclude<TModelName>['include'] (or inferred from the args)
and change the args.include type to be of that generic (e.g., include?:
TIncludeArgs) so TypeScript can infer GetPayload<TModelName, TIncludeArgs>;
modify the findUnique declaration (symbol: findUnique) to use the new generic
constraint instead of object, keeping GetPayload<TModelName, TIncludeArgs> as
the return payload type to restore correct inference.
---
Outside diff comments:
In `@examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts`:
- Around line 583-617: Add JSDoc comments to the exported interfaces
DataCreateInput, DataUpdateInput, and DataDeleteInput documenting each field:
for DataCreateInput document the `data` (shape and purpose), optional `query`
(what include/relations it accepts), and `context` (ServiceContext purpose and
usage); for DataUpdateInput document `where` (unique identifier semantics),
`data` (partial update payload), optional `query`, and `context`; for
DataDeleteInput document `where`, optional `query`, and `context`. Keep each
field description concise, mention types (e.g., InferInput<TFields>,
WhereUniqueInput<TModelName>, ModelInclude) and whether the field is optional,
and place the JSDoc immediately above each interface declaration
(DataCreateInput, DataUpdateInput, DataDeleteInput).
In
`@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts`:
- Around line 32-37: The validateQuery function currently rejects any query
object that contains a select key; change the check in validateQuery(query:
unknown, operation: string) so it only throws when select is present and not
strictly undefined (i.e., the property exists with a defined value), allowing
select?: undefined per the ModelInclude<TModelName> contract; update the
condition to test that (query as any).select !== undefined before throwing and
keep the error message and operation reference intact.
In
`@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts`:
- Around line 631-655: The execute callback argument types in
CommitCreateConfig, CommitUpdateConfig, and CommitDeleteConfig currently require
query.include to always be present; change the execute signature for each (the
execute: (args: { tx: PrismaTransaction; ...; query: { include:
NonNullable<TIncludeArgs['include']> }; serviceContext: ServiceContext; }) =>
...) so that query.include is optional by replacing query: { include:
NonNullable<TIncludeArgs['include']> } with query: { include?:
NonNullable<TIncludeArgs['include']> } in all three interfaces
(CommitCreateConfig, CommitUpdateConfig, CommitDeleteConfig) so callers can pass
{} when no includes are requested.
---
Nitpick comments:
In
`@examples/blog-with-auth/apps/backend/src/modules/blogs/services/blog.data-service.ts`:
- Around line 31-40: Add JSDoc comments for the exported service functions
updateBlog and deleteBlog: document each parameter (where, data/input, query,
context) including their types (DataUpdateInput<'blog', typeof blogInputFields,
TIncludeArgs> and corresponding delete input), explain the generic TIncludeArgs
and what it controls, and describe the returned payload shape
(GetPayload<'blog', TIncludeArgs>) and any possible throws/errors; place these
comments immediately above the exported functions (updateBlog and deleteBlog)
and ensure parameter names, generic type usage, and return type are explicitly
described so IDEs and generated docs show inputs and the payload structure.
In
`@examples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user.data-service.ts`:
- Around line 105-113: Add JSDoc blocks for the exported data-service functions
createUser, updateUser, and deleteUser: document the function purpose, each
parameter (e.g., the destructured data/input, query, and context parameters
typed via DataCreateInput/DataUpdateInput/DataDeleteInput and ModelInclude), and
the returned payload type (GetPayload<'user', TIncludeArgs> or equivalent).
Place the JSDoc immediately above each exported function declaration
(createUser, updateUser, deleteUser), include `@param` entries for input/data,
query, and context, and an `@returns` describing the resolved payload shape and
generic TIncludeArgs behavior.
In
`@examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-item.data-service.ts`:
- Around line 66-76: Add JSDoc blocks for the exported service functions
createTodoItem, updateTodoItem, and deleteTodoItem: describe each function's
purpose, document the generic type parameter TIncludeArgs, and annotate the
parameters (data/input, query, context) including their shapes/types (e.g.,
DataCreateInput/DataUpdateInput/DataDeleteInput for 'todoItem') and the returned
Promise payload (Promise<GetPayload<'todoItem', TIncludeArgs>>), making sure the
docs mention what fields are included in the payload when different include args
are used.
In
`@examples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list-share.data-service.ts`:
- Around line 41-52: Add JSDoc blocks to the exported service functions
createTodoListShare, updateTodoListShare, and deleteTodoListShare: for each
function document what it does, describe the parameters (data/input, query,
context) including their types (DataCreateInput/DataUpdateInput/DataDeleteInput
for 'todoListShare' and TIncludeArgs), and document the returned payload type
(Promise<GetPayload<'todoListShare', TIncludeArgs>>). Place the JSDoc
immediately above each function export (e.g., above the createTodoListShare
declaration and the corresponding updateTodoListShare and deleteTodoListShare
declarations) and include brief descriptions for any important fields on input
and the structure of the returned GetPayload.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 408e9d20-9ba7-4816-9099-5cf8ff361ba7
⛔ Files ignored due to path filters (19)
examples/blog-with-auth/apps/backend/baseplate/generated/src/modules/accounts/services/user.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/modules/articles/services/article.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/modules/blogs/services/blog.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/commit-operations.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-types.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-utils.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/accounts/users/services/user-image.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/accounts/users/services/user-profile.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/accounts/users/services/user.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/todos/services/todo-item.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/todos/services/todo-list-share.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/modules/todos/services/todo-list.data-service.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/commit-operations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-types.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-utils.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!**/generated/**packages/fastify-generators/src/generators/prisma/data-utils/generated/ts-import-providers.tsis excluded by!**/generated/**,!**/generated/**packages/fastify-generators/src/generators/prisma/data-utils/generated/typed-templates.tsis excluded by!**/generated/**,!**/generated/**
📒 Files selected for processing (27)
.changeset/fix-modelquery-no-relations.mdexamples/blog-with-auth/apps/backend/src/modules/accounts/services/user.data-service.tsexamples/blog-with-auth/apps/backend/src/modules/articles/services/article.data-service.tsexamples/blog-with-auth/apps/backend/src/modules/blogs/services/blog.data-service.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/prisma-types.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/prisma-utils.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user-image.data-service.tsexamples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user-profile.data-service.tsexamples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user.data-service.tsexamples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-item.data-service.tsexamples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list-share.data-service.tsexamples/todo-with-better-auth/apps/backend/src/modules/todos/services/todo-list.data-service.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/commit-operations.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/prisma-types.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/prisma-utils.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/types.tspackages/fastify-generators/src/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.tspackages/fastify-generators/src/generators/prisma/data-utils/extractor.jsonpackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tspackages/fastify-generators/src/generators/prisma/prisma-data-create/prisma-data-create.generator.tspackages/fastify-generators/src/generators/prisma/prisma-data-delete/prisma-data-delete.generator.tspackages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.ts
| export async function createUser< | ||
| TQueryArgs extends ModelQuery<'user'> = ModelQuery<'user'>, | ||
| TIncludeArgs extends ModelInclude<'user'> = ModelInclude<'user'>, | ||
| >({ | ||
| data: input, | ||
| query, | ||
| context, | ||
| }: DataCreateInput<'user', typeof userInputFields, TQueryArgs>): Promise< | ||
| GetPayload<'user', TQueryArgs> | ||
| }: DataCreateInput<'user', typeof userInputFields, TIncludeArgs>): Promise< | ||
| GetPayload<'user', TIncludeArgs> | ||
| > { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the user.data-service.ts file
find . -name "user.data-service.ts" -type fRepository: halfdomelabs/baseplate
Length of output: 491
🏁 Script executed:
# Get the file structure to understand the codebase layout
git ls-files examples/blog-with-auth/apps/backend/src/modules/accounts/services/ | head -20Repository: halfdomelabs/baseplate
Length of output: 622
🏁 Script executed:
# Examine the full user.data-service.ts file
cat -n examples/blog-with-auth/apps/backend/src/modules/accounts/services/user.data-service.tsRepository: halfdomelabs/baseplate
Length of output: 3840
🏁 Script executed:
# Search for the Data*Input type definitions
rg "type DataCreateInput|type DataUpdateInput|type DataDeleteInput" examples/blog-with-auth/apps/backend/src/ -A 5Repository: halfdomelabs/baseplate
Length of output: 48
🏁 Script executed:
# Search for Data*Input type definitions more broadly
rg "DataCreateInput|DataUpdateInput|DataDeleteInput" examples/blog-with-auth/apps/backend/src/utils/data-operations/ -A 3Repository: halfdomelabs/baseplate
Length of output: 1485
🏁 Script executed:
# Also check the prisma-types file for ModelInclude definition
rg "ModelInclude|GetPayload" examples/blog-with-auth/apps/backend/src/utils/data-operations/ -A 3Repository: halfdomelabs/baseplate
Length of output: 41007
🏁 Script executed:
# Check if there are any calls to these methods to understand expected usage
rg "createUser|updateUser|deleteUser" examples/blog-with-auth/apps/backend/src --type ts -B 2 -A 2 | head -50Repository: halfdomelabs/baseplate
Length of output: 4859
🏁 Script executed:
# Check how commit-operations handles undefined query
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts | sed -n '1,50p'Repository: halfdomelabs/baseplate
Length of output: 1828
🏁 Script executed:
# Check how validateQuery handles undefined query
rg "validateQuery" examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts -B 2 -A 8Repository: halfdomelabs/baseplate
Length of output: 1512
🏁 Script executed:
# Check the CommitCreateConfig to see how query is used
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '250,350p'Repository: halfdomelabs/baseplate
Length of output: 3481
🏁 Script executed:
# Look at the full types.ts to understand Data*Input interface signatures
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '1,120p'Repository: halfdomelabs/baseplate
Length of output: 4842
🏁 Script executed:
# Get the Data*Input interface definitions
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '360,450p'Repository: halfdomelabs/baseplate
Length of output: 3361
🏁 Script executed:
# Find the exact line numbers for Data*Input interfaces
rg "export interface DataCreateInput|export interface DataUpdateInput|export interface DataDeleteInput" examples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsRepository: halfdomelabs/baseplate
Length of output: 167
🏁 Script executed:
# Get those specific sections
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '700,800p'Repository: halfdomelabs/baseplate
Length of output: 1256
🏁 Script executed:
# Search for the exact line where DataCreateInput interface starts
rg -n "export interface DataCreateInput" examples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsRepository: halfdomelabs/baseplate
Length of output: 103
🏁 Script executed:
# Search for the exact line where DataUpdateInput interface starts
rg -n "export interface DataUpdateInput" examples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsRepository: halfdomelabs/baseplate
Length of output: 103
🏁 Script executed:
# Search for the exact line where DataDeleteInput interface starts
rg -n "export interface DataDeleteInput" examples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsRepository: halfdomelabs/baseplate
Length of output: 103
🏁 Script executed:
# Get DataCreateInput interface (lines 583-595)
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '583,595p'Repository: halfdomelabs/baseplate
Length of output: 500
🏁 Script executed:
# Get DataUpdateInput interface (lines 596-609)
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '596,609p'Repository: halfdomelabs/baseplate
Length of output: 555
🏁 Script executed:
# Get DataDeleteInput interface (lines 610-620)
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '610,625p'Repository: halfdomelabs/baseplate
Length of output: 541
Default TIncludeArgs generic parameter to undefined for optional query semantics.
The shared DataCreateInput / DataUpdateInput / DataDeleteInput types make query optional (line 589, 603, 615), but all three service methods default TIncludeArgs to ModelInclude<'user'>. When callers omit query, the return type is still inferred as GetPayload<'user', ModelInclude<'user'>> rather than the base GetPayload<'user', undefined>. This creates a type mismatch: an optional parameter should not default the generic to a non-undefined value.
Update the type constraint to allow undefined and default to it: change TIncludeArgs extends ModelInclude<TModelName> = ModelInclude<TModelName> to TIncludeArgs extends ModelInclude<TModelName> | undefined = undefined in all three Data*Input interfaces and their corresponding methods. This ensures that omitting query produces the correct base payload type.
Also applies to: updateUser (70-78), deleteUser (104-112)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@examples/blog-with-auth/apps/backend/src/modules/accounts/services/user.data-service.ts`
around lines 37 - 45, The generic default for TIncludeArgs causes omitted query
parameters to still infer a ModelInclude type; update the type constraints so
TIncludeArgs can be undefined and defaults to undefined: change the generic
constraint in the shared input types (DataCreateInput, DataUpdateInput,
DataDeleteInput) from "TIncludeArgs extends ModelInclude<TModelName> =
ModelInclude<TModelName>" to "TIncludeArgs extends ModelInclude<TModelName> |
undefined = undefined", and update the service method signatures (createUser,
updateUser, deleteUser) to use the same TIncludeArgs extends
ModelInclude<'user'> | undefined = undefined so that when query is omitted the
return type becomes GetPayload<'user', undefined>.
| export async function createArticle< | ||
| TQueryArgs extends ModelQuery<'article'> = ModelQuery<'article'>, | ||
| TIncludeArgs extends ModelInclude<'article'> = ModelInclude<'article'>, | ||
| >({ | ||
| data: input, | ||
| query, | ||
| context, | ||
| }: DataCreateInput<'article', typeof articleInputFields, TQueryArgs>): Promise< | ||
| GetPayload<'article', TQueryArgs> | ||
| > { | ||
| }: DataCreateInput< | ||
| 'article', | ||
| typeof articleInputFields, | ||
| TIncludeArgs | ||
| >): Promise<GetPayload<'article', TIncludeArgs>> { |
There was a problem hiding this comment.
Document the exported article service methods.
createArticle() and updateArticle() still lack the required JSDoc blocks.
As per coding guidelines, "Add JSDocs to all exported functions, interfaces, and classes with documentation of parameters, return values, and all fields".
Also applies to: 68-79
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@examples/blog-with-auth/apps/backend/src/modules/articles/services/article.data-service.ts`
around lines 34 - 44, Add JSDoc blocks for the exported service functions
createArticle and updateArticle: for each function document the purpose,
describe each parameter (data/input, query, context and the generic
TIncludeArgs), list the return type (Promise<GetPayload<'article',
TIncludeArgs>>), and note any thrown errors or side effects; place the JSDoc
immediately above the function declarations (createArticle and updateArticle)
and include `@param` and `@returns` tags and brief descriptions of the data shape
based on articleInputFields.
| async function refetchResult< | ||
| TModelName extends ModelPropName, | ||
| TQueryArgs extends ModelQuery<TModelName>, | ||
| TIncludeArgs extends ModelInclude<TModelName>, | ||
| >( | ||
| model: TModelName, | ||
| result: GetPayload<TModelName>, | ||
| query: TQueryArgs, | ||
| query: TIncludeArgs, | ||
| refetchWithQuery?: ( | ||
| result: GetPayload<TModelName>, | ||
| query: TQueryArgs, | ||
| query: TIncludeArgs, | ||
| ) => Promise<GetPayload<TModelName>>, | ||
| ): Promise<GetPayload<TModelName, TQueryArgs>> { | ||
| ): Promise<GetPayload<TModelName, TIncludeArgs>> { | ||
| if (refetchWithQuery) { | ||
| return refetchWithQuery(result, query) as unknown as Promise< | ||
| GetPayload<TModelName, TQueryArgs> | ||
| GetPayload<TModelName, TIncludeArgs> | ||
| >; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts | head -100Repository: halfdomelabs/baseplate
Length of output: 3978
🏁 Script executed:
wc -l examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.tsRepository: halfdomelabs/baseplate
Length of output: 153
🏁 Script executed:
# Find the types.ts file mentioned in the diff
find examples/blog-with-auth -name "types.ts" -type f | grep -E "(data-operations|utils)"Repository: halfdomelabs/baseplate
Length of output: 229
🏁 Script executed:
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | grep -A 20 -B 5 "refetchWithQuery"Repository: halfdomelabs/baseplate
Length of output: 2181
🏁 Script executed:
# Search for usages of refetchResult and refetchWithQuery in the codebase
rg "refetchWithQuery|refetchResult" examples/blog-with-auth/apps/backend/src --type ts --type tsx -B 2 -A 2Repository: halfdomelabs/baseplate
Length of output: 93
🏁 Script executed:
rg "refetchWithQuery|refetchResult" examples/blog-with-auth/apps/backend/src --type ts -B 2 -A 2Repository: halfdomelabs/baseplate
Length of output: 6311
🏁 Script executed:
# Also check CommitDeleteConfig for refetchWithQuery
cat -n examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts | sed -n '690,730p'Repository: halfdomelabs/baseplate
Length of output: 1598
Tighten the refetchWithQuery callback contract to enforce included relations.
The callback parameter on line 64–67 only guarantees Promise<GetPayload<TModelName>>, but the function returns Promise<GetPayload<TModelName, TIncludeArgs>>. The cast on line 70–72 masks this mismatch, allowing an implementation to skip the relations in query.include and still type-check.
Update the return type of refetchWithQuery in both CommitCreateConfig and CommitUpdateConfig (in types.ts) from Promise<GetPayload<TModelName>> to Promise<GetPayload<TModelName, TIncludeArgs>>, then remove the cast in refetchResult.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts`
around lines 57 - 72, The refetchResult function currently casts the callback
return to include relations because refetchWithQuery is typed as
Promise<GetPayload<TModelName>); update the refetchWithQuery signature in
CommitCreateConfig and CommitUpdateConfig (types.ts) to return
Promise<GetPayload<TModelName, TIncludeArgs>> so the callback is required to
include the relations from query, then remove the forced cast in refetchResult
and return the callback result directly (i.e., have refetchResult return the
Promise<GetPayload<TModelName, TIncludeArgs>> returned by refetchWithQuery).
| export async function deleteUserImage< | ||
| TQueryArgs extends ModelQuery<'userImage'> = ModelQuery<'userImage'>, | ||
| TIncludeArgs extends ModelInclude<'userImage'> = ModelInclude<'userImage'>, | ||
| >({ | ||
| where, | ||
| query, | ||
| context, | ||
| }: DataDeleteInput<'userImage', TQueryArgs>): Promise< | ||
| GetPayload<'userImage', TQueryArgs> | ||
| }: DataDeleteInput<'userImage', TIncludeArgs>): Promise< | ||
| GetPayload<'userImage', TIncludeArgs> |
There was a problem hiding this comment.
Add the missing JSDoc for deleteUserImage().
This exported function changed here but still has no function/params/return docs.
As per coding guidelines, "Add JSDoc comments to all exported functions, interfaces, and classes documenting the function/type, parameters, return value, and all fields".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@examples/todo-with-better-auth/apps/backend/src/modules/accounts/users/services/user-image.data-service.ts`
around lines 24 - 31, Add a JSDoc comment above the exported async function
deleteUserImage that documents the function purpose, each parameter (where,
query, context from the DataDeleteInput<'userImage', TIncludeArgs> object), the
generic TIncludeArgs type constraint, and the return value
(Promise<GetPayload<'userImage', TIncludeArgs>>); include brief descriptions for
the DataDeleteInput properties and mention that it deletes a userImage and
returns the deleted userImage payload (including any included relations), and
annotate thrown errors or exceptions if applicable.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts (1)
143-146: Consider a cleaner type expression for the empty query case.When
needsRefetchis true orconfig.queryis undefined, casting{}to{ include: NonNullable<TIncludeArgs['include']> }is technically misleading since the object has noincludeproperty. This works at runtime but reduces type accuracy.A clearer approach could be a type that explicitly allows no include:
type QueryWithOptionalInclude<T> = {} | { include: T };This is a minor type hygiene issue and doesn't affect runtime behavior.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts` around lines 143 - 146, The current createQuery assignment casts {} to { include: NonNullable<TIncludeArgs['include']> } which is misleading; define a clearer union type (e.g. type QueryWithOptionalInclude<T> = {} | { include: T }) and use it for createQuery so the branch when needsRefetch || !config.query yields the empty-object variant while the other branch uses config.query as QueryWithOptionalInclude<NonNullable<TIncludeArgs['include']>>; update the createQuery declaration to use QueryWithOptionalInclude to reflect that include may be absent instead of forcing a cast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts`:
- Around line 647-652: The execute method signatures currently return
Promise<GetPayload<TModelName>> which does not respect the provided query
include shape; change the return type to Promise<GetPayload<TModelName,
TIncludeArgs>> for the execute signatures (the ones using parameters tx, data,
query, serviceContext) so implementations must return results matching the
include tree, or alternatively update the contract to require implementations to
call refetchWithQuery and document/enforce that; update the other two matching
signatures (the ones at the other occurrences) the same way to keep types
consistent.
In
`@examples/todo-with-better-auth/apps/backend/src/utils/data-operations/types.ts`:
- Around line 647-652: The execute callback return type must reflect the include
shape: update the signature of execute in CommitCreateConfig,
CommitUpdateConfig, and CommitDeleteConfig so it returns
Promise<GetPayload<TModelName, TIncludeArgs>> (or otherwise bind the return
generic to TIncludeArgs) instead of Promise<GetPayload<TModelName>>; ensure the
execute method declaration that currently takes query: { include:
NonNullable<TIncludeArgs['include']> } is paired with the matching
GetPayload<TModelName, TIncludeArgs> return type so callers cannot assume
included relations are present unless the executor provides them.
In
`@packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts`:
- Around line 650-655: The execute callback's return type must be bound to the
include shape so implementations cannot ignore requested includes; update the
signature(s) for execute in types.ts (the one shown and the other occurrences
referenced) so the Promise return uses GetPayload parameterized by the query's
include (e.g. Promise<GetPayload<TModelName, NonNullable<typeof
query.include>>>), or alternatively make query optional and remove the include
type from the parameter to avoid a false-safe cast—apply the same change to the
other execute signatures noted (the blocks around the other occurrences).
---
Nitpick comments:
In
`@examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.ts`:
- Around line 143-146: The current createQuery assignment casts {} to { include:
NonNullable<TIncludeArgs['include']> } which is misleading; define a clearer
union type (e.g. type QueryWithOptionalInclude<T> = {} | { include: T }) and use
it for createQuery so the branch when needsRefetch || !config.query yields the
empty-object variant while the other branch uses config.query as
QueryWithOptionalInclude<NonNullable<TIncludeArgs['include']>>; update the
createQuery declaration to use QueryWithOptionalInclude to reflect that include
may be absent instead of forcing a cast.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 906a3d40-d216-4d1c-a110-7202dcfd2edf
⛔ Files ignored due to path filters (6)
examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/commit-operations.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-utils.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/commit-operations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/prisma-utils.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-better-auth/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!**/generated/**
📒 Files selected for processing (9)
examples/blog-with-auth/apps/backend/src/utils/data-operations/commit-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/prisma-utils.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/commit-operations.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/prisma-utils.tsexamples/todo-with-better-auth/apps/backend/src/utils/data-operations/types.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Documentation