Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add angular codegen v6 support #799

Merged
merged 9 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/amplify-codegen/src/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ async function add(context, apiId = null, region = 'us-east-1') {
apiId,
...(withoutInit ? { frontend } : {}),
...(withoutInit && frontend === 'javascript' ? { framework } : {}),
// The default Amplify JS lib version is set for 6 for angular codegen
...(answer.target === 'angular' ? { amplifyJsLibraryVersion: 6 } : {}),
},
};

Expand Down
16 changes: 16 additions & 0 deletions packages/amplify-codegen/src/commands/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ async function generateTypes(context, forceDownloadSchema, withoutInit = false,
}
const target = cfg.amplifyExtension.codeGenTarget;

let amplifyJsLibraryVersion = cfg.amplifyExtension.amplifyJsLibraryVersion;

/**
* amplifyJsLibraryVersion config is currently used for angular codegen
* The supported value is 5 for JS v5 and 6 for JS v6
* When the value is undefined, it will stay at codegen for JS v5 for non-breaking change for existing users
* For the other values set, a warning message will be sent in the console and the codegen will use the v6 codegen
*/
if (target === 'angular' && amplifyJsLibraryVersion && amplifyJsLibraryVersion !== 6 && amplifyJsLibraryVersion !== 5) {
context.print.warning(
`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.`,
);
amplifyJsLibraryVersion = 6
}

const excludes = cfg.excludes.map(pattern => `!${pattern}`);
const normalizedPatterns = [...includeFiles, ...excludes].map((path) => normalizePathForGlobPattern(path));
const queryFilePaths = globby.sync(normalizedPatterns, {
Expand Down Expand Up @@ -114,6 +129,7 @@ async function generateTypes(context, forceDownloadSchema, withoutInit = false,
target,
introspection,
multipleSwiftFiles,
amplifyJsLibraryVersion,
});
const outputs = Object.entries(output);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async function askCodeGenTargetLanguage(context, target, withoutInit = false, de
default: target || null,
},
]);

return answer.target;
}

Expand Down
40 changes: 40 additions & 0 deletions packages/amplify-codegen/tests/commands/types.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { ensureIntrospectionSchema, getFrontEndHandler, getAppSyncAPIDetails } =
const MOCK_CONTEXT = {
print: {
info: jest.fn(),
warning: jest.fn(),
},
amplify: {
getEnvInfo: jest.fn(),
Expand Down Expand Up @@ -56,6 +57,19 @@ const MOCK_APIS = [

getFrontEndHandler.mockReturnValue('javascript');

const MOCK_ANGULAR_PROJECT_BASE = {
excludes: [MOCK_EXCLUDE_PATH],
includes: [MOCK_INCLUDE_PATH],
schema: MOCK_SCHEMA,
amplifyExtension: {
generatedFileName: MOCK_GENERATED_FILE_NAME,
codeGenTarget: 'angular',
graphQLApiId: MOCK_API_ID,
region: MOCK_REGION,
amplifyJsLibraryVersion: 5,
},
};

describe('command - types', () => {
beforeEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -163,4 +177,30 @@ describe('command - types', () => {
expect(generateTypesHelper).not.toHaveBeenCalled();
expect(globby.sync).not.toHaveBeenCalled();
});

it('should show a warning if the amplifyJsLibraryVersion is invalid', async () => {
const MOCK_ANGULAR_PROJECT = {
...MOCK_ANGULAR_PROJECT_BASE
};
MOCK_ANGULAR_PROJECT.amplifyExtension.amplifyJsLibraryVersion = 7
fs.readFileSync
.mockReturnValueOnce('query 1')
.mockReturnValueOnce('query 2')
.mockReturnValueOnce('schema');
loadConfig.mockReturnValue({
getProjects: jest.fn().mockReturnValue([MOCK_ANGULAR_PROJECT]),
});
await generateTypes(MOCK_CONTEXT, false);
expect(MOCK_CONTEXT.print.warning).toHaveBeenCalledWith(
'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.'
);
expect(generateTypesHelper).toHaveBeenCalledWith({
queries: [new Source('query 1', 'q1.gql'), new Source('query 2', 'q2.gql')],
schema: 'schema',
target: 'angular',
introspection: false,
multipleSwiftFiles: false,
amplifyJsLibraryVersion: 6,
});
});
});
1 change: 1 addition & 0 deletions packages/graphql-generator/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type GenerateTypesOptions = {
queries: string | Source[];
introspection?: boolean;
multipleSwiftFiles?: boolean;
amplifyJsLibraryVersion?: number;
};

// @public (undocumented)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,202 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`generateTypes amplifyJsLibraryVersion generates angular types for v5 when value is 5 or undefined 1`] = `
Object {
"api.service.ts": "/* tslint:disable */
/* eslint-disable */
// This file was automatically generated and should not be edited.
import { Injectable } from \\"@angular/core\\";
import API, { graphqlOperation, GraphQLResult } from \\"@aws-amplify/api-graphql\\";
import { Observable } from \\"zen-observable-ts\\";

export interface SubscriptionResponse<T> {
value: GraphQLResult<T>;
}

export type Blog = {
__typename: \\"Blog\\";
id: string;
name: string;
posts?: ModelPostConnection | null;
createdAt: string;
updatedAt: string;
};

export type ModelPostConnection = {
__typename: \\"ModelPostConnection\\";
items: Array<Post | null>;
nextToken?: string | null;
};

export type Post = {
__typename: \\"Post\\";
id: string;
title: string;
blog?: Blog | null;
comments?: ModelCommentConnection | null;
createdAt: string;
updatedAt: string;
blogPostsId?: string | null;
};

export type ModelCommentConnection = {
__typename: \\"ModelCommentConnection\\";
items: Array<Comment | null>;
nextToken?: string | null;
};

export type Comment = {
__typename: \\"Comment\\";
id: string;
post?: Post | null;
content: string;
createdAt: string;
updatedAt: string;
postCommentsId?: string | null;
};

export type GetBlogQuery = {
__typename: \\"Blog\\";
id: string;
name: string;
posts?: {
__typename: \\"ModelPostConnection\\";
nextToken?: string | null;
} | null;
createdAt: string;
updatedAt: string;
};

@Injectable({
providedIn: \\"root\\"
})
export class APIService {
async GetBlog(id: string): Promise<GetBlogQuery> {
const statement = \`query GetBlog($id: ID!) {
getBlog(id: $id) {
__typename
id
name
posts {
__typename
nextToken
}
createdAt
updatedAt
}
}\`;
const gqlAPIServiceArguments: any = {
id
};
const response = (await API.graphql(
graphqlOperation(statement, gqlAPIServiceArguments)
)) as any;
return <GetBlogQuery>response.data.getBlog;
}
}
",
}
`;

exports[`generateTypes amplifyJsLibraryVersion generates angular types for v6 when value is 6 1`] = `
Object {
"api.service.ts": "/* tslint:disable */
/* eslint-disable */
// This file was automatically generated and should not be edited.
import { Injectable } from \\"@angular/core\\";
import { Client, generateClient, GraphQLResult } from \\"aws-amplify/api\\";
import { Observable } from \\"rxjs\\";

export type Blog = {
__typename: \\"Blog\\";
id: string;
name: string;
posts?: ModelPostConnection | null;
createdAt: string;
updatedAt: string;
};

export type ModelPostConnection = {
__typename: \\"ModelPostConnection\\";
items: Array<Post | null>;
nextToken?: string | null;
};

export type Post = {
__typename: \\"Post\\";
id: string;
title: string;
blog?: Blog | null;
comments?: ModelCommentConnection | null;
createdAt: string;
updatedAt: string;
blogPostsId?: string | null;
};

export type ModelCommentConnection = {
__typename: \\"ModelCommentConnection\\";
items: Array<Comment | null>;
nextToken?: string | null;
};

export type Comment = {
__typename: \\"Comment\\";
id: string;
post?: Post | null;
content: string;
createdAt: string;
updatedAt: string;
postCommentsId?: string | null;
};

export type GetBlogQuery = {
__typename: \\"Blog\\";
id: string;
name: string;
posts?: {
__typename: \\"ModelPostConnection\\";
nextToken?: string | null;
} | null;
createdAt: string;
updatedAt: string;
};

@Injectable({
providedIn: \\"root\\"
})
export class APIService {
public client: Client;
constructor() {
this.client = generateClient();
}
async GetBlog(id: string): Promise<GetBlogQuery> {
const statement = \`query GetBlog($id: ID!) {
getBlog(id: $id) {
__typename
id
name
posts {
__typename
nextToken
}
createdAt
updatedAt
}
}\`;
const gqlAPIServiceArguments: any = {
id
};
const response = (await this.client.graphql({
query: statement,
variables: gqlAPIServiceArguments
})) as any;
return <GetBlogQuery>response.data.getBlog;
}
}
",
}
`;

exports[`generateTypes multipleSwiftFiles generates multiple files 1`] = `
Object {
"Types.graphql.swift": "// This file was automatically generated and should not be edited.
Expand Down
25 changes: 25 additions & 0 deletions packages/graphql-generator/src/__tests__/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,29 @@ describe('generateTypes', () => {
expect(generateTypes(options)).rejects.toThrow('Query documents must be of type Source[] when generating multiple Swift files.');
});
});

describe('amplifyJsLibraryVersion', () => {
test('generates angular types for v5 when value is 5 or undefined', async () => {
const options: GenerateTypesOptions = {
schema: sdlSchema,
queries,
target: 'angular',
amplifyJsLibraryVersion: 5,
};
const typesV5 = await generateTypes(options);
const typesUndefined = await generateTypes({ ...options, amplifyJsLibraryVersion: undefined });
expect(typesV5).toEqual(typesUndefined);
expect(typesV5).toMatchSnapshot();
});
test('generates angular types for v6 when value is 6', async () => {
const options: GenerateTypesOptions = {
schema: sdlSchema,
queries,
target: 'angular',
amplifyJsLibraryVersion: 6,
};
const types = await generateTypes(options);
expect(types).toMatchSnapshot();
});
});
});
3 changes: 2 additions & 1 deletion packages/graphql-generator/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { generate, generateFromString } from '@aws-amplify/graphql-types-generat
import { GenerateTypesOptions, GeneratedOutput } from './typescript';

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

const generatedOutput = await generateFromString(schema, introspection, queries, target, multipleSwiftFiles, {
addTypename: true,
complexObjectSupport: 'auto',
amplifyJsLibraryVersion,
});

return Object.fromEntries(Object.entries(generatedOutput).map(([filepath, contents]) => [path.basename(filepath), contents]));
Expand Down
1 change: 1 addition & 0 deletions packages/graphql-generator/src/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type GenerateTypesOptions = {
queries: string | Source[];
introspection?: boolean;
multipleSwiftFiles?: boolean; // only used when target is swift
amplifyJsLibraryVersion?: number; // only used when target is angular
};

export type GenerateModelsOptions = {
Expand Down
Loading
Loading