@aws-amplify/amplify-category-api
Version:
Amplify CLI API Category Plugin
88 lines (74 loc) • 3.48 kB
text/typescript
import path from 'path';
import * as fs from 'fs-extra';
import { DocumentNode, parse } from 'graphql';
import { $TSContext, AmplifyError, ApiCategoryFacade } from '@aws-amplify/amplify-cli-core';
import { constructTransform } from '@aws-amplify/graphql-transformer';
import { SCHEMA_DIR_NAME, SCHEMA_FILENAME } from '../graphql-transformer/constants';
import { generateTransformerOptions } from '../graphql-transformer/transformer-options-v2';
import { contextUtil } from './context-util';
/**
* SchemaReader is a utility point to consolidate and abstract GraphQL Schema reading
* The readSchema method provides a flag to read the un-processed (original) schema
* if desired, but by default the intent of the SchemaReader is to use the preProcess
* utility of the V2 transformer
*/
export class SchemaReader {
private schemaPath: string;
private schemaDocument: DocumentNode;
private preProcessedSchemaDocument: DocumentNode;
getSchemaPath = async (resourceDir: string): Promise<string> => {
if (this.schemaPath) {
return this.schemaPath;
}
const schemaFilePath = path.normalize(path.join(resourceDir, SCHEMA_FILENAME));
const schemaDirPath = path.normalize(path.join(resourceDir, SCHEMA_DIR_NAME));
if (fs.pathExistsSync(schemaFilePath)) {
this.schemaPath = schemaFilePath;
} else if (fs.pathExistsSync(schemaDirPath)) {
this.schemaPath = schemaDirPath;
} else {
throw new AmplifyError('ApiCategorySchemaNotFoundError', {
message: 'No schema found',
resolution: `Your graphql schema should be in either ${schemaFilePath} or ${schemaDirPath}`,
});
}
return this.schemaPath;
};
invalidateCachedSchema = (): void => {
this.schemaPath = null;
this.schemaDocument = null;
this.preProcessedSchemaDocument = null;
};
readSchema = async (context: $TSContext, options: any, usePreProcessing = true): Promise<DocumentNode> => {
const preProcessSchema = usePreProcessing && (await ApiCategoryFacade.getTransformerVersion(context)) === 2;
if (!this.schemaDocument) {
const fileContentsList = new Array<Promise<Buffer>>();
const resourceDir = await contextUtil.getResourceDir(context, options);
const schemaPath = await this.getSchemaPath(resourceDir);
const stats = fs.statSync(schemaPath);
if (stats.isDirectory()) {
fs.readdirSync(schemaPath).forEach((fileName) => {
fileContentsList.push(fs.readFile(path.join(schemaPath, fileName)));
});
} else {
fileContentsList.push(fs.readFile(schemaPath));
}
if (!fileContentsList.length) {
throw new AmplifyError('ApiCategorySchemaNotFoundError', {
message: 'No schema found',
resolution: `Your graphql schema should be in ${schemaPath}`,
});
}
const bufferList = await Promise.all(fileContentsList);
const fullSchema = bufferList.map((buff) => buff.toString()).join('\n');
this.schemaDocument = parse(fullSchema);
}
if (preProcessSchema && !this.preProcessedSchemaDocument) {
const transformerOptions = await generateTransformerOptions(context, options);
const transform = constructTransform(transformerOptions);
this.preProcessedSchemaDocument = transform.preProcessSchema(this.schemaDocument);
}
return preProcessSchema ? this.preProcessedSchemaDocument : this.schemaDocument;
};
}
export const schemaReader = new SchemaReader();