diff --git a/packages/schema/src/plugins/zod/transformer.ts b/packages/schema/src/plugins/zod/transformer.ts index f79c945cc..16e1451bf 100644 --- a/packages/schema/src/plugins/zod/transformer.ts +++ b/packages/schema/src/plugins/zod/transformer.ts @@ -342,7 +342,21 @@ export default class Transformer { // "Input" or "NestedInput" suffix mappedInputTypeName += match[4]; - processedInputType = { ...inputType, type: mappedInputTypeName }; + // Prisma's naming is inconsistent for update input types, so we need + // to check for a few other candidates and use the one that matches + // a DMMF input type name + const candidates = [mappedInputTypeName]; + if (mappedInputTypeName.includes('UpdateOne')) { + candidates.push(...candidates.map((name) => name.replace('UpdateOne', 'Update'))); + } + if (mappedInputTypeName.includes('NestedInput')) { + candidates.push(...candidates.map((name) => name.replace('NestedInput', 'Input'))); + } + + const finalMappedName = + candidates.find((name) => this.inputObjectTypes.some((it) => it.name === name)) ?? mappedInputTypeName; + + processedInputType = { ...inputType, type: finalMappedName }; } return processedInputType; } diff --git a/packages/sdk/src/utils.ts b/packages/sdk/src/utils.ts index 09a538f77..0427ab4f0 100644 --- a/packages/sdk/src/utils.ts +++ b/packages/sdk/src/utils.ts @@ -659,8 +659,16 @@ export function getRelationBackLink(field: DataModelField) { const targetModel = field.type.reference.ref as DataModel; + const sameField = (f1: DataModelField, f2: DataModelField) => { + // for fields inherited from a delegate model, always use + // the base to compare + const parent1 = f1.$inheritedFrom ?? f1.$container; + const parent2 = f2.$inheritedFrom ?? f2.$container; + return f1.name === f2.name && parent1 === parent2; + }; + for (const otherField of targetModel.fields) { - if (otherField === field) { + if (sameField(otherField, field)) { // backlink field is never self continue; } diff --git a/tests/regression/tests/issue-2226.test.ts b/tests/regression/tests/issue-2226.test.ts new file mode 100644 index 000000000..8dc55bfad --- /dev/null +++ b/tests/regression/tests/issue-2226.test.ts @@ -0,0 +1,31 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 2226', () => { + it('regression', async () => { + const { zodSchemas } = await loadSchema( + ` +model Registration { + id String @id + regType String + @@delegate(regType) + + replacedRegistrationId String? + replacedRegistration Registration? @relation("ReplacedBy", fields: [replacedRegistrationId], references: [id]) + replacements Registration[] @relation("ReplacedBy") +} + +// Delegated subtype +model RegistrationFramework extends Registration { +} +`, + { fullZod: true } + ); + + const schema = zodSchemas.objects.RegistrationFrameworkUpdateInputObjectSchema; + expect(schema).toBeDefined(); + const parsed = schema.safeParse({ + replacedRegistrationId: '123', + }); + expect(parsed.success).toBe(true); + }); +});