diff --git a/.changeset/fix-schema-input-types.md b/.changeset/fix-schema-input-types.md new file mode 100644 index 000000000..9be0a61e9 --- /dev/null +++ b/.changeset/fix-schema-input-types.md @@ -0,0 +1,14 @@ +--- +"@aws-amplify/data-schema": patch +--- + +fix(schema): preserve `array`, `arrayRequired`, and `valueRequired` when generating input types for custom fields + +Previously, nested custom input types dropped important metadata about array and requiredness. +This change ensures: + +- `array` is passed through for referenced custom types +- `arrayRequired` and `valueRequired` are correctly preserved +- Inline custom types default to `false` for these fields + +This fixes inconsistencies between schema definitions and generated GraphQL input types. diff --git a/packages/data-schema-types/docs/data-schema-types.derivedapidefinition.md b/packages/data-schema-types/docs/data-schema-types.derivedapidefinition.md index 4cf945a75..875dcd20a 100644 --- a/packages/data-schema-types/docs/data-schema-types.derivedapidefinition.md +++ b/packages/data-schema-types/docs/data-schema-types.derivedapidefinition.md @@ -158,3 +158,4 @@ Return the schema definition as a graphql string, with amplify directives allowe + diff --git a/packages/data-schema-types/docs/data-schema-types.graphqlformattederror.md b/packages/data-schema-types/docs/data-schema-types.graphqlformattederror.md index 686fd3fd0..f5aaee77c 100644 --- a/packages/data-schema-types/docs/data-schema-types.graphqlformattederror.md +++ b/packages/data-schema-types/docs/data-schema-types.graphqlformattederror.md @@ -162,3 +162,4 @@ _(Optional)_ If an error can be associated to a particular field in the GraphQL + diff --git a/packages/data-schema-types/docs/data-schema-types.md b/packages/data-schema-types/docs/data-schema-types.md index b44c0ce3c..4eea3df35 100644 --- a/packages/data-schema-types/docs/data-schema-types.md +++ b/packages/data-schema-types/docs/data-schema-types.md @@ -563,3 +563,4 @@ Replaces the value of a key in a complex generic type param + diff --git a/packages/data-schema-types/docs/data-schema-types.sourcelocation.md b/packages/data-schema-types/docs/data-schema-types.sourcelocation.md index 6ae658dbc..fc4a14be8 100644 --- a/packages/data-schema-types/docs/data-schema-types.sourcelocation.md +++ b/packages/data-schema-types/docs/data-schema-types.sourcelocation.md @@ -74,3 +74,4 @@ number + diff --git a/packages/data-schema-types/docs/index.md b/packages/data-schema-types/docs/index.md index 3c97e8017..25c26061a 100644 --- a/packages/data-schema-types/docs/index.md +++ b/packages/data-schema-types/docs/index.md @@ -27,3 +27,4 @@ Description + diff --git a/packages/data-schema/__tests__/CustomOperations.test-d.ts b/packages/data-schema/__tests__/CustomOperations.test-d.ts index 21ff0e499..e80fccf0d 100644 --- a/packages/data-schema/__tests__/CustomOperations.test-d.ts +++ b/packages/data-schema/__tests__/CustomOperations.test-d.ts @@ -1051,3 +1051,93 @@ describe('.arguments() modifier', () => { type Test = Expect>; }); }); + +describe('input type metadata preservation - TypeScript types', () => { + it('should handle TodoUpsert schema with array and required modifiers', () => { + const schema = a.schema({ + TodoTagType: a.customType({ + name: a.string().required(), + color: a.string().required(), + }), + Todo: a + .model({ + content: a.string(), + tags: a.ref('TodoTagType').array(), + updatedTs: a.integer(), + }), + TodoUpsert: a.customType({ + content: a.string(), + tags: a.ref('TodoTagType').array(), + updatedTs: a.integer(), + }), + batchUpsertTodos: a + .mutation() + .arguments({ + tableName: a.string().required(), + items: a.ref('TodoUpsert').array().required(), + }) + .returns(a.ref('Todo').array()) + .handler(a.handler.function('myFunc')), + }); + + type Schema = ClientSchema; + + // Verify that the type structure includes required fields properly + type ActualArgs = Schema['batchUpsertTodos']['args']; + + // Basic type structure verification - the exact shape is verified in runtime tests + const _typeCheck: ActualArgs = {} as ActualArgs; + + // These assignments should work with your fix + const validArgs: ActualArgs = { + tableName: 'test', + items: [{ + content: 'test content', + tags: [{ name: 'tag1', color: 'blue' }], + updatedTs: 12345 + }] + }; + + // This should be a type compile-time validation that the types work correctly + expect(validArgs).toBeDefined(); + }); + + it('should preserve array and required modifiers in TypeScript types', () => { + const schema = a.schema({ + TagType: a.customType({ + name: a.string().required(), + color: a.string().required(), + }), + testMutation: a + .mutation() + .arguments({ + requiredTags: a.ref('TagType').array().required(), + optionalTags: a.ref('TagType').array(), + singleRequiredTag: a.ref('TagType').required(), + singleOptionalTag: a.ref('TagType'), + }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + }); + + type Schema = ClientSchema; + type ActualArgs = Schema['testMutation']['args']; + + // Verify the structure allows valid assignments + const validArgs: ActualArgs = { + requiredTags: [{ name: 'tag1', color: 'red' }], + singleRequiredTag: { name: 'tag2', color: 'blue' }, + // optionalTags and singleOptionalTag can be omitted + }; + + const validArgsWithOptionals: ActualArgs = { + requiredTags: [{ name: 'tag1', color: 'red' }], + singleRequiredTag: { name: 'tag2', color: 'blue' }, + optionalTags: [{ name: 'tag3', color: 'green' }], + singleOptionalTag: { name: 'tag4', color: 'yellow' }, + }; + + expect(validArgs).toBeDefined(); + expect(validArgsWithOptionals).toBeDefined(); + }); +}); diff --git a/packages/data-schema/__tests__/CustomOperations.test.ts b/packages/data-schema/__tests__/CustomOperations.test.ts index 63a50deea..70b02d1c5 100644 --- a/packages/data-schema/__tests__/CustomOperations.test.ts +++ b/packages/data-schema/__tests__/CustomOperations.test.ts @@ -1663,6 +1663,232 @@ describe('CustomOperation transform', () => { }); }); + describe('input type metadata preservation', () => { + test('regression: existing simple input types still work correctly', () => { + const s = a + .schema({ + post: a.customType({ + title: a.string(), + content: a.string(), + }), + simpleQuery: a + .query() + .arguments({ + simpleArg: a.ref('post'), + }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify the input type is generated correctly for simple cases + expect(result).toContain('input postInput'); + expect(result).toContain('simpleArg: postInput'); + + expect(result).toMatchSnapshot(); + }); + + test('should preserve array and required modifiers in input types', () => { + // Based on the user's real schema that demonstrates the bug + const s = a + .schema({ + TodoTagType: a.customType({ + name: a.string().required(), + color: a.string().required(), + }), + Todo: a + .model({ + content: a.string(), + tags: a.ref('TodoTagType').array(), + updatedTs: a.integer(), + }), + TodoUpsert: a.customType({ + content: a.string(), + tags: a.ref('TodoTagType').array(), + updatedTs: a.integer(), + }), + batchUpsertTodos: a + .mutation() + .arguments({ + tableName: a.string().required(), + items: a.ref('TodoUpsert').array().required(), + }) + .returns(a.ref('Todo').array()) + .handler(a.handler.function('myFunc')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify the input types are generated with proper GraphQL syntax + expect(result).toContain('input TodoTagTypeInput'); + expect(result).toContain('input TodoUpsertInput'); + + // The key test: verify that array and required modifiers are preserved + expect(result).toContain('tableName: String!'); + expect(result).toContain('items: [TodoUpsertInput]!'); // Fixed: array is required but elements are not + + // Verify nested structure is correct too + expect(result).toContain('tags: [TodoTagTypeInput]'); + + expect(result).toMatchSnapshot(); + }); + + test('preserves array().required() modifier on referenced custom type arguments', () => { + const s = a + .schema({ + TagType: a.customType({ + name: a.string().required(), + color: a.string().required(), + }), + testMutation: a + .mutation() + .arguments({ + requiredTags: a.ref('TagType').array().required(), // Array is required, items are optional + optionalTags: a.ref('TagType').array(), + singleRequiredTag: a.ref('TagType').required(), + singleOptionalTag: a.ref('TagType'), + bothRequired: a.ref('TagType').required().array().required(), // Both array and items required + }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify the input type is generated with proper GraphQL syntax + expect(result).toContain('input TagTypeInput'); + expect(result).toContain('requiredTags: [TagTypeInput]!'); // Array required, items optional + expect(result).toContain('optionalTags: [TagTypeInput]'); // Both optional + expect(result).toContain('singleRequiredTag: TagTypeInput!'); // Single item required + expect(result).toContain('singleOptionalTag: TagTypeInput'); // Single item optional + expect(result).toContain('bothRequired: [TagTypeInput!]!'); // Both required + + expect(result).toMatchSnapshot(); + }); + + test('preserves modifiers on nested custom type references', () => { + const s = a + .schema({ + InnerType: a.customType({ + value: a.string(), + }), + OuterType: a.customType({ + innerItems: a.ref('InnerType').array(), + singleInner: a.ref('InnerType').required(), + }), + testMutation: a + .mutation() + .arguments({ + data: a.ref('OuterType').required(), + dataArray: a.ref('OuterType').array().required(), + }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify all input types are generated + expect(result).toContain('input InnerTypeInput'); + expect(result).toContain('input OuterTypeInput'); + + // Verify top-level argument modifiers are preserved + expect(result).toContain('data: OuterTypeInput!'); + expect(result).toContain('dataArray: [OuterTypeInput]!'); // Array required, items optional + + // Verify nested field modifiers are preserved + expect(result).toContain('innerItems: [InnerTypeInput]'); + expect(result).toContain('singleInner: InnerTypeInput!'); + + expect(result).toMatchSnapshot(); + }); + + test('preserves modifiers in complex batch operation scenarios', () => { + const s = a + .schema({ + MetadataType: a.customType({ + version: a.string().required(), + timestamp: a.integer().required(), + }), + ItemType: a.customType({ + id: a.string().required(), + data: a.string(), + metadata: a.ref('MetadataType').required(), + tags: a.ref('MetadataType').array(), + }), + batchOperation: a + .mutation() + .arguments({ + operationId: a.string().required(), + itemsToCreate: a.ref('ItemType').array().required(), + itemsToUpdate: a.ref('ItemType').array(), + metadataOverride: a.ref('MetadataType'), + }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify all input types are generated + expect(result).toContain('input MetadataTypeInput'); + expect(result).toContain('input ItemTypeInput'); + + // Verify argument modifiers are preserved + expect(result).toContain('operationId: String!'); + expect(result).toContain('itemsToCreate: [ItemTypeInput]!'); // Array required, items optional + expect(result).toContain('itemsToUpdate: [ItemTypeInput]'); + expect(result).toContain('metadataOverride: MetadataTypeInput'); + + // Verify nested field modifiers are preserved + expect(result).toContain('metadata: MetadataTypeInput!'); + expect(result).toContain('tags: [MetadataTypeInput]'); + + expect(result).toMatchSnapshot(); + }); + + test('preserves modifiers in subscription arguments', () => { + const s = a + .schema({ + FilterType: a.customType({ + category: a.string().required(), + priority: a.integer(), + }), + someMutation: a + .mutation() + .arguments({ input: a.string() }) + .returns(a.string()) + .handler(a.handler.function('myFunc')), + subscribeToUpdates: a + .subscription() + .arguments({ + filters: a.ref('FilterType').array().required(), + globalFilter: a.ref('FilterType'), + }) + .handler(a.handler.function('myFunc')) + .for(a.ref('someMutation')), + }) + .authorization((allow) => allow.publicApiKey()); + + const result = s.transform().schema; + + // Verify input types are generated + expect(result).toContain('input FilterTypeInput'); + + // Verify subscription argument modifiers are preserved + expect(result).toContain('filters: [FilterTypeInput]!'); // Array required, items optional + expect(result).toContain('globalFilter: FilterTypeInput'); + + expect(result).toMatchSnapshot(); + }); + }); + const fakeSecret = () => ({}) as any; const datasourceConfigMySQL = { diff --git a/packages/data-schema/__tests__/__snapshots__/CustomOperations.test.ts.snap b/packages/data-schema/__tests__/__snapshots__/CustomOperations.test.ts.snap index 285056234..308e5012a 100644 --- a/packages/data-schema/__tests__/__snapshots__/CustomOperations.test.ts.snap +++ b/packages/data-schema/__tests__/__snapshots__/CustomOperations.test.ts.snap @@ -904,6 +904,156 @@ type Query { }" `; +exports[`CustomOperation transform input type metadata preservation preserves array().required() modifier on referenced custom type arguments 1`] = ` +"type TagType +{ + name: String! + color: String! +} + +input TagTypeInput { + name: String! + color: String! +} + +type Mutation { + testMutation(requiredTags: [TagTypeInput]!, optionalTags: [TagTypeInput], singleRequiredTag: TagTypeInput!, singleOptionalTag: TagTypeInput, bothRequired: [TagTypeInput!]!): String @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + +exports[`CustomOperation transform input type metadata preservation preserves modifiers in complex batch operation scenarios 1`] = ` +"type MetadataType +{ + version: String! + timestamp: Int! +} + +type ItemType +{ + id: String! + data: String + metadata: MetadataType! + tags: [MetadataType] +} + +input MetadataTypeInput { + version: String! + timestamp: Int! +} + +input ItemTypeInput { + id: String! + data: String + metadata: MetadataTypeInput! + tags: [MetadataTypeInput] +} + +type Mutation { + batchOperation(operationId: String!, itemsToCreate: [ItemTypeInput]!, itemsToUpdate: [ItemTypeInput], metadataOverride: MetadataTypeInput): String @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + +exports[`CustomOperation transform input type metadata preservation preserves modifiers in subscription arguments 1`] = ` +"type FilterType +{ + category: String! + priority: Int +} + +input FilterTypeInput { + category: String! + priority: Int +} + +type Mutation { + someMutation(input: String): String @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +} + +type Subscription { + subscribeToUpdates(filters: [FilterTypeInput]!, globalFilter: FilterTypeInput): String @function(name: "myFunc") @aws_subscribe(mutations: ["someMutation"]) @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + +exports[`CustomOperation transform input type metadata preservation preserves modifiers on nested custom type references 1`] = ` +"type InnerType +{ + value: String +} + +type OuterType +{ + innerItems: [InnerType] + singleInner: InnerType! +} + +input InnerTypeInput { + value: String +} + +input OuterTypeInput { + innerItems: [InnerTypeInput] + singleInner: InnerTypeInput! +} + +type Mutation { + testMutation(data: OuterTypeInput!, dataArray: [OuterTypeInput]!): String @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + +exports[`CustomOperation transform input type metadata preservation regression: existing simple input types still work correctly 1`] = ` +"type post +{ + title: String + content: String +} + +input postInput { + title: String + content: String +} + +type Query { + simpleQuery(simpleArg: postInput): String @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + +exports[`CustomOperation transform input type metadata preservation should preserve array and required modifiers in input types 1`] = ` +"type Todo @model @auth(rules: [{allow: public, provider: apiKey}]) +{ + content: String + tags: [TodoTagType] + updatedTs: Int +} + +type TodoTagType +{ + name: String! + color: String! +} + +type TodoUpsert +{ + content: String + tags: [TodoTagType] + updatedTs: Int +} + +input TodoTagTypeInput { + name: String! + color: String! +} + +input TodoUpsertInput { + content: String + tags: [TodoTagTypeInput] + updatedTs: Int +} + +type Mutation { + batchUpsertTodos(tableName: String!, items: [TodoUpsertInput]!): [Todo] @function(name: "myFunc") @auth(rules: [{allow: public, provider: apiKey}]) +}" +`; + exports[`CustomOperation transform sql schema Schema w model, custom query, mutation, and subscription 1`] = ` "type Post @model(timestamps: null) @auth(rules: [{allow: public, provider: apiKey}]) { diff --git a/packages/data-schema/docs/data-schema.a.belongsto.md b/packages/data-schema/docs/data-schema.a.belongsto.md index 49cb9d1ca..36e0585fe 100644 --- a/packages/data-schema/docs/data-schema.a.belongsto.md +++ b/packages/data-schema/docs/data-schema.a.belongsto.md @@ -63,6 +63,7 @@ the field(s) that should be used to reference the related model + **Returns:** [ModelRelationshipField](./data-schema.modelrelationshipfield.md)<[ModelRelationshipTypeArgFactory](./data-schema.modelrelationshiptypeargfactory.md)<RM, [ModelRelationshipTypes.belongsTo](./data-schema.modelrelationshiptypes.md), false>, RM, "required" \| "valueRequired", undefined> diff --git a/packages/data-schema/docs/data-schema.a.combine.md b/packages/data-schema/docs/data-schema.a.combine.md index 5830eb5f1..0efdd0b5a 100644 --- a/packages/data-schema/docs/data-schema.a.combine.md +++ b/packages/data-schema/docs/data-schema.a.combine.md @@ -47,6 +47,7 @@ The schemas to combine into a single API + **Returns:** [CombinedModelSchema](./data-schema.combinedmodelschema.md)<Schema> diff --git a/packages/data-schema/docs/data-schema.a.conversation.md b/packages/data-schema/docs/data-schema.a.conversation.md index 5598c2077..2ba2345fa 100644 --- a/packages/data-schema/docs/data-schema.a.conversation.md +++ b/packages/data-schema/docs/data-schema.a.conversation.md @@ -45,6 +45,7 @@ ConversationInput + **Returns:** ConversationType diff --git a/packages/data-schema/docs/data-schema.a.customtype.md b/packages/data-schema/docs/data-schema.a.customtype.md index 02651d38a..cbf1197c4 100644 --- a/packages/data-schema/docs/data-schema.a.customtype.md +++ b/packages/data-schema/docs/data-schema.a.customtype.md @@ -49,6 +49,7 @@ the fields to be added to the custom type + **Returns:** [CustomType](./data-schema.customtype.md)<{ fields: T; }> diff --git a/packages/data-schema/docs/data-schema.a.enum.md b/packages/data-schema/docs/data-schema.a.enum.md index afd3445fe..d7616437a 100644 --- a/packages/data-schema/docs/data-schema.a.enum.md +++ b/packages/data-schema/docs/data-schema.a.enum.md @@ -45,6 +45,7 @@ values + **Returns:** [EnumType](./data-schema.enumtype.md)<values> diff --git a/packages/data-schema/docs/data-schema.a.generation.md b/packages/data-schema/docs/data-schema.a.generation.md index 6b3779cd2..13a10fb4a 100644 --- a/packages/data-schema/docs/data-schema.a.generation.md +++ b/packages/data-schema/docs/data-schema.a.generation.md @@ -52,6 +52,7 @@ GenerationInput + **Returns:** [CustomOperation](./data-schema.customoperation.md)<{ arguments: null; returnType: null; authorization: \[\]; typeName: 'Generation'; handlers: null; input: GenerationInput; }, 'for' \| 'handler', typeof generationBrand> diff --git a/packages/data-schema/docs/data-schema.a.hasmany.md b/packages/data-schema/docs/data-schema.a.hasmany.md index 666ad93a0..7dec834d2 100644 --- a/packages/data-schema/docs/data-schema.a.hasmany.md +++ b/packages/data-schema/docs/data-schema.a.hasmany.md @@ -63,6 +63,7 @@ the field(s) that should be used to reference the related model + **Returns:** [ModelRelationshipField](./data-schema.modelrelationshipfield.md)<[ModelRelationshipTypeArgFactory](./data-schema.modelrelationshiptypeargfactory.md)<RM, [ModelRelationshipTypes.hasMany](./data-schema.modelrelationshiptypes.md), true>, RM, "required", undefined> diff --git a/packages/data-schema/docs/data-schema.a.hasone.md b/packages/data-schema/docs/data-schema.a.hasone.md index cd2841690..8ffd9dfdc 100644 --- a/packages/data-schema/docs/data-schema.a.hasone.md +++ b/packages/data-schema/docs/data-schema.a.hasone.md @@ -63,6 +63,7 @@ the field(s) that should be used to reference the related model + **Returns:** [ModelRelationshipField](./data-schema.modelrelationshipfield.md)<[ModelRelationshipTypeArgFactory](./data-schema.modelrelationshiptypeargfactory.md)<RM, [ModelRelationshipTypes.hasOne](./data-schema.modelrelationshiptypes.md), false>, RM, "valueRequired", undefined> diff --git a/packages/data-schema/docs/data-schema.a.md b/packages/data-schema/docs/data-schema.a.md index 68d2d703a..2286b454a 100644 --- a/packages/data-schema/docs/data-schema.a.md +++ b/packages/data-schema/docs/data-schema.a.md @@ -357,3 +357,4 @@ Description + diff --git a/packages/data-schema/docs/data-schema.a.model.md b/packages/data-schema/docs/data-schema.a.model.md index 78c1fb43d..50df7124e 100644 --- a/packages/data-schema/docs/data-schema.a.model.md +++ b/packages/data-schema/docs/data-schema.a.model.md @@ -53,6 +53,7 @@ database table fields. Supports scalar types and relationship types. + **Returns:** [ModelType](./data-schema.modeltype.md)<{ fields: T; identifier: [ModelDefaultIdentifier](./data-schema.modeldefaultidentifier.md); secondaryIndexes: \[\]; authorization: \[\]; disabledOperations: \[\]; }> diff --git a/packages/data-schema/docs/data-schema.a.ref.md b/packages/data-schema/docs/data-schema.a.ref.md index 521c10315..0e27e256b 100644 --- a/packages/data-schema/docs/data-schema.a.ref.md +++ b/packages/data-schema/docs/data-schema.a.ref.md @@ -43,6 +43,7 @@ T + **Returns:** [RefType](./data-schema.reftype.md)<RefTypeArgFactory<T>, never, undefined> diff --git a/packages/data-schema/docs/data-schema.a.schema.md b/packages/data-schema/docs/data-schema.a.schema.md index e3be75c7b..cda92b26e 100644 --- a/packages/data-schema/docs/data-schema.a.schema.md +++ b/packages/data-schema/docs/data-schema.a.schema.md @@ -51,6 +51,7 @@ The API and data model definition + **Returns:** [ModelSchema](./data-schema.modelschema.md)<{ types: Types; authorization: \[\]; configuration: any; }, never> diff --git a/packages/data-schema/docs/data-schema.enumtype.md b/packages/data-schema/docs/data-schema.enumtype.md index 57045d146..dc3b7af01 100644 --- a/packages/data-schema/docs/data-schema.enumtype.md +++ b/packages/data-schema/docs/data-schema.enumtype.md @@ -54,3 +54,4 @@ Description + diff --git a/packages/data-schema/docs/data-schema.md b/packages/data-schema/docs/data-schema.md index 703f1fb40..4dce2fd52 100644 --- a/packages/data-schema/docs/data-schema.md +++ b/packages/data-schema/docs/data-schema.md @@ -277,3 +277,4 @@ Container for representing the authorization of function resources + diff --git a/packages/data-schema/docs/data-schema.modelfieldtype.md b/packages/data-schema/docs/data-schema.modelfieldtype.md index 532e509a9..f3974d463 100644 --- a/packages/data-schema/docs/data-schema.modelfieldtype.md +++ b/packages/data-schema/docs/data-schema.modelfieldtype.md @@ -225,3 +225,4 @@ Url + diff --git a/packages/data-schema/docs/data-schema.modelrelationshiptypes.md b/packages/data-schema/docs/data-schema.modelrelationshiptypes.md index 95c3bda08..5f0e7d90b 100644 --- a/packages/data-schema/docs/data-schema.modelrelationshiptypes.md +++ b/packages/data-schema/docs/data-schema.modelrelationshiptypes.md @@ -73,3 +73,4 @@ hasOne + diff --git a/packages/data-schema/docs/index.md b/packages/data-schema/docs/index.md index 944d57f8f..5f8361f8c 100644 --- a/packages/data-schema/docs/index.md +++ b/packages/data-schema/docs/index.md @@ -27,3 +27,4 @@ Description + diff --git a/packages/data-schema/src/SchemaProcessor.ts b/packages/data-schema/src/SchemaProcessor.ts index 5e6f53131..23da566b0 100644 --- a/packages/data-schema/src/SchemaProcessor.ts +++ b/packages/data-schema/src/SchemaProcessor.ts @@ -1391,7 +1391,13 @@ function generateInputTypes( if (refType.type === 'CustomType') { const nestedInputTypeName = `${fieldDef.data.link}Input`; processedFields[fieldName] = { - data: { type: 'ref', link: nestedInputTypeName }, + data: { + type: 'ref', + link: nestedInputTypeName, + array: fieldDef.data.array, + arrayRequired: fieldDef.data.arrayRequired, + valueRequired: fieldDef.data.valueRequired + }, }; // Process the nested type if it hasn't been processed and isn't a circular reference @@ -1425,7 +1431,13 @@ function generateInputTypes( // Handle inline custom types const nestedInputTypeName = `${capitalize(originalTypeName)}${capitalize(fieldName)}Input`; processedFields[fieldName] = { - data: { type: 'ref', link: nestedInputTypeName }, + data: { + type: 'ref', + link: nestedInputTypeName, + array: false, + arrayRequired: false, + valueRequired: false + }, }; if (!processedTypes.has(nestedInputTypeName)) {