Skip to content

Commit 5c6c91c

Browse files
authored
fix(modelgen-js): use optional fields for FK in manyToMany (#462)
1 parent 522fb23 commit 5c6c91c

File tree

4 files changed

+87
-6
lines changed

4 files changed

+87
-6
lines changed

packages/appsync-modelgen-plugin/src/__tests__/visitors/__snapshots__/appsync-javascript-visitor.test.ts.snap

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,58 @@ export declare class Team {
114114
static copyOf(source: Team, mutator: (draft: MutableModel<Team>) => MutableModel<Team> | void): Team;
115115
}"
116116
`;
117+
118+
exports[`Javascript visitor with connected models of custom pk manyToMany relation should generate correct declaration for manyToMany model when custom pk is enabled 1`] = `
119+
"import { ModelInit, MutableModel, __modelMeta__, CompositeIdentifier, ManagedIdentifier } from \\"@aws-amplify/datastore\\";
120+
121+
122+
123+
124+
125+
export declare class Post {
126+
readonly [__modelMeta__]: {
127+
identifier: CompositeIdentifier<Post, ['customPostId', 'title']>;
128+
readOnlyFields: 'createdAt' | 'updatedAt';
129+
};
130+
readonly customPostId: string;
131+
readonly title: string;
132+
readonly content?: string | null;
133+
readonly tags?: (PostTags | null)[] | null;
134+
readonly createdAt?: string | null;
135+
readonly updatedAt?: string | null;
136+
constructor(init: ModelInit<Post>);
137+
static copyOf(source: Post, mutator: (draft: MutableModel<Post>) => MutableModel<Post> | void): Post;
138+
}
139+
140+
export declare class Tag {
141+
readonly [__modelMeta__]: {
142+
identifier: CompositeIdentifier<Tag, ['customTagId', 'label']>;
143+
readOnlyFields: 'createdAt' | 'updatedAt';
144+
};
145+
readonly customTagId: string;
146+
readonly label: string;
147+
readonly posts?: (PostTags | null)[] | null;
148+
readonly createdAt?: string | null;
149+
readonly updatedAt?: string | null;
150+
constructor(init: ModelInit<Tag>);
151+
static copyOf(source: Tag, mutator: (draft: MutableModel<Tag>) => MutableModel<Tag> | void): Tag;
152+
}
153+
154+
export declare class PostTags {
155+
readonly [__modelMeta__]: {
156+
identifier: ManagedIdentifier<PostTags, 'id'>;
157+
readOnlyFields: 'createdAt' | 'updatedAt';
158+
};
159+
readonly id: string;
160+
readonly postCustomPostId?: string | null;
161+
readonly posttitle?: string | null;
162+
readonly tagCustomTagId?: string | null;
163+
readonly taglabel?: string | null;
164+
readonly post: Post;
165+
readonly tag: Tag;
166+
readonly createdAt?: string | null;
167+
readonly updatedAt?: string | null;
168+
constructor(init: ModelInit<PostTags>);
169+
static copyOf(source: PostTags, mutator: (draft: MutableModel<PostTags>) => MutableModel<PostTags> | void): PostTags;
170+
}"
171+
`;

packages/appsync-modelgen-plugin/src/__tests__/visitors/appsync-javascript-visitor.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,4 +885,30 @@ describe('Javascript visitor with connected models of custom pk', () => {
885885
expect(declarations).toMatchSnapshot();
886886
});
887887
});
888+
describe('manyToMany relation', () => {
889+
it('should generate correct declaration for manyToMany model when custom pk is enabled', () => {
890+
const schema = /* GraphQL */ `
891+
type Post @model {
892+
customPostId: ID! @primaryKey(sortKeyFields: ["title"])
893+
title: String!
894+
content: String
895+
tags: [Tag] @manyToMany(relationName: "PostTags")
896+
}
897+
type Tag @model {
898+
customTagId: ID! @primaryKey(sortKeyFields: ["label"])
899+
label: String!
900+
posts: [Post] @manyToMany(relationName: "PostTags")
901+
}
902+
`;
903+
const visitor = getVisitor(schema, {
904+
isDeclaration: true,
905+
isTimestampFieldsAdded: true,
906+
respectPrimaryKeyAttributesOnConnectionField: true,
907+
transformerVersion: 2,
908+
});
909+
const declarations = visitor.generate();
910+
validateTs(declarations);
911+
expect(declarations).toMatchSnapshot();
912+
});
913+
});
888914
});

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,11 +953,11 @@ describe('AppSyncModelVisitor', () => {
953953
const modelASortKeyField = ModelAModelB.fields.find(f => f.name === 'modelAsortId')!;
954954
expect(modelASortKeyField).toBeDefined();
955955
expect(modelASortKeyField.type).toEqual('ID');
956-
expect(modelASortKeyField.isNullable).toBe(false);
956+
expect(modelASortKeyField.isNullable).toBe(true);
957957
const modelBSortKeyField = ModelAModelB.fields.find(f => f.name === 'modelBsortId')!;
958958
expect(modelBSortKeyField).toBeDefined();
959959
expect(modelBSortKeyField.type).toEqual('ID');
960-
expect(modelBSortKeyField.isNullable).toBe(false);
960+
expect(modelBSortKeyField.isNullable).toBe(true);
961961
const modelAIndexDirective = ModelAModelB.directives.find(d => d.name === 'key' && d.arguments.name === 'byModelA')!;
962962
expect(modelAIndexDirective).toBeDefined();
963963
expect(modelAIndexDirective.arguments.fields).toEqual(['modelACustomId', 'modelAsortId']);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ export class AppSyncModelVisitor<
682682
},
683683
{
684684
type: 'ID',
685-
isNullable: false,
685+
isNullable: true,
686686
isList: false,
687687
name: firstModelKeyFieldName,
688688
directives: [
@@ -698,15 +698,15 @@ export class AppSyncModelVisitor<
698698
...firstModelSortKeyFields.map(field => {
699699
return {
700700
type: field.type,
701-
isNullable: false,
701+
isNullable: true,
702702
isList: field.isList,
703703
name: this.generateIntermediateModelSortKeyFieldName(firstModel, field),
704704
directives: [],
705705
};
706706
}),
707707
{
708708
type: 'ID',
709-
isNullable: false,
709+
isNullable: true,
710710
isList: false,
711711
name: secondModelKeyFieldName,
712712
directives: [
@@ -722,7 +722,7 @@ export class AppSyncModelVisitor<
722722
...secondModelSortKeyFields.map(field => {
723723
return {
724724
type: field.type,
725-
isNullable: false,
725+
isNullable: true,
726726
isList: field.isList,
727727
name: this.generateIntermediateModelSortKeyFieldName(secondModel, field),
728728
directives: [],

0 commit comments

Comments
 (0)