Skip to content

Commit 7d1a269

Browse files
authored
feat: add angular codegen v6 support (#799)
* feat: add angular codegen v6 support * feat: add codegen target angularv6 * add unit tests * fix unit test * fix e2e * fix: remove angularv6 target and use amplifyJsLibaryVersion * default behavior set to 6 when invalid * add unit test for invalid input * add amplifyJsLibraryVersion tests
1 parent a94649e commit 7d1a269

File tree

14 files changed

+867
-23
lines changed

14 files changed

+867
-23
lines changed

packages/amplify-codegen/src/commands/add.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ async function add(context, apiId = null, region = 'us-east-1') {
145145
apiId,
146146
...(withoutInit ? { frontend } : {}),
147147
...(withoutInit && frontend === 'javascript' ? { framework } : {}),
148+
// The default Amplify JS lib version is set for 6 for angular codegen
149+
...(answer.target === 'angular' ? { amplifyJsLibraryVersion: 6 } : {}),
148150
},
149151
};
150152

packages/amplify-codegen/src/commands/types.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ async function generateTypes(context, forceDownloadSchema, withoutInit = false,
5858
}
5959
const target = cfg.amplifyExtension.codeGenTarget;
6060

61+
let amplifyJsLibraryVersion = cfg.amplifyExtension.amplifyJsLibraryVersion;
62+
63+
/**
64+
* amplifyJsLibraryVersion config is currently used for angular codegen
65+
* The supported value is 5 for JS v5 and 6 for JS v6
66+
* When the value is undefined, it will stay at codegen for JS v5 for non-breaking change for existing users
67+
* For the other values set, a warning message will be sent in the console and the codegen will use the v6 codegen
68+
*/
69+
if (target === 'angular' && amplifyJsLibraryVersion && amplifyJsLibraryVersion !== 6 && amplifyJsLibraryVersion !== 5) {
70+
context.print.warning(
71+
`Amplify JS library version ${amplifyJsLibraryVersion} is not supported. The current support JS library version is [5, 6]. Codegen will be executed for JS v6 instead.`,
72+
);
73+
amplifyJsLibraryVersion = 6
74+
}
75+
6176
const excludes = cfg.excludes.map(pattern => `!${pattern}`);
6277
const normalizedPatterns = [...includeFiles, ...excludes].map((path) => normalizePathForGlobPattern(path));
6378
const queryFilePaths = globby.sync(normalizedPatterns, {
@@ -114,6 +129,7 @@ async function generateTypes(context, forceDownloadSchema, withoutInit = false,
114129
target,
115130
introspection,
116131
multipleSwiftFiles,
132+
amplifyJsLibraryVersion,
117133
});
118134
const outputs = Object.entries(output);
119135

packages/amplify-codegen/src/walkthrough/questions/languageTarget.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ async function askCodeGenTargetLanguage(context, target, withoutInit = false, de
4343
default: target || null,
4444
},
4545
]);
46+
4647
return answer.target;
4748
}
4849

packages/amplify-codegen/tests/commands/types.test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const { ensureIntrospectionSchema, getFrontEndHandler, getAppSyncAPIDetails } =
1212
const MOCK_CONTEXT = {
1313
print: {
1414
info: jest.fn(),
15+
warning: jest.fn(),
1516
},
1617
amplify: {
1718
getEnvInfo: jest.fn(),
@@ -56,6 +57,19 @@ const MOCK_APIS = [
5657

5758
getFrontEndHandler.mockReturnValue('javascript');
5859

60+
const MOCK_ANGULAR_PROJECT_BASE = {
61+
excludes: [MOCK_EXCLUDE_PATH],
62+
includes: [MOCK_INCLUDE_PATH],
63+
schema: MOCK_SCHEMA,
64+
amplifyExtension: {
65+
generatedFileName: MOCK_GENERATED_FILE_NAME,
66+
codeGenTarget: 'angular',
67+
graphQLApiId: MOCK_API_ID,
68+
region: MOCK_REGION,
69+
amplifyJsLibraryVersion: 5,
70+
},
71+
};
72+
5973
describe('command - types', () => {
6074
beforeEach(() => {
6175
jest.clearAllMocks();
@@ -163,4 +177,30 @@ describe('command - types', () => {
163177
expect(generateTypesHelper).not.toHaveBeenCalled();
164178
expect(globby.sync).not.toHaveBeenCalled();
165179
});
180+
181+
it('should show a warning if the amplifyJsLibraryVersion is invalid', async () => {
182+
const MOCK_ANGULAR_PROJECT = {
183+
...MOCK_ANGULAR_PROJECT_BASE
184+
};
185+
MOCK_ANGULAR_PROJECT.amplifyExtension.amplifyJsLibraryVersion = 7
186+
fs.readFileSync
187+
.mockReturnValueOnce('query 1')
188+
.mockReturnValueOnce('query 2')
189+
.mockReturnValueOnce('schema');
190+
loadConfig.mockReturnValue({
191+
getProjects: jest.fn().mockReturnValue([MOCK_ANGULAR_PROJECT]),
192+
});
193+
await generateTypes(MOCK_CONTEXT, false);
194+
expect(MOCK_CONTEXT.print.warning).toHaveBeenCalledWith(
195+
'Amplify JS library version 7 is not supported. The current support JS library version is [5, 6]. Codegen will be executed for JS v6 instead.'
196+
);
197+
expect(generateTypesHelper).toHaveBeenCalledWith({
198+
queries: [new Source('query 1', 'q1.gql'), new Source('query 2', 'q2.gql')],
199+
schema: 'schema',
200+
target: 'angular',
201+
introspection: false,
202+
multipleSwiftFiles: false,
203+
amplifyJsLibraryVersion: 6,
204+
});
205+
});
166206
});

packages/graphql-generator/API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export type GenerateTypesOptions = {
5555
queries: string | Source[];
5656
introspection?: boolean;
5757
multipleSwiftFiles?: boolean;
58+
amplifyJsLibraryVersion?: number;
5859
};
5960

6061
// @public (undocumented)

packages/graphql-generator/src/__tests__/__snapshots__/types.test.ts.snap

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,202 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`generateTypes amplifyJsLibraryVersion generates angular types for v5 when value is 5 or undefined 1`] = `
4+
Object {
5+
"api.service.ts": "/* tslint:disable */
6+
/* eslint-disable */
7+
// This file was automatically generated and should not be edited.
8+
import { Injectable } from \\"@angular/core\\";
9+
import API, { graphqlOperation, GraphQLResult } from \\"@aws-amplify/api-graphql\\";
10+
import { Observable } from \\"zen-observable-ts\\";
11+
12+
export interface SubscriptionResponse<T> {
13+
value: GraphQLResult<T>;
14+
}
15+
16+
export type Blog = {
17+
__typename: \\"Blog\\";
18+
id: string;
19+
name: string;
20+
posts?: ModelPostConnection | null;
21+
createdAt: string;
22+
updatedAt: string;
23+
};
24+
25+
export type ModelPostConnection = {
26+
__typename: \\"ModelPostConnection\\";
27+
items: Array<Post | null>;
28+
nextToken?: string | null;
29+
};
30+
31+
export type Post = {
32+
__typename: \\"Post\\";
33+
id: string;
34+
title: string;
35+
blog?: Blog | null;
36+
comments?: ModelCommentConnection | null;
37+
createdAt: string;
38+
updatedAt: string;
39+
blogPostsId?: string | null;
40+
};
41+
42+
export type ModelCommentConnection = {
43+
__typename: \\"ModelCommentConnection\\";
44+
items: Array<Comment | null>;
45+
nextToken?: string | null;
46+
};
47+
48+
export type Comment = {
49+
__typename: \\"Comment\\";
50+
id: string;
51+
post?: Post | null;
52+
content: string;
53+
createdAt: string;
54+
updatedAt: string;
55+
postCommentsId?: string | null;
56+
};
57+
58+
export type GetBlogQuery = {
59+
__typename: \\"Blog\\";
60+
id: string;
61+
name: string;
62+
posts?: {
63+
__typename: \\"ModelPostConnection\\";
64+
nextToken?: string | null;
65+
} | null;
66+
createdAt: string;
67+
updatedAt: string;
68+
};
69+
70+
@Injectable({
71+
providedIn: \\"root\\"
72+
})
73+
export class APIService {
74+
async GetBlog(id: string): Promise<GetBlogQuery> {
75+
const statement = \`query GetBlog($id: ID!) {
76+
getBlog(id: $id) {
77+
__typename
78+
id
79+
name
80+
posts {
81+
__typename
82+
nextToken
83+
}
84+
createdAt
85+
updatedAt
86+
}
87+
}\`;
88+
const gqlAPIServiceArguments: any = {
89+
id
90+
};
91+
const response = (await API.graphql(
92+
graphqlOperation(statement, gqlAPIServiceArguments)
93+
)) as any;
94+
return <GetBlogQuery>response.data.getBlog;
95+
}
96+
}
97+
",
98+
}
99+
`;
100+
101+
exports[`generateTypes amplifyJsLibraryVersion generates angular types for v6 when value is 6 1`] = `
102+
Object {
103+
"api.service.ts": "/* tslint:disable */
104+
/* eslint-disable */
105+
// This file was automatically generated and should not be edited.
106+
import { Injectable } from \\"@angular/core\\";
107+
import { Client, generateClient, GraphQLResult } from \\"aws-amplify/api\\";
108+
import { Observable } from \\"rxjs\\";
109+
110+
export type Blog = {
111+
__typename: \\"Blog\\";
112+
id: string;
113+
name: string;
114+
posts?: ModelPostConnection | null;
115+
createdAt: string;
116+
updatedAt: string;
117+
};
118+
119+
export type ModelPostConnection = {
120+
__typename: \\"ModelPostConnection\\";
121+
items: Array<Post | null>;
122+
nextToken?: string | null;
123+
};
124+
125+
export type Post = {
126+
__typename: \\"Post\\";
127+
id: string;
128+
title: string;
129+
blog?: Blog | null;
130+
comments?: ModelCommentConnection | null;
131+
createdAt: string;
132+
updatedAt: string;
133+
blogPostsId?: string | null;
134+
};
135+
136+
export type ModelCommentConnection = {
137+
__typename: \\"ModelCommentConnection\\";
138+
items: Array<Comment | null>;
139+
nextToken?: string | null;
140+
};
141+
142+
export type Comment = {
143+
__typename: \\"Comment\\";
144+
id: string;
145+
post?: Post | null;
146+
content: string;
147+
createdAt: string;
148+
updatedAt: string;
149+
postCommentsId?: string | null;
150+
};
151+
152+
export type GetBlogQuery = {
153+
__typename: \\"Blog\\";
154+
id: string;
155+
name: string;
156+
posts?: {
157+
__typename: \\"ModelPostConnection\\";
158+
nextToken?: string | null;
159+
} | null;
160+
createdAt: string;
161+
updatedAt: string;
162+
};
163+
164+
@Injectable({
165+
providedIn: \\"root\\"
166+
})
167+
export class APIService {
168+
public client: Client;
169+
constructor() {
170+
this.client = generateClient();
171+
}
172+
async GetBlog(id: string): Promise<GetBlogQuery> {
173+
const statement = \`query GetBlog($id: ID!) {
174+
getBlog(id: $id) {
175+
__typename
176+
id
177+
name
178+
posts {
179+
__typename
180+
nextToken
181+
}
182+
createdAt
183+
updatedAt
184+
}
185+
}\`;
186+
const gqlAPIServiceArguments: any = {
187+
id
188+
};
189+
const response = (await this.client.graphql({
190+
query: statement,
191+
variables: gqlAPIServiceArguments
192+
})) as any;
193+
return <GetBlogQuery>response.data.getBlog;
194+
}
195+
}
196+
",
197+
}
198+
`;
199+
3200
exports[`generateTypes multipleSwiftFiles generates multiple files 1`] = `
4201
Object {
5202
"Types.graphql.swift": "// This file was automatically generated and should not be edited.

packages/graphql-generator/src/__tests__/types.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,29 @@ describe('generateTypes', () => {
6565
expect(generateTypes(options)).rejects.toThrow('Query documents must be of type Source[] when generating multiple Swift files.');
6666
});
6767
});
68+
69+
describe('amplifyJsLibraryVersion', () => {
70+
test('generates angular types for v5 when value is 5 or undefined', async () => {
71+
const options: GenerateTypesOptions = {
72+
schema: sdlSchema,
73+
queries,
74+
target: 'angular',
75+
amplifyJsLibraryVersion: 5,
76+
};
77+
const typesV5 = await generateTypes(options);
78+
const typesUndefined = await generateTypes({ ...options, amplifyJsLibraryVersion: undefined });
79+
expect(typesV5).toEqual(typesUndefined);
80+
expect(typesV5).toMatchSnapshot();
81+
});
82+
test('generates angular types for v6 when value is 6', async () => {
83+
const options: GenerateTypesOptions = {
84+
schema: sdlSchema,
85+
queries,
86+
target: 'angular',
87+
amplifyJsLibraryVersion: 6,
88+
};
89+
const types = await generateTypes(options);
90+
expect(types).toMatchSnapshot();
91+
});
92+
});
6893
});

packages/graphql-generator/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { generate, generateFromString } from '@aws-amplify/graphql-types-generat
33
import { GenerateTypesOptions, GeneratedOutput } from './typescript';
44

55
export async function generateTypes(options: GenerateTypesOptions): Promise<GeneratedOutput> {
6-
const { schema, target, queries, multipleSwiftFiles = false, introspection = false } = options;
6+
const { schema, target, queries, multipleSwiftFiles = false, introspection = false, amplifyJsLibraryVersion } = options;
77

88
const generatedOutput = await generateFromString(schema, introspection, queries, target, multipleSwiftFiles, {
99
addTypename: true,
1010
complexObjectSupport: 'auto',
11+
amplifyJsLibraryVersion,
1112
});
1213

1314
return Object.fromEntries(Object.entries(generatedOutput).map(([filepath, contents]) => [path.basename(filepath), contents]));

packages/graphql-generator/src/typescript.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type GenerateTypesOptions = {
1414
queries: string | Source[];
1515
introspection?: boolean;
1616
multipleSwiftFiles?: boolean; // only used when target is swift
17+
amplifyJsLibraryVersion?: number; // only used when target is angular
1718
};
1819

1920
export type GenerateModelsOptions = {

0 commit comments

Comments
 (0)