-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Use Zod schema defined in mutations instead of restrictObjectNulls to allow for cleaner mutations and validation #693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Use Zod schema defined in mutations instead of restrictObjectNulls to allow for cleaner mutations and validation #693
Conversation
…lls to allow for cleaner mutations and validation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: fb435cc The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughIntegrates Pothos ValidationPlugin and replaces runtime restrictObjectNulls with Zod-based schemas attached to create/update operation functions; updates field definitions, Pothos plugin types, generator templates, writers, and example projects to propagate and use $dataSchema and skipValidation flags. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant GraphQL as Pothos InputType
participant PothosVal as Validation Plugin
participant Operation as Create/Update Operation
participant Service as Application Service
Client->>GraphQL: submit mutation with data
GraphQL->>PothosVal: .validate(operation.$dataSchema)
PothosVal->>PothosVal: Zod parse/check
alt validation succeeds
PothosVal->>Operation: pass validatedData
Operation->>Operation: apply transforms / prepareComputedFields (uses validatedData)
Operation->>Service: call service with skipValidation flag (if upstream validated)
Service->>Client: return result
else validation fails
PothosVal->>Client: return validation errors
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes
Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ 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 |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (2)
192-245:FieldDefinitiondocs/example are out of sync with the interface (schema+ validated input)Two mismatches here:
- The interface exposes a
schema: TInputSchema, but the example still useszodSchema.processInputnow receivesvalue: z.output<TInputSchema>, i.e. an already‑validated value, yet the example re‑parses with a freshz.string().min(1).parse(value)and ignoresschema.To keep the docs aligned with the actual contract, consider something like:
- * - Validate the input value using a Zod schema + * - Define the Zod schema used to validate this field's input ... - * const nameField: FieldDefinition<z.ZodString, string, string> = { - * zodSchema: z.string().min(1), - * processInput: (value, ctx) => { - * const validated = z.string().min(1).parse(value); - * - * return { - * data: { - * create: validated, - * update: validated, - * }, - * }; - * }, - * }; + * const nameField: FieldDefinition<z.ZodString, string, string> = { + * schema: z.string().min(1), + * processInput: (value) => ({ + * data: { + * create: value, + * update: value, + * }, + * }), + * };This makes it clear that the pipeline handles validation using
schema, andprocessInputworks with the already‑validated value.
295-318: UpdateInferInputdocs to describe Zod output types instead of “schema types”
InferInputis now defined as:export type InferInput<TFields extends Record<string, AnyFieldDefinition>> = z.output<InferInputSchema<TFields>>;So each property is the Zod output type (e.g.
string), not “the field's Zod schema type” as stated in the bullet:* - Each value type is the field's Zod schema typeIt would be clearer to rephrase to something like:
* - Each value type is the Zod output type for that field's schemaThe example
{ name: string; email?: string | undefined }then matches both the implementation and the description.examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (1)
193-245: FieldDefinition JSDoc example is out of sync with the newschemapropertyThe interface now exposes
schema: TInputSchema, but the example in the JSDoc still shows azodSchemaproperty and manually reparsesvalue. To avoid confusion for consumers, I’d align the example with the current API and the new type ofvalue:- * const nameField: FieldDefinition<z.ZodString, string, string> = { - * zodSchema: z.string().min(1), - * processInput: (value, ctx) => { - * const validated = z.string().min(1).parse(value); - * - * return { - * data: { - * create: validated, - * update: validated, - * }, - * }; - * }, - * }; + * const nameField: FieldDefinition<z.ZodString, string, string> = { + * schema: z.string().min(1), + * processInput: (value, ctx) => { + * // `value` is already typed as the schema's output + * return { + * data: { + * create: value, + * update: value, + * }, + * }; + * }, + * };As per coding guidelines
examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts (2)
295-317: Correct documentation forInferInputtype to accurately describe runtime types produced byz.outputThe review comment is accurate. Line 300's bullet describes "the field's Zod schema type," but
InferInputusesz.output<InferInputSchema<TFields>>which produces runtime output types, not schema types. The example comment at line 313 already correctly shows runtime types ({ name: string; email?: string | undefined }), but the descriptive bullet contradicts this.Update line 300 from:
- "Each value type is the field's Zod schema type"
To:
- "Each value type is the field's runtime type inferred from its Zod schema"
This aligns the documentation with the actual behavior of
z.output.
192-245: UpdateFieldDefinitionexample to match theschemaproperty and current patternsThe example at lines 206-217 uses
zodSchemabut the interface definesschema(line 230). Additionally, the example unnecessarily re-parses the value, contradicting the interface signature wherevalue: z.output<TInputSchema>is already validated output.Update the example to:
- Replace
zodSchemawithschema- Simplify
processInputto work with the pre-validated value- Optionally show how
ctx.skipValidationcan be checked if needed-const nameField: FieldDefinition<z.ZodString, string, string> = { - zodSchema: z.string().min(1), - processInput: (value, ctx) => { - const validated = z.string().min(1).parse(value); +const nameField: FieldDefinition<z.ZodString, string, string> = { + schema: z.string().min(1), + processInput: (value, ctx) => { + const validated = value; return { data: { create: validated, update: validated, }, };
🧹 Nitpick comments (10)
packages/fastify-generators/src/writers/pothos/resolvers.ts (2)
18-23: Export theNestedArgContextinterface.As per coding guidelines, interfaces and types should be exported. This also improves reusability and allows other modules to reference this type if needed.
Apply this diff:
-interface NestedArgContext { +export interface NestedArgContext { /** * If the field is validated, we can skip the restrictObjectNulls call. */ isValidatedField?: boolean; }Based on coding guidelines.
100-100: Prefer explicit boolean conversion for clarity.The current expression could result in
isValidatedFieldbeingundefinedwhen botharg.zodSchemaFragmentis falsy andcontext.isValidatedFieldis undefined. While this works correctly in the boolean context on line 110, explicit boolean conversion improves clarity and aligns with the coding guideline to prefer??over||.Consider one of these alternatives:
- const isValidatedField = !!arg.zodSchemaFragment || context.isValidatedField; + const isValidatedField = !!arg.zodSchemaFragment || (context.isValidatedField ?? false);Or:
- const isValidatedField = !!arg.zodSchemaFragment || context.isValidatedField; + const isValidatedField = !!arg.zodSchemaFragment || !!context.isValidatedField;Based on coding guidelines.
plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts (1)
3-10: Move external library import to the top of the import block.The
zodimport should be placed before local imports, per the coding guidelines.As per coding guidelines.
Apply this diff to fix the import ordering:
+import z from 'zod'; + import type { FileCategory } from '$typesFileCategory'; import type { FieldDefinition } from '%dataUtilsImports'; import type { Prisma } from '%prismaGeneratedImports'; import { STORAGE_ADAPTERS } from '$configAdapters'; import { BadRequestError } from '%errorHandlerServiceImports'; import { prisma } from '%prismaImports'; -import z from 'zod';examples/blog-with-auth/apps/backend/src/modules/accounts/schema/user.mutations.ts (2)
22-38: Consider adding JSDoc and explicit return type per coding guidelines.Per the coding guidelines, exported functions should include JSDoc documentation and explicit return types. While Pothos infers types for mutation fields, consider adding JSDoc above the mutation definition to document its purpose, parameters, and return value.
Based on coding guidelines.
50-68: Consider adding JSDoc and explicit return type per coding guidelines.Per the coding guidelines, exported functions should include JSDoc documentation and explicit return types. Consider adding JSDoc above the mutation definition to document its purpose, parameters, and return value.
Based on coding guidelines.
examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.ts (2)
63-79: Consider adding JSDoc and explicit return type per coding guidelines.Per the coding guidelines for this path (
examples/todo-with-auth0/apps/backend/src/**/*.{ts,tsx}), all exported functions should include JSDoc documenting purpose, parameters, returns, and fields. Consider adding documentation above the mutation definition.Based on coding guidelines.
94-112: Consider adding JSDoc and explicit return type per coding guidelines.Per the coding guidelines for this path, exported functions should include JSDoc documenting purpose, parameters, returns, and fields. Consider adding documentation above the mutation definition.
Based on coding guidelines.
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (1)
86-103: Alignschema’s runtime value with its conditional Zod typeThe new conditional type for the first
FieldDefinitiongeneric and theschemaproperty is good in principle, but right now both branches share the same runtime instance (fileInputSchema), and only the type changes viaas. If anything downstream relies on Zod’s runtime optional/nullable behavior (e.g.,schema.parse(null)succeeding for optional fields), this will not work as expected.Consider constructing an actual optional/nullable schema when
config.optionalis set, and keep the conditional type for TS:return { - schema: fileInputSchema as TOptional extends true - ? z.ZodOptional<z.ZodNullable<typeof fileInputSchema>> - : typeof fileInputSchema, + schema: (config.optional + ? fileInputSchema.nullable().optional() + : fileInputSchema) as TOptional extends true + ? z.ZodOptional<z.ZodNullable<typeof fileInputSchema>> + : typeof fileInputSchema, processInput: async ( value: z.infer<typeof fileInputSchema> | null | undefined, processCtx, ) => {This keeps the generic typing you introduced but also makes the runtime schema genuinely accept
null/undefinedfor the optional case.packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (1)
256-262: Consider exportingIdentityto align with the “export all types” guidelinePer the coding guidelines, interfaces and types in
*.tsfiles should be exported.Identity<T>is currently internal; if it’s intended for consumers (and it is already used in public utility types), it would be clearer to mark it as exported:-type Identity<T> = T extends object +export type Identity<T> = T extends objectIf you prefer to keep it internal, we might want to revisit the guideline or rename it to signal non‑exported/private usage.
packages/fastify-generators/src/writers/pothos/input-types.ts (1)
56-75: Consider adding an explicit return type to match TS style guidelinesSince this exported helper is widely used, it would be nice to explicitly annotate its return type as
PothosTypeDefinitionWithVariableNamerather than relying on inference:-export function writePothosInputDefinitionFromDtoFields( +export function writePothosInputDefinitionFromDtoFields( name: string, fields: ServiceOutputDtoField[], options: PothosWriterOptions, shouldExport?: boolean, suffix?: TsCodeFragment, -): PothosTypeDefinitionWithVariableName { +): PothosTypeDefinitionWithVariableName {As per coding guidelines
| type CreateOperationFunction< | ||
| TModelName extends ModelPropName, | ||
| TFields extends Record<string, AnyFieldDefinition>, | ||
| > = (<TQueryArgs extends ModelQuery<TModelName>>( | ||
| input: CreateOperationInput<TModelName, TFields, TQueryArgs>, | ||
| ) => Promise<GetPayload<TModelName, TQueryArgs>>) & { | ||
| $dataSchema: InferInputSchema<TFields>; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Export CreateOperationFunction and type createOperation so $dataSchema is type-checked
Two points here:
-
CreateOperationFunctionis currently file-local. Given the intent to expose this as part of the public API and the guideline to export interfaces/types, it should be exported. -
createOperationis inferred as a bare generic function, socreateOperation.$dataSchema = …won’t type-check (property$dataSchemadoesn’t exist on the inferred function type). Either annotatecreateOperationwithCreateOperationFunctionor cast before attaching the property.
A minimal fix:
-export interface CreateOperationInput<
+export interface CreateOperationInput<
@@
-}
-
-type CreateOperationFunction<
+}
+
+export type CreateOperationFunction<
@@
->: (<TQueryArgs extends ModelQuery<TModelName>>(
+> = (<TQueryArgs extends ModelQuery<TModelName>>(
input: CreateOperationInput<TModelName, TFields, TQueryArgs>,
) => Promise<GetPayload<TModelName, TQueryArgs>>) & {
$dataSchema: InferInputSchema<TFields>;
};
@@
export function defineCreateOperation<
@@
>(
config: CreateOperationConfig<TModelName, TFields, TPrepareResult>,
-): CreateOperationFunction<TModelName, TFields> {
- const createOperation = async <TQueryArgs extends ModelQuery<TModelName>>({
+): CreateOperationFunction<TModelName, TFields> {
+ const createOperation: CreateOperationFunction<TModelName, TFields> =
+ async <TQueryArgs extends ModelQuery<TModelName>>({
@@
- }: CreateOperationInput<TModelName, TFields, TQueryArgs>): Promise<
- GetPayload<TModelName, TQueryArgs>
- > => {
+ }: CreateOperationInput<TModelName, TFields, TQueryArgs>): Promise<
+ GetPayload<TModelName, TQueryArgs>
+ > => {
@@
- };
+ };
createOperation.$dataSchema = generateCreateSchema(config.fields);
return createOperation;
}This keeps runtime behavior while making the $dataSchema contract explicit.
Also applies to: 398-415, 509-510
I'll verify the review comment by examining the file content at the specified locations.
🏁 Script executed:
#!/bin/bash
# Examine the primary location (lines 345-352)
echo "=== PRIMARY LOCATION (lines 345-352) ==="
sed -n '340,360p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Examine secondary locations (lines 398-415 and 509-510)
echo -e "\n=== SECONDARY LOCATION (lines 398-415) ==="
sed -n '395,420p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
echo -e "\n=== SECONDARY LOCATION (lines 509-510) ==="
sed -n '505,515p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check if CreateOperationFunction is exported anywhere in the file
echo -e "\n=== SEARCHING FOR CreateOperationFunction EXPORT ==="
rg -n 'export.*CreateOperationFunction' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tsLength of output: 2008
The output confirms the review comment. Let me verify the similar patterns in the other operation types:
🏁 Script executed:
#!/bin/bash
# Check for UpdateOperationFunction
echo "=== SEARCHING FOR UpdateOperationFunction ==="
rg -n -B2 'type UpdateOperationFunction' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check for DeleteOperationFunction
echo -e "\n=== SEARCHING FOR DeleteOperationFunction ==="
rg -n -B2 'type DeleteOperationFunction' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check for any exported operation function types
echo -e "\n=== SEARCHING FOR ALL OPERATION FUNCTION TYPES ==="
rg -n 'type.*OperationFunction' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check defineUpdateOperation and defineDeleteOperation similar patterns
echo -e "\n=== CHECKING defineUpdateOperation ==="
rg -n -A20 'export function defineUpdateOperation' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts | head -30
echo -e "\n=== CHECKING defineDeleteOperation ==="
rg -n -A20 'export function defineDeleteOperation' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts | head -30Length of output: 2119
🏁 Script executed:
#!/bin/bash
# Get full UpdateOperationFunction definition
echo "=== UpdateOperationFunction DEFINITION ==="
sed -n '611,630p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Get full context around updateOperation assignment
echo -e "\n=== updateOperation ASSIGNMENT IN defineUpdateOperation ==="
sed -n '675,685p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check where updateOperation.$dataSchema is assigned
echo -e "\n=== updateOperation.\$dataSchema ASSIGNMENT ==="
rg -n 'updateOperation\.\$dataSchema' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Check line 509-510 more precisely to see context
echo -e "\n=== CONTEXT FOR 509-510 ==="
sed -n '505,512p' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
# Get line numbers for updateOperation.$dataSchema assignment
echo -e "\n=== ALL DATASCHEMA ASSIGNMENTS ==="
rg -n '\$dataSchema' examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tsLength of output: 1931
Export CreateOperationFunction and UpdateOperationFunction, and add explicit type annotations to the operation variables
Two related issues affecting the create and update operations:
-
CreateOperationFunction(line 345) andUpdateOperationFunction(line 611) are not exported. Given the intent to expose these as part of the public API and the guideline to export types, both should be exported. -
createOperation(lines ~412) andupdateOperation(line 676) are inferred as bare async functions, so assigning$dataSchemawon't type-check (property doesn't exist on the inferred function type). Annotate both with their respective types before attaching the property.
Minimal fix pattern:
- Export both operation function types
- Add type annotation:
const createOperation: CreateOperationFunction<TModelName, TFields> = async ... - Add type annotation:
const updateOperation: UpdateOperationFunction<TModelName, TFields> = async ...
This makes the $dataSchema contract explicit and enables proper type-checking.
🤖 Prompt for AI Agents
In
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
around lines 345-352 and 611-676, the type aliases CreateOperationFunction and
UpdateOperationFunction must be exported and the createOperation and
updateOperation variables must be explicitly typed so attaching $dataSchema
typechecks: export both CreateOperationFunction and UpdateOperationFunction,
then annotate the functions like const createOperation:
CreateOperationFunction<TModelName, TFields> = async (...) => { ... } and const
updateOperation: UpdateOperationFunction<TModelName, TFields> = async (...) => {
... } before assigning createOperation.$dataSchema and
updateOperation.$dataSchema.
examples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.ts
Show resolved
Hide resolved
| /** | ||
| * Infers the input schema from a record of field definitions. | ||
| * | ||
| * Creates an object type where: | ||
| * - Each key corresponds to a field name | ||
| * - Each value type is the field's Zod schema type | ||
| * | ||
| * @template TFields - Record of field definitions | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const fields = { | ||
| * name: scalarField(z.string()), | ||
| * email: scalarField(z.string().email().optional()), | ||
| * }; | ||
| * | ||
| * type InputSchema = InferInputSchema<typeof fields>; | ||
| * // { name: z.ZodString; email?: z.ZodString | undefined } | ||
| * ``` | ||
| */ | ||
| export type InferInputSchema< | ||
| TFields extends Record<string, AnyFieldDefinition>, | ||
| > = z.ZodObject<{ | ||
| [K in keyof TFields]: TFields[K] extends FieldDefinition< | ||
| infer TInputSchema, | ||
| any, | ||
| any | ||
| > | ||
| ? TInputSchema | ||
| : never; | ||
| }>; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify JSDoc for InferInput to reflect that it returns schema output types
InferInputSchema correctly documents that each property is the field’s Zod schema type. However, InferInput now returns z.output<InferInputSchema<TFields>>, i.e., the output TypeScript type of each schema, not the schema objects themselves. I’d tweak the description accordingly:
- * - Each value type is the field's Zod schema type
+ * - Each value type is the output type of the field's Zod schemaThis keeps the prose consistent with the example showing { name: string; email?: string | undefined }.
Also applies to: 295-317
🤖 Prompt for AI Agents
In examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
around lines 263 to 294 (and similarly for 295 to 317), the JSDoc for
InferInputSchema incorrectly states it returns the field's Zod schema types; in
reality the exported InferInput type uses z.output<InferInputSchema<TFields>>
and therefore represents the schemas' output TypeScript types. Update the JSDoc
to clarify that the resulting type represents the output (parsed) TypeScript
values produced by each Zod schema (e.g., string, optional string), and adjust
the example description to say the inferred type is { name: string; email?:
string | undefined } rather than Zod schema objects.
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
Outdated
Show resolved
Hide resolved
examples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts
Show resolved
Hide resolved
| /** | ||
| * Infers the input schema from a record of field definitions. | ||
| * | ||
| * Creates an object type where: | ||
| * - Each key corresponds to a field name | ||
| * - Each value type is the field's Zod schema type | ||
| * | ||
| * @template TFields - Record of field definitions | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const fields = { | ||
| * name: scalarField(z.string()), | ||
| * email: scalarField(z.string().email().optional()), | ||
| * }; | ||
| * | ||
| * type InputSchema = InferInputSchema<typeof fields>; | ||
| * // { name: z.ZodString; email?: z.ZodString | undefined } | ||
| * ``` | ||
| */ | ||
| export type InferInputSchema< | ||
| TFields extends Record<string, AnyFieldDefinition>, | ||
| > = z.ZodObject<{ | ||
| [K in keyof TFields]: TFields[K] extends FieldDefinition< | ||
| infer TInputSchema, | ||
| any, | ||
| any | ||
| > | ||
| ? TInputSchema | ||
| : never; | ||
| }>; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
InferInputSchema doc comment doesn’t match the actual type
InferInputSchema is defined as a z.ZodObject<…>, but the example comment suggests it’s a plain object type of field schemas. You might want to tweak the wording and example:
- Say “returns a
z.ZodObjectwhose shape maps field names to their input schemas”. - Example type should be
z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }>(or similar), not a plain object type.
Only the docs are off; the implementation itself looks correct and mirrors the blog/fastify templates.
Based on learnings
🏁 Script executed:
#!/bin/bash
# Inspect the InferInputSchema type definition and surrounding context
cat examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts | sed -n '250,300p'Length of output: 1256
🏁 Script executed:
#!/bin/bash
# Check imports and FieldDefinition type to understand the structure
head -100 examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts | tail -50Length of output: 1841
🏁 Script executed:
#!/bin/bash
# Search for InferInputSchema usage in the codebase to understand how it's consumed
rg -n 'InferInputSchema' examples/todo-with-auth0/apps/backend/src/ -A 2 -B 2Length of output: 5018
Update JSDoc example to reflect that InferInputSchema returns a z.ZodObject, not a plain object type
The JSDoc comment at lines 263–294 is misleading. The type definition correctly returns z.ZodObject<{ ... }>, but the example shows a plain object type. Update the comment to:
- Clarify that it returns a
z.ZodObjectwhose shape maps field names to their input schemas - Change the example type annotation to reflect the actual type, e.g.,
z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }>(or similar Zod-wrapped representation)
🤖 Prompt for AI Agents
In examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts
around lines 263 to 294, the JSDoc example incorrectly shows a plain object type
but the exported InferInputSchema returns a z.ZodObject; update the comment to
state clearly that the type returns a z.ZodObject whose shape maps each field
name to its Zod input schema, and replace the example type annotation with a
Zod-wrapped representation (for example show z.ZodObject<{ name: z.ZodString;
email: z.ZodOptional<z.ZodString> }> or similar) so the docs match the actual
return type.
| z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>, | ||
| undefined, | ||
| undefined | { delete: true } | ||
| > { | ||
| return { | ||
| schema: generateCreateSchema(config.fields).nullish(), | ||
| processInput: async (value, processCtx) => { | ||
| // Handle null - delete the relation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix schema generic to match .nullish() output
.nullish() returns ZodNullable<ZodOptional<T>>, so the function currently promises callers a ZodOptional<ZodNullable<T>> but actually hands them a different wrapper. That leaks an incorrect method surface to generated code and can break downstream schema operations. Please swap the generic to reflect the real shape. (nuxt-sidebase-parse.sidebase.io)
-): FieldDefinition<
- z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>,
+): FieldDefinition<
+ z.ZodNullable<z.ZodOptional<InferInputSchema<TFields>>>,🤖 Prompt for AI Agents
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts
around lines 267 to 274: the function return type currently declares
ZodOptional<ZodNullable<InferInputSchema<TFields>>> but .nullish() actually
produces ZodNullable<ZodOptional<InferInputSchema<TFields>>>; update the generic
to ZodNullable<ZodOptional<InferInputSchema<TFields>>> so the declared schema
type matches the runtime .nullish() wrapper, leaving processInput and other
logic unchanged.
| /** | ||
| * Infers the input schema from a record of field definitions. | ||
| * | ||
| * Creates an object type where: | ||
| * - Each key corresponds to a field name | ||
| * - Each value type is the field's Zod schema type | ||
| * | ||
| * @template TFields - Record of field definitions | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const fields = { | ||
| * name: scalarField(z.string()), | ||
| * email: scalarField(z.string().email().optional()), | ||
| * }; | ||
| * | ||
| * type InputSchema = InferInputSchema<typeof fields>; | ||
| * // { name: z.ZodString; email?: z.ZodString | undefined } | ||
| * ``` | ||
| */ | ||
| export type InferInputSchema< | ||
| TFields extends Record<string, AnyFieldDefinition>, | ||
| > = z.ZodObject<{ | ||
| [K in keyof TFields]: TFields[K] extends FieldDefinition< | ||
| infer TInputSchema, | ||
| any, | ||
| any | ||
| > | ||
| ? TInputSchema | ||
| : never; | ||
| }>; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InferInputSchema JSDoc example doesn’t match the actual type it produces
InferInputSchema returns a z.ZodObject<...>, where each value is the field’s Zod schema type. The example comment:
// { name: z.ZodString; email?: z.ZodString | undefined }suggests a plain object type with an optional email property, which is not what the alias actually returns, nor how Zod encodes optionality (it would be z.ZodOptional<z.ZodString> in the shape).
To avoid confusion, consider updating the example to something closer to:
// z.ZodObject<{
// name: z.ZodString;
// email: z.ZodOptional<z.ZodString>;
// }>or simply drop the inline example type and keep the textual description.
🤖 Prompt for AI Agents
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts
lines 263-294: the JSDoc example for InferInputSchema is misleading because the
type is a z.ZodObject whose values are Zod schema types (e.g., z.ZodString or
z.ZodOptional<z.ZodString>), not a plain TS object with optional properties;
update the example to reflect the actual returned type (for example show
z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }>) or remove
the inline example entirely and keep the textual description so the docs
accurately match the implemented type.
...plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (1)
25-43: ExportFileFieldConfigto comply with TypeScript export guidelineCurrent
FileFieldConfigis internal. Given the repo rule that interfaces/types should be exported, consider:-interface FileFieldConfig< +export interface FileFieldConfig< TFileCategory extends FileCategory, TOptional extends boolean = false, > {This keeps the existing JSDoc valid while aligning with the shared TS guidelines.
As per coding guidelines
♻️ Duplicate comments (8)
examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts (1)
264-294: Update JSDoc example to reflect thatInferInputSchemareturns az.ZodObject, not a plain object typeThe example comment at line 281 shows
// { name: z.ZodString; email?: z.ZodString | undefined }, but the actual type definition returnsz.ZodObject<{ [K in keyof TFields]: ... }>. Update the example to show the correct Zod-wrapped representation, e.g.,z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }>.examples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts (1)
32-92: Update docstring to clarify validation happens at GraphQL layer, not withinscalarFieldThe docstring at line 35 states "validates input using a Zod schema," but
scalarFielditself doesn't callschema.parse(). Validation occurs at the GraphQL input type level via.validate(operation.$dataSchema). For standalone use outside GraphQL, callers must validate usinggenerateCreateSchema(fields).parse(input)before passing data to these helpers.Update the docstring to clarify when and where validation occurs.
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (1)
1-1: Zod import is now NodeNext/ESM‑safeUsing
import { z } from 'zod';is correct here and fixes the earlier default‑import issue under NodeNext/ESM.packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (1)
190-201: Align FieldDefinition and Infer JSDoc/examples with the new schema‑driven model*The types now correctly model a schema‑centric pipeline:
FieldDefinitionis parameterized byTInputSchema extends z.ZodSchemaand exposes aschema: TInputSchema.processInputreceivesvalue: z.output<TInputSchema>, which implies validation has already happened upstream.InferInputSchemabuilds az.ZodObject<...>from field schemas, andInferInputreturnsz.output<InferInputSchema<TFields>>(parsed values, e.g.string, not Zod schema objects).However, the JSDoc and example code are still based on the old design:
- Summary bullets still say “Validate the input value using a Zod schema”, and the example uses
zodSchemaplusz.string().min(1).parse(value).- The InferInputSchema and InferInput comments claim “Each value type is the field’s Zod schema type” and show a plain object type with schema‑shaped properties.
To avoid confusing consumers of this template, I’d recommend:
- Updating the FieldDefinition doc/example to show
schemaas the stored Zod schema andprocessInputoperating on an already‑validatedvaluewithout callingparse()again.- Tweaking the InferInputSchema/InferInput comments to say that:
- InferInputSchema yields a
z.ZodObjectwhose properties are the field schemas.- InferInput yields the output TS types from those schemas (e.g.
{ name: string; email?: string | undefined }).This keeps the public docs in sync with the actual generic signatures used by generators.
Also applies to: 202-216, 218-246, 264-295, 296-303, 317-318
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (1)
190-201: Bring FieldDefinition and Infer docs in line with schema/output types*The runtime and types have moved to a schema‑centric, operation‑level validation model:
FieldDefinitionis parameterized byTInputSchema extends z.ZodSchema, exposesschema: TInputSchema, andprocessInputreceives az.output<TInputSchema>(already‑validated input).InferInputSchemabuilds az.ZodObjectof field schemas.InferInputis the parsed output type:z.output<InferInputSchema<TFields>>.But the documentation still reflects the old model:
- FieldDefinition’s summary bullet and example talk about validating via
schema.parse()and reference azodSchemaproperty that no longer exists.- InferInputSchema’s example shows a plain object of schema types (
{ name: z.ZodString; ... }) rather than az.ZodObject<...>.- InferInput’s comment says “Each value type is the field’s Zod schema type” even though the example correctly shows
{ name: string; email?: string | undefined }.To avoid confusion for app developers reading this file, I’d suggest:
- Updating the FieldDefinition comment/example to show
schemaand aprocessInputthat trusts the already‑validatedvalue(no extraparse()).- Updating the InferInputSchema example to show the
z.ZodObject<{ ... }>form.- Changing the InferInput description to say “Each value type is the output type of the field’s Zod schema”.
The types are solid; this is purely a documentation refresh to match the new design.
Also applies to: 202-216, 218-246, 264-295, 296-303, 317-318
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts (1)
70-79: Fix nestedOneToOneField schema generic to match.nullish()output and clarify scalarField docsTwo points here:
- Type vs runtime schema mismatch in nestedOneToOneField
generateCreateSchema(config.fields).nullish()returnsZodNullable<ZodOptional<InferInputSchema<TFields>>>, but the declared FieldDefinition schema type isz.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>. This inverts the wrapper order and exposes an inaccurate schema surface to generated code.You can fix the generic without changing runtime behaviour by swapping the wrappers:
export function nestedOneToOneField<...>( config: NestedOneToOneFieldConfig<...>, -): FieldDefinition< - z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>, - undefined, - undefined | { delete: true } -> { +): FieldDefinition< + z.ZodNullable<z.ZodOptional<InferInputSchema<TFields>>>, + undefined, + undefined | { delete: true } +> { return { - schema: generateCreateSchema(config.fields).nullish(), + schema: generateCreateSchema(config.fields).nullish(), processInput: async (value, processCtx) => { // ...This aligns the declared type with the actual
.nullish()schema.
- scalarField documentation still implies field‑level validation
The implementation now stores
schemaand expects validation to happen at the operation level, withprocessInputreceiving an already‑validatedvalue. The JSDoc still says “validates input using a Zod schema”; it would be less surprising to phrase this as “creates a field definition with an associated Zod schema (used by operation‑level validation), plus an optional transform applied to the validated value”, matching the behaviour used bygenerateCreateSchemaand$dataSchema.The code itself looks good; this is just documentation / typing alignment.
Also applies to: 80-89, 258-274, 275-277
examples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.ts (1)
32-44: Correct nestedOneToOneField Zod schema generic and clarify scalarField behaviourAs in the template version:
- nestedOneToOneField schema generic
The return type currently advertises:
FieldDefinition< z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>, undefined, undefined | { delete: true } >but
schemais:schema: generateCreateSchema(config.fields).nullish(),and
.nullish()actually producesZodNullable<ZodOptional<...>>. To keep the public type surface honest, update the generic like this:-): FieldDefinition< - z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>, - undefined, - undefined | { delete: true } -> { +): FieldDefinition< + z.ZodNullable<z.ZodOptional<InferInputSchema<TFields>>>, + undefined, + undefined | { delete: true } +> { return { schema: generateCreateSchema(config.fields).nullish(), // ...This matches the runtime schema returned by
.nullish().
- scalarField documentation
scalarFieldnow:
- Stores a Zod schema on
schema.- Relies on operation‑level validation (e.g. via
generateCreateSchema/$dataSchema).- Optionally transforms the already‑validated value before emitting create/update data.
The docstring still says it “validates input using a Zod schema”, which no longer reflects the implementation. Consider rewording it to emphasize that it provides the schema for operation‑level validation and applies an optional transform to the validated value, as suggested in earlier review comments.
Also applies to: 70-79, 80-89, 258-274, 275-277
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts (1)
353-360: Export operation function types and add explicit type annotations to operation variables.The issues raised in the previous review remain unresolved:
CreateOperationFunction(line 353) andUpdateOperationFunction(line 630) are not exported. Per coding guidelines, all types should be exported. These types are part of the public API since they define the return types of exported functions.
createOperation(line 418) andupdateOperation(line 697) lack explicit type annotations. Without typing these variables, the$dataSchemaproperty assignment (lines 523, 829) won't type-check properly.As per coding guidelines.
Apply the fix pattern suggested in the previous review:
-type CreateOperationFunction< +export type CreateOperationFunction< TModelName extends ModelPropName, TFields extends Record<string, AnyFieldDefinition>, > = (<TQueryArgs extends ModelQuery<TModelName>>( input: CreateOperationInput<TModelName, TFields, TQueryArgs>, ) => Promise<GetPayload<TModelName, TQueryArgs>>) & { $dataSchema: InferInputSchema<TFields>; };-type UpdateOperationFunction< +export type UpdateOperationFunction< TModelName extends ModelPropName, TFields extends Record<string, AnyFieldDefinition>, > = (<TQueryArgs extends ModelQuery<TModelName>>( input: UpdateOperationInput<TModelName, TFields, TQueryArgs>, ) => Promise<GetPayload<TModelName, TQueryArgs>>) & { $dataSchema: z.ZodObject<{ [k in keyof TFields]: z.ZodOptional<TFields[k]['schema']>; }>; };For the variable annotations, explicitly type them before attaching
$dataSchema:- const createOperation = async <TQueryArgs extends ModelQuery<TModelName>>({ + const createOperation: CreateOperationFunction<TModelName, TFields> = + async <TQueryArgs extends ModelQuery<TModelName>>({- const updateOperation = async <TQueryArgs extends ModelQuery<TModelName>>({ + const updateOperation: UpdateOperationFunction<TModelName, TFields> = + async <TQueryArgs extends ModelQuery<TModelName>>({Also applies to: 630-639, 415-525, 694-831
🧹 Nitpick comments (5)
plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts (1)
24-42: Consider exportingFileFieldConfigfor better API usability.The
FileFieldConfiginterface is used as a parameter type for the exportedfileFieldfunction. Exporting it would allow consumers to reference this type explicitly, which can improve type safety and developer experience when creating configuration objects.Apply this diff to export the interface:
-interface FileFieldConfig< +export interface FileFieldConfig< TFileCategory extends FileCategory, TOptional extends boolean = false, > {As per coding guidelines.
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (3)
13-20: File input schema + alias look good; consider reusing alias in this fileThe Zod schema and exported
FileInput = z.infer<typeof fileInputSchema>are consistent and match the plugin template. You might optionally useFileInputin this file (e.g., inprocessInput’s parameter type) to keep the inferred type DRY and easier to update.
80-101: Align optional schema runtime type with genericFieldDefinitiontypeFor the optional case, the generic uses:
TOptional extends true ? z.ZodOptional<z.ZodNullable<typeof fileInputSchema>> : typeof fileInputSchemabut the runtime value is
fileInputSchema.nullish(), which is equivalent to.optional().nullable()and yields a different wrapper ordering. To make the implementation match the generic more closely and potentially drop theascast, consider:- schema: (config.optional - ? fileInputSchema.nullish() - : fileInputSchema) as TOptional extends true + schema: (config.optional + ? fileInputSchema.nullable().optional() + : fileInputSchema) as TOptional extends true ? z.ZodOptional<z.ZodNullable<typeof fileInputSchema>> : typeof fileInputSchema,Same semantics (
id| null | undefined), but the type structure lines up with the declared conditional type.
102-104: Prefer using theFileInputalias inprocessInputYou can make the parameter type a bit clearer and reuse the exported alias:
- value: z.infer<typeof fileInputSchema> | null | undefined, + value: FileInput | null | undefined,This keeps the implementation consistent with what you export as the public file input type.
examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.ts (1)
71-76: ConfirmskipValidation: truesemantics are honored end‑to‑endPassing
skipValidation: trueintocreateUser/updateUserassumes those operations only run Zod validation when this flag is false, relying on Pothos’.validate(...)to have already parsed input. Please double‑check that:
- the create/update operations default
skipValidationtofalse, and- they fully bypass schema parsing when
skipValidationistrue.This avoids double validation and keeps behaviour consistent across other call sites that don’t set the flag.
Also applies to: 103-110
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (18)
examples/blog-with-auth/apps/backend/baseplate/generated/src/modules/accounts/schema/user.mutations.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/define-operations.tsis excluded by!**/generated/**,!**/generated/**examples/blog-with-auth/apps/backend/baseplate/generated/src/utils/data-operations/field-definitions.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-auth0/apps/backend/baseplate/generated/src/modules/accounts/users/schema/user.mutations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/modules/storage/services/file-field.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/modules/todos/schema/todo-item.mutations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/modules/todos/schema/todo-list-share.mutations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/modules/todos/schema/todo-list.mutations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/utils/data-operations/define-operations.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/utils/data-operations/field-definitions.tsis excluded by!**/generated/**,!**/generated/**examples/todo-with-auth0/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!**/generated/**tests/simple/apps/backend/baseplate/generated/src/utils/data-operations/define-operations.tsis excluded by!**/generated/**,!tests/**,!**/generated/**tests/simple/apps/backend/baseplate/generated/src/utils/data-operations/field-definitions.tsis excluded by!**/generated/**,!tests/**,!**/generated/**tests/simple/apps/backend/baseplate/generated/src/utils/data-operations/types.tsis excluded by!**/generated/**,!tests/**,!**/generated/**tests/simple/apps/backend/src/utils/data-operations/define-operations.tsis excluded by!tests/**tests/simple/apps/backend/src/utils/data-operations/field-definitions.tsis excluded by!tests/**tests/simple/apps/backend/src/utils/data-operations/types.tsis excluded by!tests/**
📒 Files selected for processing (20)
examples/blog-with-auth/apps/backend/src/modules/accounts/schema/user.mutations.ts(3 hunks)examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts(12 hunks)examples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.ts(6 hunks)examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts(5 hunks)examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.ts(3 hunks)examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts(4 hunks)examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-item.mutations.ts(3 hunks)examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.ts(3 hunks)examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts(3 hunks)examples/todo-with-auth0/apps/backend/src/utils/data-operations/define-operations.ts(12 hunks)examples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts(6 hunks)examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts(5 hunks)packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts(3 hunks)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts(12 hunks)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts(6 hunks)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts(5 hunks)packages/fastify-generators/src/generators/prisma/prisma-data-create/prisma-data-create.generator.ts(4 hunks)packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.ts(4 hunks)packages/fastify-generators/src/types/service-dto-kinds.ts(1 hunks)plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- examples/blog-with-auth/apps/backend/src/modules/accounts/schema/user.mutations.ts
- examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-item.mutations.ts
- examples/todo-with-auth0/apps/backend/src/utils/data-operations/define-operations.ts
- packages/fastify-generators/src/generators/prisma/prisma-data-create/prisma-data-create.generator.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
**/*.{ts,tsx}: TypeScript with strict type checking
Always include return types on top-level functions including React components (React.ReactElement)
Include absolute paths in import statements via tsconfig paths (@src/is the alias forsrc/)
If a particular interface or type is not exported, change the file so it is exportedIf a particular interface or type is not exported, update the TypeScript file so it is exported
Files:
packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.tspackages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tspackages/fastify-generators/src/types/service-dto-kinds.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tsplugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
Node 16 module resolution - include file extensions in imports (
.js)
Files:
packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.tspackages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tspackages/fastify-generators/src/types/service-dto-kinds.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tsplugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
**/*.{ts,tsx,js}: Sort imports by group: external libs first, then local imports
Use camelCase for variables/functions, PascalCase for types/classes
Order functions such that functions are placed below the variables/functions they use
We use the prefer using nullish coalescing operator (??) ESLint rule instead of a logical or (||), as it is a safer operator
Use console.info/warn/error instead of console.log
Files:
packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.tspackages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tspackages/fastify-generators/src/types/service-dto-kinds.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tsplugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
**/*
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
Use kebab-case for file names
Files:
packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.tspackages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tspackages/fastify-generators/src/types/service-dto-kinds.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tsplugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (examples/todo-with-auth0/CLAUDE.md)
examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx}: Always use .js extensions in import statements, even when importing from TypeScript files
Useimport typefor type-only imports
Always specify explicit return types for all functions
Add JSDoc to all exported functions, interfaces, and classes documenting purpose, parameters, returns, and fields
Files:
examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts
examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*
📄 CodeRabbit inference engine (examples/todo-with-auth0/CLAUDE.md)
Use kebab-case for all file and directory names
Files:
examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts
examples/blog-with-auth/apps/**/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (examples/blog-with-auth/CLAUDE.md)
examples/blog-with-auth/apps/**/src/**/*.{ts,tsx}: Always use .js file extensions in import statements, even when importing from .ts files
Useimport typefor type-only imports
Always specify explicit return types for all functions
Add JSDoc to all exported functions, interfaces, and classes, documenting purpose, parameters, return values, and all fields
Files:
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
🧠 Learnings (29)
📚 Learning: 2025-05-05T06:36:50.687Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 521
File: packages/react-generators/src/generators/admin/admin-crud-edit/admin-crud-edit.generator.ts:90-94
Timestamp: 2025-05-05T06:36:50.687Z
Learning: In this codebase, import paths can include `.ts` extensions, and the `resolveModuleSpecifier` function will handle them appropriately. There's no need to strip file extensions before passing paths to functions like `TsCodeUtils.importFragment`.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-07-07T18:24:17.522Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 592
File: plugins/plugin-auth/src/auth0/generators/react/auth0-hooks/templates/src/hooks/use-required-user-id.ts:1-2
Timestamp: 2025-07-07T18:24:17.522Z
Learning: Files under templates/** directories can use `// ts-nocheck` because they are templates meant for code generation, not direct type checking.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-07-22T09:11:29.223Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-07-22T09:11:29.223Z
Learning: Applies to {packages/project-builder-web/**,packages/ui-components/**}/*.tsx : Use ShadCN-based components from `baseplate-dev/ui-components` and always prefer these components over creating custom ones
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-05-05T06:37:43.106Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 521
File: plugins/baseplate-plugin-storage/src/generators/react/upload-components/upload-components.generator.ts:108-112
Timestamp: 2025-05-05T06:37:43.106Z
Learning: The template extractor in the baseplate codebase can automatically infer and determine the necessary import map providers for certain templates, making explicit specification of importMapProviders unnecessary in those cases.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-07-30T13:27:20.000Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 623
File: plugins/plugin-auth/src/local-auth/core/generators/react-session/templates/src/app/user-session-provider.tsx:6-12
Timestamp: 2025-07-30T13:27:20.000Z
Learning: Ignore ESLint import ordering rules for files in templates/** directories as these are code generation templates, not direct source code.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-05-05T06:37:51.001Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 521
File: packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts:163-166
Timestamp: 2025-05-05T06:37:51.001Z
Learning: For certain templates in the codebase, the `importMapProviders` property is not explicitly required as the template extractor will automatically determine and infer the necessary import map providers.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-06-11T18:31:22.247Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 571
File: packages/core-generators/src/renderers/extractor/plugins/typed-templates-file.ts:102-106
Timestamp: 2025-06-11T18:31:22.247Z
Learning: For `templateExtractorBarrelExportPlugin.addGeneratedBarrelExport`, the generated barrel exports are written into `generated/index.ts`, therefore the `moduleSpecifier` must be specified relative to that file (e.g., `./typed-templates.js`), not the project root.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-07-16T17:15:56.714Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 613
File: packages/react-generators/src/generators/core/react-components/templates/components/ui/circular-progress/circular-progress.tsx:0-0
Timestamp: 2025-07-16T17:15:56.714Z
Learning: For imports starting with `$` (template aliases), do not require `.js` extensions as these are resolved differently during the generation process, unlike regular file imports which require explicit `.js` extensions under Node 16 module resolution.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-08-17T01:30:00.344Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 633
File: packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts:47-48
Timestamp: 2025-08-17T01:30:00.344Z
Learning: In template extraction systems like apply-simple-replacements.ts, it's intentional to skip processing import declarations to allow unused imports to be removed properly after template variable replacements are applied.
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx} : Use `import type` for type-only imports
Applied to files:
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tspackages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{tsconfig*.json,apps/{admin,backend}/tsconfig*.json} : Use TypeScript NodeNext module resolution and module ("moduleResolution": "NodeNext", "module": "NodeNext")
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx} : Add JSDoc to all exported functions, interfaces, and classes documenting purpose, parameters, returns, and fields
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx} : Always specify explicit return types for all functions
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{unit,int}.test.ts : Name test files with .unit.test.ts or .int.test.ts suffixes
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{tsconfig*.json,apps/{admin,backend}/tsconfig*.json} : Enable "isolatedModules": true in TypeScript
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{unit,int}.test.ts : Vitest tests must not use globals; import describe/it/expect from 'vitest'
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{apps/admin/src,apps/backend/src}/**/*.{ts,tsx} : Always use .js extensions in import statements, even when importing from TypeScript files
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{tsconfig*.json,apps/{admin,backend}/tsconfig*.json} : Enable strict type checking in TypeScript ("strict": true)
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.tsexamples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts
📚 Learning: 2025-10-23T21:00:29.010Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/blog-with-auth/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:00:29.010Z
Learning: Applies to examples/blog-with-auth/apps/**/src/**/*.{ts,tsx} : Add JSDoc to all exported functions, interfaces, and classes, documenting purpose, parameters, return values, and all fields
Applied to files:
examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.tsexamples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
📚 Learning: 2025-10-23T21:00:29.010Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/blog-with-auth/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:00:29.010Z
Learning: Applies to examples/blog-with-auth/**/tsconfig*.json : Use TypeScript module resolution NodeNext (and matching ESM settings)
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-10-23T21:01:15.331Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:01:15.331Z
Learning: Applies to examples/todo-with-auth0/{package.json,apps/{admin,backend}/package.json} : Use ESM only by setting "type": "module" in package.json
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-01-23T09:12:46.178Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 428
File: packages/project-builder-server/src/sync/index.ts:5-5
Timestamp: 2025-01-23T09:12:46.178Z
Learning: Avoid importing directly from 'dist' directories. Instead, expose functionality through the package's public API and import from the main package entry point.
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-10-23T21:00:29.010Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/blog-with-auth/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:00:29.010Z
Learning: Applies to examples/blog-with-auth/**/package.json : Module system must be ESM only by setting "type": "module" in package.json
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-07-22T09:10:31.413Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-07-22T09:10:31.413Z
Learning: Applies to **/*.{js,ts,tsx} : Node 16 module resolution - include file extensions in imports (`.js`)
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-07-22T09:10:31.413Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-07-22T09:10:31.413Z
Learning: Applies to **/index.{ts,tsx,js} : Prefer barrel exports e.g. export * from './foo.js' instead of individual named exports
Applied to files:
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts
📚 Learning: 2025-10-14T08:07:58.492Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-14T08:07:58.492Z
Learning: Applies to **/*.{ts,tsx} : If a particular interface or type is not exported, update the TypeScript file so it is exported
Applied to files:
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
📚 Learning: 2025-07-22T09:11:16.930Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-22T09:11:16.930Z
Learning: Refactor code to be more easily testable, such as exporting types or functions
Applied to files:
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
📚 Learning: 2025-07-22T09:10:31.413Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-07-22T09:10:31.413Z
Learning: Applies to **/*.{ts,tsx} : If a particular interface or type is not exported, change the file so it is exported
Applied to files:
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts
📚 Learning: 2025-10-23T21:00:29.010Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/blog-with-auth/CLAUDE.md:0-0
Timestamp: 2025-10-23T21:00:29.010Z
Learning: Applies to examples/blog-with-auth/apps/**/src/**/*.{ts,tsx} : Use `import type` for type-only imports
Applied to files:
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts
🧬 Code graph analysis (14)
packages/fastify-generators/src/generators/prisma/prisma-data-update/prisma-data-update.generator.ts (3)
packages/core-generators/src/renderers/typescript/utils/ts-code-utils.ts (2)
TsCodeUtils(85-584)tsTemplate(587-587)packages/fastify-generators/src/types/service-output.ts (1)
createServiceOutputDtoInjectedArg(85-100)packages/fastify-generators/src/types/service-dto-kinds.ts (1)
skipValidationKind(93-93)
packages/fastify-generators/src/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.ts (2)
packages/fastify-generators/src/types/service-dto-kinds.ts (1)
skipValidationKind(93-93)packages/core-generators/src/renderers/typescript/utils/ts-code-utils.ts (1)
tsTemplate(587-587)
examples/todo-with-auth0/apps/backend/src/modules/accounts/users/schema/user.mutations.ts (1)
examples/blog-with-auth/apps/backend/src/plugins/graphql/builder.ts (1)
builder(28-80)
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list-share.mutations.ts (1)
examples/blog-with-auth/apps/backend/src/plugins/graphql/builder.ts (1)
builder(28-80)
examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts (2)
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (3)
FieldDefinition(218-246)InferInputSchema(284-294)AnyFieldDefinition(249-249)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (3)
FieldDefinition(218-246)InferInputSchema(284-294)AnyFieldDefinition(249-249)
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (1)
plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts (1)
FileInput(19-19)
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts (1)
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (3)
AnyFieldDefinition(249-249)InferInputSchema(284-294)InferInput(317-318)
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts (3)
examples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.ts (1)
scalarField(70-92)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (2)
FieldDefinition(218-246)InferInputSchema(284-294)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts (1)
generateCreateSchema(240-250)
examples/blog-with-auth/apps/backend/src/utils/data-operations/field-definitions.ts (2)
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (2)
FieldDefinition(218-246)InferInputSchema(284-294)examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts (1)
generateCreateSchema(242-252)
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts (2)
examples/blog-with-auth/apps/backend/src/plugins/graphql/builder.ts (1)
builder(28-80)plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/schema/file-input.input-type.ts (1)
fileInputInputType(5-11)
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (2)
examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (3)
FieldDefinition(218-246)InferInputSchema(284-294)AnyFieldDefinition(249-249)examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts (3)
FieldDefinition(218-246)InferInputSchema(284-294)AnyFieldDefinition(249-249)
plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts (2)
examples/todo-with-auth0/apps/backend/src/modules/storage/services/file-field.ts (1)
FileInput(20-20)packages/fastify-generators/src/generators/core/config-service/templates/src/services/config.ts (1)
config(5-5)
examples/todo-with-auth0/apps/backend/src/utils/data-operations/field-definitions.ts (2)
examples/todo-with-auth0/apps/backend/src/utils/data-operations/types.ts (2)
FieldDefinition(218-246)InferInputSchema(284-294)examples/todo-with-auth0/apps/backend/src/utils/data-operations/define-operations.ts (1)
generateCreateSchema(242-252)
packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts (3)
examples/blog-with-auth/apps/backend/src/utils/data-operations/define-operations.ts (4)
generateCreateSchema(242-252)CreateOperationInput(335-351)transformFields(103-209)UpdateOperationInput(610-628)examples/blog-with-auth/apps/backend/src/utils/data-operations/types.ts (3)
AnyFieldDefinition(249-249)InferInputSchema(284-294)InferInput(317-318)packages/fastify-generators/src/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts (3)
AnyFieldDefinition(249-249)InferInputSchema(284-294)InferInput(317-318)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Verify Sync (todo-with-auth0)
- GitHub Check: Verify Sync (blog-with-auth)
- GitHub Check: Lint Examples (todo-with-auth0)
- GitHub Check: Test E2E
- GitHub Check: test
- GitHub Check: Lint
| const updateTodoListDataInputType = builder | ||
| .inputType('UpdateTodoListData', { | ||
| fields: (t) => ({ | ||
| ownerId: t.field({ type: 'Uuid' }), | ||
| position: t.int(), | ||
| name: t.string(), | ||
| createdAt: t.field({ type: 'DateTime' }), | ||
| status: t.field({ type: todoListStatusEnum }), | ||
| coverPhoto: t.field({ type: fileInputInputType }), | ||
| }), | ||
| }) | ||
| .validate(updateTodoList.$dataSchema); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add JSDoc documentation to exported input type.
The exported updateTodoListDataInputType constant lacks JSDoc documentation. According to the coding guidelines for this path, all exported functions, interfaces, and classes should have JSDoc documenting their purpose and fields.
Based on learnings
Apply this diff to add JSDoc:
+/**
+ * Input type for updating an existing todo list
+ * Validated against the Zod schema from updateTodoList service
+ */
const updateTodoListDataInputType = builder
.inputType('UpdateTodoListData', {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const updateTodoListDataInputType = builder | |
| .inputType('UpdateTodoListData', { | |
| fields: (t) => ({ | |
| ownerId: t.field({ type: 'Uuid' }), | |
| position: t.int(), | |
| name: t.string(), | |
| createdAt: t.field({ type: 'DateTime' }), | |
| status: t.field({ type: todoListStatusEnum }), | |
| coverPhoto: t.field({ type: fileInputInputType }), | |
| }), | |
| }) | |
| .validate(updateTodoList.$dataSchema); | |
| /** | |
| * Input type for updating an existing todo list | |
| * Validated against the Zod schema from updateTodoList service | |
| */ | |
| const updateTodoListDataInputType = builder | |
| .inputType('UpdateTodoListData', { | |
| fields: (t) => ({ | |
| ownerId: t.field({ type: 'Uuid' }), | |
| position: t.int(), | |
| name: t.string(), | |
| createdAt: t.field({ type: 'DateTime' }), | |
| status: t.field({ type: todoListStatusEnum }), | |
| coverPhoto: t.field({ type: fileInputInputType }), | |
| }), | |
| }) | |
| .validate(updateTodoList.$dataSchema); |
🤖 Prompt for AI Agents
In
examples/todo-with-auth0/apps/backend/src/modules/todos/schema/todo-list.mutations.ts
around lines 49 to 60, the exported constant updateTodoListDataInputType is
missing JSDoc; add a JSDoc block immediately above the export that briefly
describes the purpose of this input type (used for updating a todo list) and
documents each field (ownerId: Uuid, position: number, name: string, createdAt:
DateTime, status: todoListStatusEnum, coverPhoto: fileInputInputType) and note
that the input is validated against updateTodoList.$dataSchema so readers know
validation is applied.
| type CreateOperationFunction< | ||
| TModelName extends ModelPropName, | ||
| TFields extends Record<string, AnyFieldDefinition>, | ||
| > = (<TQueryArgs extends ModelQuery<TModelName>>( | ||
| input: CreateOperationInput<TModelName, TFields, TQueryArgs>, | ||
| ) => Promise<GetPayload<TModelName, TQueryArgs>>) & { | ||
| $dataSchema: InferInputSchema<TFields>; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Export operation function types and add explicit type annotations (template file).
This template file has the same issues as the example file, but fixing them here is especially critical since this code will be generated for all projects using this template:
-
CreateOperationFunction(line 351) andUpdateOperationFunction(line 628) are not exported. These types should be exported per coding guidelines. -
createOperation(line 416) andupdateOperation(line 695) lack explicit type annotations. Without proper typing, the$dataSchemaproperty assignments (lines 521, 827) won't type-check.
As per coding guidelines.
Apply these fixes:
-type CreateOperationFunction<
+export type CreateOperationFunction<
TModelName extends ModelPropName,
TFields extends Record<string, AnyFieldDefinition>,
> = (<TQueryArgs extends ModelQuery<TModelName>>(
input: CreateOperationInput<TModelName, TFields, TQueryArgs>,
) => Promise<GetPayload<TModelName, TQueryArgs>>) & {
$dataSchema: InferInputSchema<TFields>;
};-type UpdateOperationFunction<
+export type UpdateOperationFunction<
TModelName extends ModelPropName,
TFields extends Record<string, AnyFieldDefinition>,
> = (<TQueryArgs extends ModelQuery<TModelName>>(
input: UpdateOperationInput<TModelName, TFields, TQueryArgs>,
) => Promise<GetPayload<TModelName, TQueryArgs>>) & {
$dataSchema: z.ZodObject<{
[k in keyof TFields]: z.ZodOptional<TFields[k]['schema']>;
}>;
};- const createOperation = async <TQueryArgs extends ModelQuery<TModelName>>({
+ const createOperation: CreateOperationFunction<TModelName, TFields> =
+ async <TQueryArgs extends ModelQuery<TModelName>>({- const updateOperation = async <TQueryArgs extends ModelQuery<TModelName>>({
+ const updateOperation: UpdateOperationFunction<TModelName, TFields> =
+ async <TQueryArgs extends ModelQuery<TModelName>>({Also applies to: 628-637, 413-523, 692-829
| import { STORAGE_ADAPTERS } from '$configAdapters'; | ||
| import { BadRequestError } from '%errorHandlerServiceImports'; | ||
| import { prisma } from '%prismaImports'; | ||
| import { z } from 'zod'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Reorder imports: external libraries should come before local imports.
The zod import should be placed before the local imports (lines 3-9) to comply with the import ordering guideline.
Apply this diff to fix the import order:
+import { z } from 'zod';
+
import type { FileCategory } from '$typesFileCategory';
import type { FieldDefinition } from '%dataUtilsImports';
import type { Prisma } from '%prismaGeneratedImports';
import { STORAGE_ADAPTERS } from '$configAdapters';
import { BadRequestError } from '%errorHandlerServiceImports';
import { prisma } from '%prismaImports';
-import { z } from 'zod';As per coding guidelines.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { z } from 'zod'; | |
| import { z } from 'zod'; | |
| import type { FileCategory } from '$typesFileCategory'; | |
| import type { FieldDefinition } from '%dataUtilsImports'; | |
| import type { Prisma } from '%prismaGeneratedImports'; | |
| import { STORAGE_ADAPTERS } from '$configAdapters'; | |
| import { BadRequestError } from '%errorHandlerServiceImports'; | |
| import { prisma } from '%prismaImports'; |
🤖 Prompt for AI Agents
In
plugins/plugin-storage/src/generators/fastify/storage-module/templates/module/services/file-field.ts
around line 10, the import of the external library `zod` is placed after local
imports (lines 3-9); move the line "import { z } from 'zod';" so it appears
before any local/project imports to ensure external libraries are listed first
and comply with the import ordering guideline.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.