Skip to content

Commit

Permalink
fix(amplify-codegen): set sourceDir path to correct graphql schema lo…
Browse files Browse the repository at this point in the history
…cation (#6512)

* fix(amplify-frontend-javascript): update source and distribution dir

#5483

* fix(amplify-app): update source and distribution dir

#5483

* fix(amplify-app): source dir path issues

* fix(amplify-codegen): sourceDir path issues in graphql schema

* merge and update code to not fail push if codegen has error

Co-authored-by: Wei He <[email protected]>
  • Loading branch information
yuth and wei authored Feb 10, 2021
1 parent 8273037 commit 6edf229
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 24 deletions.
2 changes: 1 addition & 1 deletion packages/amplify-app/src/framework-config-mapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const vueConfig = {
};

const emberConfig = {
SourceDir: '/',
SourceDir: './',
DistributionDir: 'dist',
BuildCommand: `${npm} run-script build -- -e production`,
StartCommand: `${npm} run-script start`,
Expand Down
42 changes: 26 additions & 16 deletions packages/amplify-codegen/src/callbacks/postPushCallback.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const path = require('path');
const { pathManager } = require('amplify-cli-core');

const loadConfig = require('../codegen-config');
const generateStatements = require('../commands/statements');
const generateTypes = require('../commands/types');
Expand All @@ -10,25 +13,32 @@ async function postPushCallback(context, graphQLConfig) {
return;
}

if (!graphQLConfig.gqlConfig.schema) {
const config = loadConfig(context);
const schemaLocation = getSchemaDownloadLocation(context);
try {
if (!graphQLConfig.gqlConfig.schema) {
const config = loadConfig(context);

const newProject = graphQLConfig.gqlConfig;
newProject.schema = schemaLocation;
config.addProject(newProject);
config.save();
}
const apis = getAppSyncAPIDetails(context);
const projectPath = pathManager.findProjectRoot() || process.cwd();
const schemaLocation = path.join(projectPath, getSchemaDownloadLocation(context));

await downloadIntrospectionSchema(context, apis[0].id, graphQLConfig.gqlConfig.schema);
if (graphQLConfig.shouldGenerateDocs) {
await generateStatements(context);
}
if (graphQLConfig.shouldGenerateModels) {
await generateModels(context);
const newProject = graphQLConfig.gqlConfig;
newProject.schema = schemaLocation;
config.addProject(newProject);
config.save();
}
const apis = getAppSyncAPIDetails(context);

await downloadIntrospectionSchema(context, apis[0].id, graphQLConfig.gqlConfig.schema);
if (graphQLConfig.shouldGenerateDocs) {
await generateStatements(context);
}
if (graphQLConfig.shouldGenerateModels) {
await generateModels(context);
}
await generateTypes(context);
} catch (error) {
// Code Generation failure should not result in actual push failure
context.print.warning(`Code generation failed with the following error \n${error.message}.`);
}
await generateTypes(context);
}

module.exports = postPushCallback;
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
const path = require('path');
const { pathManager } = require('amplify-cli-core');

const getAndroidResDir = require('./getAndroidResDir');
const getFrontEndHandler = require('./getFrontEndHandler');

function isSubDirectory(parent, pathToCheck) {
const relative = path.relative(parent, pathToCheck);
return relative && !relative.startsWith('..') && !path.isAbsolute(relative);
}
function getSchemaDownloadLocation(context) {
let downloadDir;
try {
Expand All @@ -18,6 +23,10 @@ function getSchemaDownloadLocation(context) {
const outputPath = frontEnd === 'javascript' ? sourceDir : '';
downloadDir = path.join(outputPath, 'graphql');
}

const projectRoot = pathManager.findProjectRoot();
// Downloaded schema should always be inside the project dir so the project is self contained
downloadDir = isSubDirectory(projectRoot, path.resolve(downloadDir)) ? downloadDir : path.join(projectRoot, downloadDir);
return path.join(downloadDir, 'schema.json');
}

Expand Down
13 changes: 11 additions & 2 deletions packages/amplify-codegen/tests/callbacks/postPushCallback.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('path');
const { pathManager } = require('amplify-cli-core');
const loadConfig = require('../../src/codegen-config');
const { downloadIntrospectionSchema, getAppSyncAPIDetails, getSchemaDownloadLocation } = require('../../src/utils');
const generateStatements = require('../../src/commands/statements');
Expand All @@ -10,6 +12,7 @@ const MOCK_CONTEXT = {
},
};

jest.mock('amplify-cli-core');
jest.mock('../../src/codegen-config');
jest.mock('../../src/utils');
jest.mock('../../src/commands/statements');
Expand All @@ -19,6 +22,7 @@ const MOCK_PROJECT_NAME = 'MOCK_PROJECT';
const MOCK_API_ID = 'MOCK_API_ID';
const MOCK_API_ENDPOINT = 'MOCK_API_ENDPOINT';

const MOCK_PATH_MANAGER_PROJECT_ROOT = '/project';
const MOCK_SELECTED_PROJECT = {
projectName: MOCK_PROJECT_NAME,
id: MOCK_API_ID,
Expand All @@ -42,6 +46,7 @@ const LOAD_CONFIG_METHODS = {
describe('Callback - Post Push update AppSync API', () => {
beforeEach(() => {
jest.resetAllMocks();
pathManager.findProjectRoot.mockReturnValue(MOCK_PATH_MANAGER_PROJECT_ROOT);
loadConfig.mockReturnValue(LOAD_CONFIG_METHODS);
getAppSyncAPIDetails.mockReturnValue(MOCK_PROJECTS);
getSchemaDownloadLocation.mockReturnValue(MOCK_SCHEMA_DOWNLOAD_LOCATION);
Expand All @@ -52,15 +57,19 @@ describe('Callback - Post Push update AppSync API', () => {
expect(loadConfig).toHaveBeenCalledWith(MOCK_CONTEXT);
expect(getAppSyncAPIDetails).toHaveBeenCalledWith(MOCK_CONTEXT);
expect(getSchemaDownloadLocation).toHaveBeenCalledWith(MOCK_CONTEXT);
expect(downloadIntrospectionSchema).toHaveBeenCalledWith(MOCK_CONTEXT, MOCK_API_ID, MOCK_SCHEMA_DOWNLOAD_LOCATION);
expect(downloadIntrospectionSchema).toHaveBeenCalledWith(
MOCK_CONTEXT,
MOCK_API_ID,
path.join(MOCK_PATH_MANAGER_PROJECT_ROOT, MOCK_SCHEMA_DOWNLOAD_LOCATION),
);
expect(LOAD_CONFIG_METHODS.addProject).toHaveBeenCalled();
const newProject = LOAD_CONFIG_METHODS.addProject.mock.calls[0][0];
expect(newProject).toEqual({
...MOCK_GRAPHQL_CONFIG.gqlConfig,
amplifyExtension: {
...MOCK_GRAPHQL_CONFIG.gqlConfig.amplifyExtension,
},
schema: MOCK_SCHEMA_DOWNLOAD_LOCATION,
schema: path.join(MOCK_PATH_MANAGER_PROJECT_ROOT, MOCK_SCHEMA_DOWNLOAD_LOCATION),
});
expect(generateTypes).toHaveBeenCalledTimes(1);
expect(generateStatements).toHaveBeenCalledTimes(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const { join, dirname } = require('path');
const { pathManager } = require('amplify-cli-core');

const getSchemaDownloadLocation = require('../../src/utils/getSchemaDownloadLocation');
const getAndroidResDir = require('../../src/utils/getAndroidResDir');
const getFrontendHandler = require('../../src/utils/getFrontEndHandler');

jest.mock('../../src/utils/getAndroidResDir');
jest.mock('../../src/utils/getFrontEndHandler');
jest.mock('amplify-cli-core');

let mockContext;
const mockProjectConfigDefault = 'MOCK_PROJECT_CONFIG';
Expand All @@ -19,12 +21,14 @@ const mockProjectConfig = {
};
const mockResDir = 'MOCK_RES_DIR/Res';
const mockAPIName = 'FooAPI';
const mockProjectRoot = '/home/user/project/proj1';

const mockGetProjectConfigDefault = jest.fn();
const mockGetProjectConfig = jest.fn();
describe('getSchemaDownloadLocation', () => {
beforeEach(() => {
jest.resetAllMocks();
pathManager.findProjectRoot.mockReturnValue(mockProjectRoot);
mockGetProjectConfigDefault.mockReturnValue(mockProjectConfigDefault);
mockGetProjectConfig.mockReturnValue(mockProjectConfig);
getAndroidResDir.mockImplementation(() => {
Expand All @@ -40,7 +44,7 @@ describe('getSchemaDownloadLocation', () => {
},
};
const downloadLocation = getSchemaDownloadLocation(mockContext);
expect(downloadLocation).toEqual(join('src', 'graphql', 'schema.json'));
expect(downloadLocation).toEqual(join(mockProjectRoot, 'src', 'graphql', 'schema.json'));
});

it('should use the defined project config directory when used in JS frontend', () => {
Expand All @@ -50,7 +54,7 @@ describe('getSchemaDownloadLocation', () => {
},
};
const downloadLocation = getSchemaDownloadLocation(mockContext);
expect(downloadLocation).toEqual(join('web-client', 'src', 'graphql', 'schema.json'));
expect(downloadLocation).toEqual(join(mockProjectRoot, 'web-client', 'src', 'graphql', 'schema.json'));
});

it('should use the graphql directory when used in iOS frontend', () => {
Expand All @@ -61,7 +65,7 @@ describe('getSchemaDownloadLocation', () => {
};
getFrontendHandler.mockReturnValue('iOS');
const downloadLocation = getSchemaDownloadLocation(mockContext);
expect(downloadLocation).toEqual(join('graphql', 'schema.json'));
expect(downloadLocation).toEqual(join(mockProjectRoot, 'graphql', 'schema.json'));
});

it('should use main directory in Android', () => {
Expand All @@ -72,6 +76,17 @@ describe('getSchemaDownloadLocation', () => {
};
getAndroidResDir.mockReturnValue(mockResDir);
const downloadLocation = getSchemaDownloadLocation(mockContext);
expect(downloadLocation).toEqual(join(dirname(mockResDir), 'graphql', 'schema.json'));
expect(downloadLocation).toEqual(join(mockProjectRoot, dirname(mockResDir), 'graphql', 'schema.json'));
});

it('should return the download location inside the project root', () => {
mockContext = {
amplify: {
getProjectConfig: mockGetProjectConfig,
},
};
getAndroidResDir.mockReturnValue(mockResDir);
const downloadLocation = getSchemaDownloadLocation(mockContext);
expect(downloadLocation).toContain(mockProjectRoot);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const vueConfig = {
};

const emberConfig = {
SourceDir: '/',
SourceDir: './',
DistributionDir: 'dist',
BuildCommand: `${npm} run-script build -- -e production`,
StartCommand: `${npm} run-script start`,
Expand Down

0 comments on commit 6edf229

Please sign in to comment.