Skip to content

Commit

Permalink
Codegen decouple (#2175)
Browse files Browse the repository at this point in the history
* feat(amplify-codegen): codegen decoupling

* feat(amplify-codegen): codegen decoupling

* fix(amplify-codegen): pull frontend from gqlconfig

* fix(amplify-codegen): check gqlconfig for frontend

* fix(amplify-codegen): merge conflict

* fix: fix

* fix(amplify-codegen): fix configure

* refactor(amplify-codegen): comment changes

* test(amplify-codegen): tests compatible with new params in functions

* fix(amplify-codegen): project declaration

* fix(amplify-codegen): lgtm fixes

* fix(amplify-codegen): lint-fix

* refactor(amplify-codegen): requested changes

made frontend and framework optional parameters, moved codegen command logic to
generateStatementsAndType.js

* fix(amplify-codegen): lint-fix
  • Loading branch information
nikhname authored and kaustavghosh06 committed Sep 12, 2019
1 parent c557182 commit 47a0f67
Show file tree
Hide file tree
Showing 19 changed files with 325 additions and 101 deletions.
2 changes: 1 addition & 1 deletion packages/amplify-codegen/commands/codegen/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ module.exports = {
context.print.error(ex.message);
}
},
};
};
4 changes: 2 additions & 2 deletions packages/amplify-codegen/commands/codegen/codegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ module.exports = {
}

try {
const forceDownloadSchema = !context.parameters.options.nodownload;
const { maxDepth } = context.parameters.options;
let forceDownloadSchema = !context.parameters.options.nodownload;
let { maxDepth } = context.parameters.options;
await codeGen.generate(context, forceDownloadSchema, maxDepth);
} catch (e) {
context.print.info(e.message);
Expand Down
145 changes: 105 additions & 40 deletions packages/amplify-codegen/src/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,64 +18,126 @@ const {
} = require('../utils');
const addWalkThrough = require('../walkthrough/add');
const changeAppSyncRegion = require('../walkthrough/changeAppSyncRegions');
const path = require('path');
const fs = require('fs-extra');
const askForFrontend = require('../walkthrough/questions/selectFrontend');
const askForFramework = require('../walkthrough/questions/selectFramework');

const frontends = ['android', 'ios', 'javascript'];
const frameworks = ['angular', 'ember', 'ionic', 'react', 'react-native', 'vue', 'none'];

async function add(context, apiId = null) {
let region = getProjectAwsRegion(context);
let withoutInit = false;
// Determine if working in an amplify project
try {
context.amplify.getProjectMeta();
} catch (e) {
withoutInit = true;
const testconfig = loadConfig(context);
if (testconfig.getProjects().length) {
throw new Error(constants.ERROR_CODEGEN_SUPPORT_MAX_ONE_API);
}
}

const schemaName = './schema.json';
const schemaPath = path.join(process.cwd(), schemaName);
if (!fs.existsSync(schemaPath) && withoutInit) {
throw Error(`Please download the introspection schema and place in ${schemaPath} before adding codegen when not in an amplify project`);
}

// Grab the frontend
let frontend;
if (withoutInit) {
({ frontend } = context.parameters.options);
if (frontend) {
// Make sure provided frontend prarameter is valid
if (!frontends.includes(frontend)) {
throw Error('Invalid frontend provided');
}
} else {
frontend = await askForFrontend(frontends);
}
}

// Grab the framework
let framework;
if (withoutInit) {
({ framework } = context.parameters.options);
if (framework) {
if (frontend !== 'javascript' || !frameworks.includes(framework)) {
throw Error('Invalid framework provided');
}
} else if (frontend === 'javascript') {
framework = await askForFramework(frameworks);
}
}

let region = 'us-east-1';
if (!withoutInit) {
region = getProjectAwsRegion(context);
}
const config = loadConfig(context);
if (config.getProjects().length) {
throw new Error(constants.ERROR_CODEGEN_SUPPORT_MAX_ONE_API);
}
let apiDetails;
if (!apiId) {
const availableAppSyncApis = getAppSyncAPIDetails(context); // published and un-published
if (availableAppSyncApis.length === 0) {
throw new NoAppSyncAPIAvailableError(constants.ERROR_CODEGEN_NO_API_AVAILABLE);
}
[apiDetails] = availableAppSyncApis;
apiDetails.isLocal = true;
} else {
let shouldRetry = true;
while (shouldRetry) {
const apiDetailSpinner = new Ora();
try {
apiDetailSpinner.start('Getting API details');
apiDetails = await getAppSyncAPIInfo(context, apiId, region);
apiDetailSpinner.succeed();
await updateAmplifyMeta(context, apiDetails);
break;
} catch (e) {
apiDetailSpinner.fail();
if (e instanceof AmplifyCodeGenAPINotFoundError) {
context.print.info(`AppSync API was not found in region ${region}`);
({ shouldRetry, region } = await changeAppSyncRegion(context, region));
} else {
throw e;
if (!withoutInit) {
if (!apiId) {
const availableAppSyncApis = getAppSyncAPIDetails(context); // published and un-published
if (availableAppSyncApis.length === 0) {
throw new NoAppSyncAPIAvailableError(constants.ERROR_CODEGEN_NO_API_AVAILABLE);
}
[apiDetails] = availableAppSyncApis;
apiDetails.isLocal = true;
} else {
let shouldRetry = true;
while (shouldRetry) {
const apiDetailSpinner = new Ora();
try {
apiDetailSpinner.start('Getting API details');
apiDetails = await getAppSyncAPIInfo(context, apiId, region);
apiDetailSpinner.succeed();
await updateAmplifyMeta(context, apiDetails);
break;
} catch (e) {
apiDetailSpinner.fail();
if (e instanceof AmplifyCodeGenAPINotFoundError) {
context.print.info(`AppSync API was not found in region ${region}`);
({ shouldRetry, region } = await changeAppSyncRegion(context, region));
} else {
throw e;
}
}
}
}
}

if (!apiDetails) {
if (!withoutInit && !apiDetails) {
return;
}
const answer = await addWalkThrough(context);
const answer = await addWalkThrough(context, undefined, withoutInit, frontend, framework);


let schema;
if (!apiDetails.isLocal) {
schema = await downloadIntrospectionSchemaWithProgress(
context,
apiDetails.id,
answer.schemaLocation,
region,
);
} else if (getFrontEndHandler(context) === 'android') {
schema = answer.schemaLocation;
if (!withoutInit) {
if (!apiDetails.isLocal) {
schema = await downloadIntrospectionSchemaWithProgress(
context,
apiDetails.id,
answer.schemaLocation,
region,
);
} else if (getFrontEndHandler(context) === 'android') {
schema = answer.schemaLocation;
} else {
schema = getSDLSchemaLocation(apiDetails.name);
}
} else {
schema = getSDLSchemaLocation(apiDetails.name);
schema = './schema.json';
}

const newProject = {
projectName: apiDetails.name,
projectName: withoutInit ? 'Codegen Project' : apiDetails.name,
includes: answer.includePattern,
excludes: answer.excludePattern,
schema,
Expand All @@ -84,6 +146,9 @@ async function add(context, apiId = null) {
generatedFileName: answer.generatedFileName || '',
docsFilePath: answer.docsFilePath,
region,
apiId,
...(withoutInit ? { frontend } : {}),
...(withoutInit ? { framework } : {}),
},
};

Expand All @@ -92,10 +157,10 @@ async function add(context, apiId = null) {
}
config.addProject(newProject);
if (answer.shouldGenerateDocs) {
await generateStatements(context, false);
await generateStatements(context, false, undefined, withoutInit, frontend);
}
if (answer.shouldGenerateCode) {
await generateTypes(context, false);
await generateTypes(context, false, withoutInit, frontend);
}
config.save();
}
Expand Down
8 changes: 7 additions & 1 deletion packages/amplify-codegen/src/commands/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ const configureProjectWalkThrough = require('../walkthrough/configure');
const add = require('./add');

async function configure(context) {
let withoutInit = false;
try {
context.amplify.getProjectMeta();
} catch (e) {
withoutInit = true;
}
const config = loadConfig(context);
if (!config.getProjects().length) {
await add(context);
return;
}
const project = await configureProjectWalkThrough(context, config.getProjects());
const project = await configureProjectWalkThrough(context, config.getProjects(), withoutInit);
config.addProject(project);
config.save();
}
Expand Down
68 changes: 51 additions & 17 deletions packages/amplify-codegen/src/commands/generateStatementsAndType.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,64 @@ const generateStatements = require('./statements');
const loadConfig = require('../codegen-config');
const constants = require('../constants');
const { ensureIntrospectionSchema, getAppSyncAPIDetails } = require('../utils');
const path = require('path');
const fs = require('fs-extra');

async function generateStatementsAndTypes(context, forceDownloadSchema, maxDepth) {
async function generateStatementsAndTypes(context, forceDownloadSchema,
maxDepth) {
let withoutInit = false;
// Determine if working in an amplify project
try {
context.amplify.getProjectMeta();
} catch (e) {
withoutInit = true;
}

// Check if introspection schema exists
const schema = './schema.json';
const schemaPath = path.join(process.cwd(), schema);
if (!fs.existsSync(schemaPath) && withoutInit) {
throw Error(`Please download the introspection schema and place in ${schemaPath} before codegen when not in an amplify project`);
}

if (withoutInit) {
forceDownloadSchema = false;
}
const config = loadConfig(context);
const projects = config.getProjects();

const { projectPath } = context.amplify.getEnvInfo();
const apis = getAppSyncAPIDetails(context);
if (!projects.length || !apis.length) {
if (!projects.length) {
throw new NoAppSyncAPIAvailableError(constants.ERROR_CODEGEN_NO_API_CONFIGURED);
}
let apis = [];
if (!withoutInit) {
apis = getAppSyncAPIDetails(context);
}
if (!apis.length && !withoutInit) {
throw new NoAppSyncAPIAvailableError(constants.ERROR_CODEGEN_NO_API_CONFIGURED);
}
const project = projects[0];
const { frontend } = project.amplifyExtension;
let projectPath = process.cwd();
if (!withoutInit) {
({ projectPath } = context.amplify.getEnvInfo());
}

const downloadPromises = projects.map(async cfg =>
await ensureIntrospectionSchema(
context,
join(projectPath, cfg.schema),
apis[0],
cfg.amplifyExtension.region,
forceDownloadSchema,
),
);
await Promise.all(downloadPromises);

await generateStatements(context, false, maxDepth);
await generateTypes(context, false);
let downloadPromises;
if (!withoutInit) {
downloadPromises = projects.map(async cfg =>
await ensureIntrospectionSchema(
context,
join(projectPath, cfg.schema),
apis[0],
cfg.amplifyExtension.region,
forceDownloadSchema,
),
);
await Promise.all(downloadPromises);
}
await generateStatements(context, false, maxDepth, withoutInit, frontend);
await generateTypes(context, false, withoutInit, frontend);
}

module.exports = generateStatementsAndTypes;
31 changes: 25 additions & 6 deletions packages/amplify-codegen/src/commands/statements.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,25 @@ const loadConfig = require('../codegen-config');
const constants = require('../constants');
const { ensureIntrospectionSchema, getFrontEndHandler, getAppSyncAPIDetails } = require('../utils');

async function generateStatements(context, forceDownloadSchema, maxDepth) {
async function generateStatements(context, forceDownloadSchema,
maxDepth, withoutInit = false, decoupleFrontend = '') {
const config = loadConfig(context);
const projects = config.getProjects();
const apis = getAppSyncAPIDetails(context);
const { projectPath } = context.amplify.getEnvInfo();
let apis = [];
if (!withoutInit) {
apis = getAppSyncAPIDetails(context);
}
let projectPath = process.cwd();
if (!withoutInit) {
({ projectPath } = context.amplify.getEnvInfo());
}
if (!projects.length || !apis.length) {
if (!withoutInit) {
context.print.info(constants.ERROR_CODEGEN_NO_API_CONFIGURED);
return;
}
}
if (!projects.length && withoutInit) {
context.print.info(constants.ERROR_CODEGEN_NO_API_CONFIGURED);
return;
}
Expand All @@ -22,9 +35,15 @@ async function generateStatements(context, forceDownloadSchema, maxDepth) {
? path.join(projectPath, cfg.amplifyExtension.docsFilePath)
: path.dirname(path.dirname(includeFiles));
const schemaPath = path.join(projectPath, cfg.schema);
const { region } = cfg.amplifyExtension;
await ensureIntrospectionSchema(context, schemaPath, apis[0], region, forceDownloadSchema);
const frontend = getFrontEndHandler(context);
let region;
let frontend;
if (!withoutInit) {
({ region } = cfg.amplifyExtension);
await ensureIntrospectionSchema(context, schemaPath, apis[0], region, forceDownloadSchema);
frontend = getFrontEndHandler(context);
} else {
frontend = decoupleFrontend;
}
const language = frontend === 'javascript' ? cfg.amplifyExtension.codeGenTarget : 'graphql';
const opsGenSpinner = new Ora(constants.INFO_MESSAGE_OPS_GEN);
opsGenSpinner.start();
Expand Down
Loading

0 comments on commit 47a0f67

Please sign in to comment.