Skip to content

Commit 2a3f392

Browse files
authored
Merge pull request #573 from aws-amplify/add-e2e-test-codegen
Refactor the `getPrimaryKeyComponentFields` method
2 parents 6920c86 + 0bbc320 commit 2a3f392

File tree

4 files changed

+64
-20
lines changed

4 files changed

+64
-20
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type Post @model {
2+
postId: ID! @primaryKey
3+
node: PostNode! @belongsTo(fields: ["postId"])
4+
title: String!
5+
}
6+
7+
type PostNode @model {
8+
id: ID!
9+
post: Post! @hasOne
10+
}

packages/amplify-codegen-e2e-tests/src/__tests__/model-introspection-codegen.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('Model Introspection Codegen test', () => {
2828
// Model introspection is generated at correct location
2929
expect(isNotEmptyDir(join(projectRoot, outputDir))).toBe(true);
3030
});
31+
3132
it('should throw error when the output directory is not defined in the command', async () => {
3233
// init project and add API category
3334
await initJSProjectWithProfile(projectRoot);
@@ -36,6 +37,7 @@ describe('Model Introspection Codegen test', () => {
3637
//generate introspection schema
3738
await expect(generateModelIntrospection(projectRoot)).rejects.toThrowError();
3839
});
40+
3941
it('should throw error if the GraphQL schema is invalid', async () => {
4042
const invalidSchema = 'modelgen/model_gen_schema_with_errors.graphql';
4143
// init project and add API category
@@ -46,5 +48,20 @@ describe('Model Introspection Codegen test', () => {
4648
//generate introspection schema
4749
await expect(generateModelIntrospection(projectRoot, { outputDir })).rejects.toThrowError();
4850
});
51+
52+
it(`should handle a schema with connected PK`, async () => {
53+
const schemaName = 'modelgen/schema_with_connected_pk.graphql';
54+
55+
// init project and add API category
56+
await initJSProjectWithProfile(projectRoot);
57+
await addApiWithoutSchema(projectRoot, { apiName });
58+
await updateApiSchema(projectRoot, apiName, schemaName);
59+
60+
const outputDir = 'output';
61+
//generate introspection schema
62+
await expect(generateModelIntrospection(projectRoot, { outputDir })).resolves.not.toThrow();
63+
// Model introspection is generated at correct location
64+
expect(isNotEmptyDir(join(projectRoot, outputDir))).toBe(true);
65+
});
4966
});
5067

packages/appsync-modelgen-plugin/src/utils/fieldUtils.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,19 @@ export function getOtherSideBelongsToField(type: string, otherSideModel: CodeGen
2525
return otherSideModel.fields.filter(f => f.type === type).find(f => f.directives.find(d => d.name === TransformerV2DirectiveName.BELONGS_TO));
2626
}
2727

28+
/**
29+
* Given a model, it returns the primary and sort key fields if present, an empty list otherwise.
30+
* @param model Codegen Model object
31+
* @returns Array of primary and sort key codegen fields if present or an empty list
32+
*/
2833
export function getModelPrimaryKeyComponentFields(model: CodeGenModel): CodeGenField[] {
29-
const primaryKeyField = model.fields.find(field => field.primaryKeyInfo)!;
30-
const { sortKeyFields } = primaryKeyField.primaryKeyInfo!;
31-
return [ primaryKeyField, ...sortKeyFields ];
34+
const primaryKeyField = model.fields.find(field => field.primaryKeyInfo);
35+
const keyFields: CodeGenField[] = [];
36+
if (primaryKeyField) {
37+
keyFields.push(primaryKeyField);
38+
if ( primaryKeyField?.primaryKeyInfo?.sortKeyFields ) {
39+
keyFields.push(...primaryKeyField.primaryKeyInfo.sortKeyFields);
40+
};
41+
}
42+
return keyFields;
3243
}

packages/appsync-modelgen-plugin/src/visitors/appsync-visitor.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -941,15 +941,17 @@ export class AppSyncModelVisitor<
941941
} else if (connectionInfo.kind === CodeGenConnectionType.HAS_ONE) {
942942
if (isCustomPKEnabled) {
943943
const connectedModelFields = getModelPrimaryKeyComponentFields(connectionInfo.connectedModel);
944-
connectionInfo.targetNames.forEach((target, index) => {
945-
addFieldToModel(model, {
946-
name: target,
947-
directives: [],
948-
type: connectedModelFields[index].type,
949-
isList: false,
950-
isNullable: field.isNullable,
944+
if (connectedModelFields?.length > 0) {
945+
connectionInfo.targetNames.forEach((target, index) => {
946+
addFieldToModel(model, {
947+
name: target,
948+
directives: [],
949+
type: connectedModelFields[index].type,
950+
isList: false,
951+
isNullable: field.isNullable,
952+
});
951953
});
952-
});
954+
}
953955
} else {
954956
addFieldToModel(model, {
955957
name: connectionInfo.targetName,
@@ -962,15 +964,17 @@ export class AppSyncModelVisitor<
962964
} else if (connectionInfo.kind === CodeGenConnectionType.BELONGS_TO) {
963965
if (isCustomPKEnabled) {
964966
const connectedModelFields = getModelPrimaryKeyComponentFields(connectionInfo.connectedModel);
965-
connectionInfo.targetNames.forEach((target, index) => {
966-
addFieldToModel(model, {
967-
name: target,
968-
directives: [],
969-
type: connectedModelFields[index].type,
970-
isList: false,
971-
isNullable: field.isNullable,
967+
if (connectedModelFields?.length > 0) {
968+
connectionInfo.targetNames.forEach((target, index) => {
969+
addFieldToModel(model, {
970+
name: target,
971+
directives: [],
972+
type: connectedModelFields[index].type,
973+
isList: false,
974+
isNullable: field.isNullable,
975+
});
972976
});
973-
});
977+
}
974978
} else {
975979
addFieldToModel(model, {
976980
name: connectionInfo.targetName,
@@ -1022,6 +1026,8 @@ export class AppSyncModelVisitor<
10221026
}
10231027
} else {
10241028
Object.values(this.modelMap).forEach(model => {
1029+
const primaryKeyFields = getModelPrimaryKeyComponentFields(model);
1030+
const primaryKeyName = (primaryKeyFields?.length > 0) ? this.getFieldName(primaryKeyFields[0]) : undefined;
10251031
model.fields.forEach(field => {
10261032
const connectionInfo = field.connectionInfo;
10271033
if (
@@ -1030,7 +1036,7 @@ export class AppSyncModelVisitor<
10301036
connectionInfo.kind !== CodeGenConnectionType.HAS_ONE &&
10311037
connectionInfo.targetName !== 'id' &&
10321038
!(this.config.target === 'introspection' &&
1033-
this.getFieldName(getModelPrimaryKeyComponentFields(model)[0]) === connectionInfo.targetName)
1039+
primaryKeyName && primaryKeyName === connectionInfo.targetName)
10341040
) {
10351041
// Need to remove the field that is targetName
10361042
removeFieldFromModel(model, connectionInfo.targetName);

0 commit comments

Comments
 (0)