@aws-amplify/amplify-category-api
Version:
Amplify CLI API Category Plugin
107 lines (99 loc) • 4.4 kB
text/typescript
import { CfnResource } from 'aws-cdk-lib';
import * as fs from 'fs-extra';
import * as path from 'path';
import _ from 'lodash';
import { pathManager, stateManager } from '@aws-amplify/amplify-cli-core';
import { Construct } from 'constructs';
import { getAppSyncAPIName } from '../provider-utils/awscloudformation/utils/amplify-meta-utils';
import { ConstructResourceMeta } from './types/types';
import { convertToAppsyncResourceObj, getStackMeta } from './types/utils';
import { AmplifyApiGraphQlResourceStackTemplate } from './cdk-compat/amplify-api-resource-stack-types';
/**
*
* @param scope
* @param overrideDir
*/
export function applyFileBasedOverride(scope: Construct, overrideDirPath?: string): AmplifyApiGraphQlResourceStackTemplate {
const overrideDir = overrideDirPath ?? path.join(pathManager.getBackendDirPath(), 'api', getAppSyncAPIName());
const overrideFilePath = path.join(overrideDir, 'build', 'override.js');
if (!fs.existsSync(overrideFilePath)) {
return {};
}
const stacks: string[] = [];
const amplifyApiObj: any = {};
scope.node.findAll().forEach((node) => {
const resource = node as CfnResource;
if (resource.cfnResourceType === 'AWS::CloudFormation::Stack') {
stacks.push(node.node.id.split('.')[0]);
}
});
scope.node.findAll().forEach((node) => {
const resource = node as CfnResource;
let pathArr;
if (node.node.id === 'Resource') {
pathArr = node.node.path.split('/').filter((key) => key !== node.node.id);
} else {
pathArr = node.node.path.split('/');
}
let constructPathObj: ConstructResourceMeta;
if (resource.cfnResourceType) {
constructPathObj = getStackMeta(pathArr, node.node.id, stacks, resource);
if (!_.isEmpty(constructPathObj.rootStack)) {
// api scope
const field = constructPathObj.rootStack!.stackType;
const { resourceName } = constructPathObj;
_.set(amplifyApiObj, [field, resourceName], resource);
} else if (!_.isEmpty(constructPathObj.nestedStack)) {
const fieldType = constructPathObj.nestedStack!.stackType;
const fieldName = constructPathObj.nestedStack!.stackName;
const { resourceName } = constructPathObj;
if (constructPathObj.resourceType.includes('Resolver')) {
_.set(amplifyApiObj, [fieldType, fieldName, 'resolvers', resourceName], resource);
} else if (constructPathObj.resourceType.includes('FunctionConfiguration')) {
_.set(amplifyApiObj, [fieldType, fieldName, 'appsyncFunctions', resourceName], resource);
} else {
_.set(amplifyApiObj, [fieldType, fieldName, resourceName], resource);
}
}
}
});
const appsyncResourceObj = convertToAppsyncResourceObj(amplifyApiObj);
const { envName } = stateManager.getLocalEnvInfo();
const { projectName } = stateManager.getProjectConfig();
const projectInfo = {
envName,
projectName,
};
try {
// TODO: Invoke `runOverride` from CLI core once core refactor is done, and
// this function can become async https://github.com/aws-amplify/amplify-cli/blob/7bc0b5654a585104a537c1a3f9615bd672435b58/packages/amplify-cli-core/src/overrides-manager/override-runner.ts#L4
// before importing the override file, we should clear the require cache to avoid
// importing an outdated version of the override file
// see: https://github.com/nodejs/modules/issues/307
// and https://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate
delete require.cache[require.resolve(overrideFilePath)];
const overrideImport = require(overrideFilePath);
if (overrideImport && overrideImport?.override && typeof overrideImport?.override === 'function') {
overrideImport.override(appsyncResourceObj, projectInfo);
}
} catch (err) {
throw new InvalidOverrideError(err);
}
return appsyncResourceObj;
}
/**
*
*/
export class InvalidOverrideError extends Error {
details: string;
resolution: string;
constructor(error: Error) {
super('Executing overrides failed.');
this.name = 'InvalidOverrideError';
this.details = error.message;
this.resolution = 'There may be runtime errors in your overrides file. If so, fix the errors and try again.';
if ((Error as any).captureStackTrace) {
(Error as any).captureStackTrace(this, InvalidOverrideError);
}
}
}