Skip to content

Commit abae276

Browse files
committed
chore: refactor getprimarykeyfields method; add e2e test
1 parent 6920c86 commit abae276

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
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: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,17 @@ 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, throws meaningful error otherwise.
30+
* @param model Codegen Model object
31+
* @returns Array of primary and sort key codegen fields
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+
if (primaryKeyField && primaryKeyField?.primaryKeyInfo) {
36+
const { sortKeyFields } = primaryKeyField.primaryKeyInfo;
37+
return [ primaryKeyField, ...sortKeyFields ];
38+
}
39+
40+
throw new Error(`Unable to get the primary key component fields for model ${model?.name}`);
3241
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,8 @@ export class AppSyncModelVisitor<
10221022
}
10231023
} else {
10241024
Object.values(this.modelMap).forEach(model => {
1025+
const primaryKeyFields = getModelPrimaryKeyComponentFields(model);
1026+
const primaryKeyName = (primaryKeyFields?.length > 0) ? this.getFieldName(primaryKeyFields[0]) : undefined;
10251027
model.fields.forEach(field => {
10261028
const connectionInfo = field.connectionInfo;
10271029
if (
@@ -1030,7 +1032,7 @@ export class AppSyncModelVisitor<
10301032
connectionInfo.kind !== CodeGenConnectionType.HAS_ONE &&
10311033
connectionInfo.targetName !== 'id' &&
10321034
!(this.config.target === 'introspection' &&
1033-
this.getFieldName(getModelPrimaryKeyComponentFields(model)[0]) === connectionInfo.targetName)
1035+
primaryKeyName && primaryKeyName === connectionInfo.targetName)
10341036
) {
10351037
// Need to remove the field that is targetName
10361038
removeFieldFromModel(model, connectionInfo.targetName);

0 commit comments

Comments
 (0)