@aws-amplify/amplify-category-api
Version:
Amplify CLI API Category Plugin
116 lines (99 loc) • 4.92 kB
text/typescript
import path from 'path';
import { DynamoDBModelTransformer } from 'graphql-dynamodb-transformer';
import { ModelAuthTransformer } from 'graphql-auth-transformer';
import { ModelConnectionTransformer } from 'graphql-connection-transformer';
import { SearchableModelTransformer } from 'graphql-elasticsearch-transformer';
import { VersionedModelTransformer } from 'graphql-versioned-transformer';
import { FunctionTransformer } from 'graphql-function-transformer';
import { HttpTransformer } from 'graphql-http-transformer';
import { PredictionsTransformer } from 'graphql-predictions-transformer';
import { KeyTransformer } from 'graphql-key-transformer';
import { $TSContext, pathManager, stateManager, CloudformationProviderFacade } from '@aws-amplify/amplify-cli-core';
import { printer } from '@aws-amplify/amplify-prompts';
import { readTransformerConfiguration, TRANSFORM_CONFIG_FILE_NAME, ITransformer, TransformConfig } from 'graphql-transformer-core';
import importFrom from 'import-from';
import importGlobal from 'import-global';
const PROVIDER_NAME = 'awscloudformation';
export const getTransformerFactoryV1 =
(context: $TSContext, resourceDir: string, authConfig?: any) => async (addSearchableTransformer: boolean, storageConfig?: any) => {
const transformerList: ITransformer[] = [
new DynamoDBModelTransformer(),
new VersionedModelTransformer(),
new FunctionTransformer(),
new HttpTransformer(),
new KeyTransformer(),
new ModelConnectionTransformer(),
new PredictionsTransformer(storageConfig),
];
if (addSearchableTransformer) {
transformerList.push(new SearchableModelTransformer());
}
const customTransformersConfig: TransformConfig = await readTransformerConfiguration(resourceDir);
const customTransformers = (
customTransformersConfig && customTransformersConfig.transformers ? customTransformersConfig.transformers : []
)
.map(importTransformerModule)
.map((imported) => {
const CustomTransformer = imported.default;
if (typeof CustomTransformer === 'function') return new CustomTransformer();
if (typeof CustomTransformer === 'object') return CustomTransformer;
throw new Error("Custom Transformers' default export must be a function or an object");
})
.filter((customTransformer) => customTransformer);
if (customTransformers.length > 0) {
transformerList.push(...customTransformers);
}
// TODO: Build dependency mechanism into transformers. Auth runs last
// so any resolvers that need to be protected will already be created.
let amplifyAdminEnabled = false;
try {
const amplifyMeta = stateManager.getMeta();
const appId = amplifyMeta?.providers?.[PROVIDER_NAME]?.AmplifyAppId;
const res = await CloudformationProviderFacade.isAmplifyAdminApp(context, appId);
amplifyAdminEnabled = res.isAdminApp;
} catch (err) {
// if it is not an AmplifyAdmin app, do nothing
}
transformerList.push(new ModelAuthTransformer({ authConfig, addAwsIamAuthInOutputSchema: amplifyAdminEnabled }));
return transformerList;
};
/**
* Attempt to load the module from a transformer name using the following priority order
* - modulePath is an absolute path to an NPM package
* - modulePath is a package name, then it will be loaded from the project's root's node_modules with createRequireFromPath.
* - modulePath is a name of a globally installed package
*/
export const importTransformerModule = (transformerName: string): any => {
const fileUrlMatch = /^file:\/\/(.*)\s*$/m.exec(transformerName);
const modulePath = fileUrlMatch ? fileUrlMatch[1] : transformerName;
if (!modulePath) {
throw new Error(`Invalid value specified for transformer: '${transformerName}'`);
}
let importedModule;
const tempModulePath = modulePath.toString();
try {
if (path.isAbsolute(tempModulePath)) {
// Load it by absolute path
/* eslint-disable-next-line global-require, import/no-dynamic-require */
importedModule = require(modulePath);
} else {
const projectRootPath = pathManager.findProjectRoot();
const projectNodeModules = path.join(projectRootPath, 'node_modules');
try {
importedModule = importFrom(projectNodeModules, modulePath);
} catch {
// Intentionally left blank to try global
}
// Try global package install
if (!importedModule) {
importedModule = importGlobal(modulePath);
}
}
// At this point we've to have an imported module, otherwise module loader, threw an error.
return importedModule;
} catch (error) {
printer.error(`Unable to import custom transformer module(${modulePath}).`);
printer.error(`You may fix this error by editing transformers at ${path.join(transformerName, TRANSFORM_CONFIG_FILE_NAME)}`);
throw error;
}
};