Skip to content

Commit ae59731

Browse files
authored
fix: schema processor to preserve array type for custom types (#629)
1 parent 405447e commit ae59731

File tree

4 files changed

+222
-4
lines changed

4 files changed

+222
-4
lines changed

.changeset/happy-apes-count.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@aws-amplify/data-schema': minor
3+
---
4+
5+
fix: array fields within custom types lose their array structure when generating input types

packages/data-schema/__tests__/ModelSchema.test.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,110 @@ describe('custom operation argument inputs', () => {
408408
expect(schema.transform().schema).toMatchSnapshot();
409409
});
410410

411-
})
411+
});
412+
413+
describe('nested array fields in custom types', () => {
414+
415+
it('when a custom type has an array ref field the input type preserves the array', () => {
416+
const fn1 = defineFunctionStub({});
417+
418+
const schema = a
419+
.schema({
420+
testType: a.customType({
421+
testField: a.string().required(),
422+
}),
423+
424+
containerType: a.customType({
425+
items: a.ref('testType').array(),
426+
}),
427+
428+
testMutation: a
429+
.mutation()
430+
.arguments({
431+
container: a.ref('containerType'),
432+
})
433+
.returns(a.string())
434+
.handler(a.handler.function(fn1))
435+
})
436+
.authorization((allow) => allow.owner());
437+
438+
expect(schema.transform().schema).toMatchSnapshot();
439+
});
440+
441+
it('when a custom type has a required array ref field the input type is a required array', () => {
442+
const fn1 = defineFunctionStub({});
443+
444+
const schema = a
445+
.schema({
446+
testType: a.customType({
447+
testField: a.string().required(),
448+
}),
449+
450+
containerType: a.customType({
451+
items: a.ref('testType').array().required(),
452+
}),
453+
454+
testMutation: a
455+
.mutation()
456+
.arguments({
457+
container: a.ref('containerType'),
458+
})
459+
.returns(a.string())
460+
.handler(a.handler.function(fn1))
461+
})
462+
.authorization((allow) => allow.owner());
463+
464+
expect(schema.transform().schema).toMatchSnapshot();
465+
});
466+
467+
it('when a custom type has an array of required ref fields the input type is an array of required refs', () => {
468+
const fn1 = defineFunctionStub({});
469+
470+
const schema = a
471+
.schema({
472+
testType: a.customType({
473+
testField: a.string().required(),
474+
}),
475+
476+
containerType: a.customType({
477+
items: a.ref('testType').required().array(),
478+
}),
479+
480+
testMutation: a
481+
.mutation()
482+
.arguments({
483+
container: a.ref('containerType'),
484+
})
485+
.returns(a.string())
486+
.handler(a.handler.function(fn1))
487+
})
488+
.authorization((allow) => allow.owner());
489+
490+
expect(schema.transform().schema).toMatchSnapshot();
491+
});
492+
493+
it('when a custom type has an array enum ref field the input type preserves the array', () => {
494+
const fn1 = defineFunctionStub({});
495+
496+
const schema = a
497+
.schema({
498+
testEnum: a.enum(['VALUE1', 'VALUE2']),
499+
500+
containerType: a.customType({
501+
statuses: a.ref('testEnum').array(),
502+
}),
503+
504+
testMutation: a
505+
.mutation()
506+
.arguments({
507+
container: a.ref('containerType'),
508+
})
509+
.returns(a.string())
510+
.handler(a.handler.function(fn1))
511+
})
512+
.authorization((allow) => allow.owner());
513+
514+
expect(schema.transform().schema).toMatchSnapshot();
515+
});
516+
517+
});

packages/data-schema/__tests__/__snapshots__/ModelSchema.test.ts.snap

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,95 @@ exports[`empty model auth inherits global auth 1`] = `
167167
someOwnerField: String
168168
}"
169169
`;
170+
171+
exports[`nested array fields in custom types when a custom type has a required array ref field the input type is a required array 1`] = `
172+
"type testType
173+
{
174+
testField: String!
175+
}
176+
177+
type containerType
178+
{
179+
items: [testType]!
180+
}
181+
182+
input testTypeInput {
183+
testField: String!
184+
}
185+
186+
input containerTypeInput {
187+
items: [testTypeInput]!
188+
}
189+
190+
type Mutation {
191+
testMutation(container: containerTypeInput): String @function(name: "FnTestMutation") @auth(rules: [{allow: owner, ownerField: "owner"}])
192+
}"
193+
`;
194+
195+
exports[`nested array fields in custom types when a custom type has an array enum ref field the input type preserves the array 1`] = `
196+
"enum testEnum {
197+
VALUE1
198+
VALUE2
199+
}
200+
201+
type containerType
202+
{
203+
statuses: [testEnum]
204+
}
205+
206+
input containerTypeInput {
207+
statuses: [testEnum]
208+
}
209+
210+
type Mutation {
211+
testMutation(container: containerTypeInput): String @function(name: "FnTestMutation") @auth(rules: [{allow: owner, ownerField: "owner"}])
212+
}"
213+
`;
214+
215+
exports[`nested array fields in custom types when a custom type has an array of required ref fields the input type is an array of required refs 1`] = `
216+
"type testType
217+
{
218+
testField: String!
219+
}
220+
221+
type containerType
222+
{
223+
items: [testType!]
224+
}
225+
226+
input testTypeInput {
227+
testField: String!
228+
}
229+
230+
input containerTypeInput {
231+
items: [testTypeInput!]
232+
}
233+
234+
type Mutation {
235+
testMutation(container: containerTypeInput): String @function(name: "FnTestMutation") @auth(rules: [{allow: owner, ownerField: "owner"}])
236+
}"
237+
`;
238+
239+
exports[`nested array fields in custom types when a custom type has an array ref field the input type preserves the array 1`] = `
240+
"type testType
241+
{
242+
testField: String!
243+
}
244+
245+
type containerType
246+
{
247+
items: [testType]
248+
}
249+
250+
input testTypeInput {
251+
testField: String!
252+
}
253+
254+
input containerTypeInput {
255+
items: [testTypeInput]
256+
}
257+
258+
type Mutation {
259+
testMutation(container: containerTypeInput): String @function(name: "FnTestMutation") @auth(rules: [{allow: owner, ownerField: "owner"}])
260+
}"
261+
`;

packages/data-schema/src/SchemaProcessor.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,13 @@ function generateInputTypes(
13911391
if (refType.type === 'CustomType') {
13921392
const nestedInputTypeName = `${fieldDef.data.link}Input`;
13931393
processedFields[fieldName] = {
1394-
data: { type: 'ref', link: nestedInputTypeName },
1394+
data: {
1395+
type: 'ref',
1396+
link: nestedInputTypeName,
1397+
array: fieldDef.data.array,
1398+
arrayRequired: fieldDef.data.arrayRequired,
1399+
valueRequired: fieldDef.data.valueRequired
1400+
},
13951401
};
13961402

13971403
// Process the nested type if it hasn't been processed and isn't a circular reference
@@ -1413,7 +1419,13 @@ function generateInputTypes(
14131419
}
14141420
} else if (refType.type === 'Enum') {
14151421
processedFields[fieldName] = {
1416-
data: { type: 'ref', link: fieldDef.data.link },
1422+
data: {
1423+
type: 'ref',
1424+
link: fieldDef.data.link,
1425+
array: fieldDef.data.array,
1426+
arrayRequired: fieldDef.data.arrayRequired,
1427+
valueRequired: fieldDef.data.valueRequired
1428+
},
14171429
};
14181430
} else {
14191431
throw new Error(
@@ -1425,7 +1437,10 @@ function generateInputTypes(
14251437
// Handle inline custom types
14261438
const nestedInputTypeName = `${capitalize(originalTypeName)}${capitalize(fieldName)}Input`;
14271439
processedFields[fieldName] = {
1428-
data: { type: 'ref', link: nestedInputTypeName },
1440+
data: {
1441+
type: 'ref',
1442+
link: nestedInputTypeName
1443+
},
14291444
};
14301445

14311446
if (!processedTypes.has(nestedInputTypeName)) {

0 commit comments

Comments
 (0)