diff --git a/packages/amplify-frontend-android/lib/amplify-config-helper.js b/packages/amplify-frontend-android/lib/amplify-config-helper.js index 4aa80d078e..df156bbfa7 100644 --- a/packages/amplify-frontend-android/lib/amplify-config-helper.js +++ b/packages/amplify-frontend-android/lib/amplify-config-helper.js @@ -1,4 +1,4 @@ -function generateConfig(context, newAWSConfig) { +function generateConfig(context, newAWSConfig, amplifyResources) { const metadata = context.amplify.getProjectMeta(); const amplifyConfig = { UserAgent: 'aws-amplify-cli/2.0', @@ -6,7 +6,7 @@ function generateConfig(context, newAWSConfig) { }; constructAnalytics(metadata, amplifyConfig); constructNotifications(metadata, amplifyConfig); - constructApi(metadata, amplifyConfig); + constructApi(metadata, amplifyConfig, amplifyResources); // Auth plugin with entire awsconfiguration contained required for Native GA release constructAuth(metadata, amplifyConfig, newAWSConfig); constructPredictions(metadata, amplifyConfig); @@ -85,7 +85,7 @@ function constructAnalytics(metadata, amplifyConfig) { } } -function constructApi(metadata, amplifyConfig) { +function constructApi(metadata, amplifyConfig, amplifyResources) { const categoryName = 'api'; const pluginName = 'awsAPIPlugin'; const region = metadata.providers.awscloudformation.Region; @@ -104,13 +104,17 @@ function constructApi(metadata, amplifyConfig) { } else if (resourceMeta.output.securityType) { authorizationType = resourceMeta.output.securityType; } + const apiKey = getAppSyncResourceOutput(amplifyResources, 'GraphQLAPIKeyOutput') || resourceMeta.output.GraphQLAPIKeyOutput; amplifyConfig[categoryName].plugins[pluginName][r] = { endpointType: 'GraphQL', - endpoint: resourceMeta.output.GraphQLAPIEndpointOutput, + endpoint: + getAppSyncResourceOutput(amplifyResources, 'GraphQLAPIEndpointOutput') || resourceMeta.output.GraphQLAPIEndpointOutput, region, authorizationType, - apiKey: resourceMeta.output.GraphQLAPIKeyOutput, }; + if (apiKey) { + amplifyConfig[categoryName].plugins[pluginName][r]['apiKey'] = apiKey; + } } else if (resourceMeta.service === 'API Gateway') { amplifyConfig[categoryName].plugins[pluginName][r] = { endpointType: 'REST', @@ -282,6 +286,13 @@ function constructGeo(metadata, amplifyConfig) { } } +function getAppSyncResourceOutput(amplifyResources, outputName) { + const appSyncResourceMapping = amplifyResources?.serviceResourceMapping?.AppSync; + if (appSyncResourceMapping && appSyncResourceMapping[0]) { + return appSyncResourceMapping[0]?.output?.[outputName]; + } +} + module.exports = { generateConfig, constructNotifications, diff --git a/packages/amplify-frontend-android/lib/frontend-config-creator.js b/packages/amplify-frontend-android/lib/frontend-config-creator.js index acd7eee96f..72ffe7617a 100644 --- a/packages/amplify-frontend-android/lib/frontend-config-creator.js +++ b/packages/amplify-frontend-android/lib/frontend-config-creator.js @@ -91,7 +91,7 @@ function writeToFile(filePath, fileName, configObject) { function getAmplifyConfig(context, amplifyResources, cloudAmplifyResources) { const newAWSConfig = getNewAWSConfigObject(context, amplifyResources, cloudAmplifyResources); - return amplifyConfigHelper.generateConfig(context, newAWSConfig); + return amplifyConfigHelper.generateConfig(context, newAWSConfig, amplifyResources); } function getNewAWSConfigObject(context, amplifyResources, cloudAmplifyResources) { diff --git a/packages/amplify-frontend-android/tests/amplify-config-helper.test.js b/packages/amplify-frontend-android/tests/amplify-config-helper.test.js index ef0bad3a11..913e797ec8 100644 --- a/packages/amplify-frontend-android/tests/amplify-config-helper.test.js +++ b/packages/amplify-frontend-android/tests/amplify-config-helper.test.js @@ -1,4 +1,4 @@ -const configHelper = require('../../amplify-frontend-android/lib/amplify-config-helper'); +const configHelper = require('../lib/amplify-config-helper'); jest.mock('@aws-amplify/amplify-cli-core'); const mapServiceName = 'Map'; @@ -126,3 +126,113 @@ describe('customer pinpoint configuration', () => { expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); }); }); + +describe('AppSync configuration', () => { + const mockContext = { + amplify: { + getProjectMeta: jest.fn(), + }, + }; + let amplifyMeta = {}; + const expectedAmplifyConfiguration = { + UserAgent: 'aws-amplify-cli/2.0', + Version: '1.0', + api: { + plugins: { + awsAPIPlugin: { + testapi: { + apiKey: 'expectedApiKey', + authorizationType: undefined, + endpoint: 'expectedEndpoint', + endpointType: 'GraphQL', + region: 'us-east-1', + }, + }, + }, + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + amplifyMeta = { + providers: { + awscloudformation: { + Region: 'us-east-1', + }, + }, + api: { + testapi: { + service: 'AppSync', + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + GraphQLAPIKeyOutput: 'expectedApiKey', + }, + }, + }, + }; + }); + it('generates correct endpoint and apiKey based on outputs in Amplify meta', () => { + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, {}); + + const expectedAmplifyConfiguration = { + UserAgent: 'aws-amplify-cli/2.0', + Version: '1.0', + api: { + plugins: { + awsAPIPlugin: { + testapi: { + apiKey: 'expectedApiKey', + authorizationType: undefined, + endpoint: 'expectedEndpoint', + endpointType: 'GraphQL', + region: 'us-east-1', + }, + }, + }, + }, + }; + expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); + }); + + it('generates correct endpoint and apiKey based on overriden resource outputs', () => { + amplifyMeta.api.testapi.output.GraphQLAPIEndpointOutput = 'notExpectedEndpoint'; + amplifyMeta.api.testapi.output.GraphQLAPIKeyOutput = 'notExpectedEndpoint'; + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyResources = { + serviceResourceMapping: { + AppSync: [ + { + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + GraphQLAPIKeyOutput: 'expectedApiKey', + }, + }, + ], + }, + }; + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, amplifyResources); + expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); + }); + + it('does not add apiKey if its not available', () => { + amplifyMeta.api.testapi.output.GraphQLAPIEndpointOutput = 'notExpectedEndpoint'; + delete amplifyMeta.api.testapi.output.GraphQLAPIKeyOutput; + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyResources = { + serviceResourceMapping: { + AppSync: [ + { + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + }, + }, + ], + }, + }; + const expected = { ...expectedAmplifyConfiguration }; + delete expected.api.plugins.awsAPIPlugin.testapi.apiKey; + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, amplifyResources); + expect(amplifyConfiguration).toMatchObject(expected); + }); +}); diff --git a/packages/amplify-frontend-ios/lib/amplify-config-helper.js b/packages/amplify-frontend-ios/lib/amplify-config-helper.js index 6cfbaf6157..bfb75af4ef 100644 --- a/packages/amplify-frontend-ios/lib/amplify-config-helper.js +++ b/packages/amplify-frontend-ios/lib/amplify-config-helper.js @@ -1,4 +1,4 @@ -function generateConfig(context, newAWSConfig) { +function generateConfig(context, newAWSConfig, amplifyResources) { const metadata = context.amplify.getProjectMeta(); const amplifyConfig = { UserAgent: 'aws-amplify-cli/2.0', @@ -6,7 +6,7 @@ function generateConfig(context, newAWSConfig) { }; constructAnalytics(metadata, amplifyConfig); constructNotifications(metadata, amplifyConfig); - constructApi(metadata, amplifyConfig); + constructApi(metadata, amplifyConfig, amplifyResources); // Auth plugin with entire awsconfiguration contained required for Native GA release constructAuth(metadata, amplifyConfig, newAWSConfig); constructPredictions(metadata, amplifyConfig); @@ -85,7 +85,7 @@ function constructAnalytics(metadata, amplifyConfig) { } } -function constructApi(metadata, amplifyConfig) { +function constructApi(metadata, amplifyConfig, amplifyResources) { const categoryName = 'api'; const pluginName = 'awsAPIPlugin'; const region = metadata.providers.awscloudformation.Region; @@ -104,13 +104,17 @@ function constructApi(metadata, amplifyConfig) { } else if (resourceMeta.output.securityType) { authorizationType = resourceMeta.output.securityType; } + const apiKey = getAppSyncResourceOutput(amplifyResources, 'GraphQLAPIKeyOutput') || resourceMeta.output.GraphQLAPIKeyOutput; amplifyConfig[categoryName].plugins[pluginName][r] = { endpointType: 'GraphQL', - endpoint: resourceMeta.output.GraphQLAPIEndpointOutput, + endpoint: + getAppSyncResourceOutput(amplifyResources, 'GraphQLAPIEndpointOutput') || resourceMeta.output.GraphQLAPIEndpointOutput, region, authorizationType, - apiKey: resourceMeta.output.GraphQLAPIKeyOutput, }; + if (apiKey) { + amplifyConfig[categoryName].plugins[pluginName][r]['apiKey'] = apiKey; + } } else if (resourceMeta.service === 'API Gateway') { amplifyConfig[categoryName].plugins[pluginName][r] = { endpointType: 'REST', @@ -283,6 +287,13 @@ function constructGeo(metadata, amplifyConfig) { } } +function getAppSyncResourceOutput(amplifyResources, outputName) { + const appSyncResourceMapping = amplifyResources?.serviceResourceMapping?.AppSync; + if (appSyncResourceMapping && appSyncResourceMapping[0]) { + return appSyncResourceMapping[0]?.output?.[outputName]; + } +} + module.exports = { generateConfig, }; diff --git a/packages/amplify-frontend-ios/lib/frontend-config-creator.js b/packages/amplify-frontend-ios/lib/frontend-config-creator.js index 48b54ac2ff..60f8f7a6e7 100644 --- a/packages/amplify-frontend-ios/lib/frontend-config-creator.js +++ b/packages/amplify-frontend-ios/lib/frontend-config-creator.js @@ -81,7 +81,7 @@ function writeToFile(filePath, fileName, configObject) { function getAmplifyConfig(context, amplifyResources, cloudAmplifyResources) { const newAWSConfig = getNewAWSConfigObject(context, amplifyResources, cloudAmplifyResources); - const amplifyConfig = amplifyConfigHelper.generateConfig(context, newAWSConfig); + const amplifyConfig = amplifyConfigHelper.generateConfig(context, newAWSConfig, amplifyResources); return amplifyConfig; } diff --git a/packages/amplify-frontend-ios/tests/amplify-config-helper.test.js b/packages/amplify-frontend-ios/tests/amplify-config-helper.test.js index ef0bad3a11..1abf9585bb 100644 --- a/packages/amplify-frontend-ios/tests/amplify-config-helper.test.js +++ b/packages/amplify-frontend-ios/tests/amplify-config-helper.test.js @@ -1,4 +1,4 @@ -const configHelper = require('../../amplify-frontend-android/lib/amplify-config-helper'); +const configHelper = require('../lib/amplify-config-helper'); jest.mock('@aws-amplify/amplify-cli-core'); const mapServiceName = 'Map'; @@ -89,6 +89,11 @@ describe('generate maps and search configuration', () => { describe('customer pinpoint configuration', () => { it('generates correct notifications channel pinpoint configuration', () => { const amplifyMeta = { + providers: { + awscloudformation: { + Region: 'us-east-1', + }, + }, notifications: { amplifyplayground: { service: 'Pinpoint', @@ -106,8 +111,14 @@ describe('customer pinpoint configuration', () => { }, }, }; - const amplifyConfiguration = {}; - configHelper.constructNotifications(amplifyMeta, amplifyConfiguration); + + const mockContext = { + amplify: { + getProjectMeta: jest.fn().mockReturnValue(amplifyMeta), + }, + }; + + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}); const expectedAmplifyConfiguration = { notifications: { @@ -126,3 +137,113 @@ describe('customer pinpoint configuration', () => { expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); }); }); + +describe('AppSync configuration', () => { + const mockContext = { + amplify: { + getProjectMeta: jest.fn(), + }, + }; + let amplifyMeta = {}; + const expectedAmplifyConfiguration = { + UserAgent: 'aws-amplify-cli/2.0', + Version: '1.0', + api: { + plugins: { + awsAPIPlugin: { + testapi: { + apiKey: 'expectedApiKey', + authorizationType: undefined, + endpoint: 'expectedEndpoint', + endpointType: 'GraphQL', + region: 'us-east-1', + }, + }, + }, + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + amplifyMeta = { + providers: { + awscloudformation: { + Region: 'us-east-1', + }, + }, + api: { + testapi: { + service: 'AppSync', + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + GraphQLAPIKeyOutput: 'expectedApiKey', + }, + }, + }, + }; + }); + it('generates correct endpoint and apiKey based on outputs in Amplify meta', () => { + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, {}); + + const expectedAmplifyConfiguration = { + UserAgent: 'aws-amplify-cli/2.0', + Version: '1.0', + api: { + plugins: { + awsAPIPlugin: { + testapi: { + apiKey: 'expectedApiKey', + authorizationType: undefined, + endpoint: 'expectedEndpoint', + endpointType: 'GraphQL', + region: 'us-east-1', + }, + }, + }, + }, + }; + expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); + }); + + it('generates correct endpoint and apiKey based on overriden resource outputs', () => { + amplifyMeta.api.testapi.output.GraphQLAPIEndpointOutput = 'notExpectedEndpoint'; + amplifyMeta.api.testapi.output.GraphQLAPIKeyOutput = 'notExpectedEndpoint'; + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyResources = { + serviceResourceMapping: { + AppSync: [ + { + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + GraphQLAPIKeyOutput: 'expectedApiKey', + }, + }, + ], + }, + }; + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, amplifyResources); + expect(amplifyConfiguration).toMatchObject(expectedAmplifyConfiguration); + }); + + it('does not add apiKey if its not available', () => { + amplifyMeta.api.testapi.output.GraphQLAPIEndpointOutput = 'notExpectedEndpoint'; + delete amplifyMeta.api.testapi.output.GraphQLAPIKeyOutput; + mockContext.amplify.getProjectMeta = jest.fn().mockReturnValue(amplifyMeta); + const amplifyResources = { + serviceResourceMapping: { + AppSync: [ + { + output: { + GraphQLAPIEndpointOutput: 'expectedEndpoint', + }, + }, + ], + }, + }; + const expected = { ...expectedAmplifyConfiguration }; + delete expected.api.plugins.awsAPIPlugin.testapi.apiKey; + const amplifyConfiguration = configHelper.generateConfig(mockContext, {}, amplifyResources); + expect(amplifyConfiguration).toMatchObject(expected); + }); +});