@aws-amplify/amplify-category-api
Version:
Amplify CLI API Category Plugin
99 lines (88 loc) • 4.48 kB
text/typescript
import * as path from 'path';
import { $TSContext, AmplifyError, ApiCategoryFacade } from '@aws-amplify/amplify-cli-core';
import { printer } from '@aws-amplify/amplify-prompts';
import fs from 'fs-extra';
import _ from 'lodash';
import { SQL_SCHEMA_FILE_NAME, ImportedDataSourceConfig, ImportedRDSType } from '@aws-amplify/graphql-transformer-core';
import { graphqlSchemaFromSQLSchema } from '@aws-amplify/graphql-schema-generator';
import { getAppSyncAPIName, getAPIResourceDir } from '../../provider-utils/awscloudformation/utils/amplify-meta-utils';
import {
storeConnectionSecrets,
getSecretsKey,
getDatabaseName,
getConnectionSecrets,
} from '../../provider-utils/awscloudformation/utils/rds-resources/database-resources';
import { writeSchemaFile, generateRDSSchema } from '../../provider-utils/awscloudformation/utils/graphql-schema-utils';
import { PREVIEW_BANNER } from '../../category-constants';
import { parse } from 'graphql';
import { getEngineInput } from '../../provider-utils/awscloudformation/utils/rds-input-utils';
const subcommand = 'generate-schema';
export const name = subcommand;
export const run = async (context: $TSContext): Promise<void> => {
const transformerVersion = await ApiCategoryFacade.getTransformerVersion(context);
if (transformerVersion !== 2) {
throw new AmplifyError('InvalidDirectiveError', {
message: 'Imported SQL schema can only generate a GraphQL schema with the version 2 transformer.',
});
}
const sqlSchema = context.parameters?.options?.['sql-schema'];
const engineType = context.parameters?.options?.['engine-type'];
const out = context.parameters?.options?.out;
// unauthenticated flow
if (sqlSchema || engineType || out) {
if (!(sqlSchema && engineType && out)) {
if (!sqlSchema) {
throw new AmplifyError('UserInputError', { message: 'A SQL schema must be provided with --sql-schema' });
}
if (!engineType) {
throw new AmplifyError('UserInputError', { message: 'An engine type must be provided with --engine-type' });
}
if (!out) {
throw new AmplifyError('UserInputError', { message: 'An output path must be provided with --out' });
}
}
if (!Object.values(ImportedRDSType).includes(engineType)) {
throw new AmplifyError('UserInputError', { message: `${engineType} is not a supported engine type.` });
}
if (!fs.existsSync(sqlSchema)) {
throw new AmplifyError('UserInputError', { message: `SQL schema file ${sqlSchema} does not exists.` });
}
const schema = await graphqlSchemaFromSQLSchema(fs.readFileSync(sqlSchema, 'utf8'), engineType);
writeSchemaFile(out, schema);
} else {
printer.warn(PREVIEW_BANNER);
const apiName = getAppSyncAPIName();
const apiResourceDir = getAPIResourceDir(apiName);
// proceed if there are any existing imported Relational Data Sources
const pathToSchemaFile = path.join(apiResourceDir, SQL_SCHEMA_FILE_NAME);
if (!fs.existsSync(pathToSchemaFile)) {
throw new AmplifyError('UserInputError', { message: 'No imported Data Sources to Generate GraphQL Schema.' });
}
const importedSchema = parse(fs.readFileSync(pathToSchemaFile, 'utf8'));
const engine = await getEngineInput(importedSchema);
const secretsKey = getSecretsKey();
const database = await getDatabaseName(context, apiName, secretsKey);
if (!database) {
throw new AmplifyError('UserInputError', {
message:
'Cannot fetch the imported database name to generate the schema. Use "amplify api update-secrets" to update the database information.',
});
}
// read and validate the RDS connection secrets
const { secrets, storeSecrets } = await getConnectionSecrets(context, secretsKey, engine);
const databaseConfig: ImportedDataSourceConfig = {
...secrets,
engine,
};
const schemaString = await generateRDSSchema(context, databaseConfig, pathToSchemaFile);
// If connection is successful, store the secrets in parameter store
if (storeSecrets) {
await storeConnectionSecrets(context, secrets, apiName, secretsKey);
}
writeSchemaFile(pathToSchemaFile, schemaString);
if (_.isEmpty(schemaString)) {
printer.warn('If your schema file is empty, it is likely that your database has no tables.');
}
printer.info(`Successfully imported the schema definition for ${databaseConfig.database} database into ${pathToSchemaFile}`);
}
};