UNPKG

@aws-amplify/amplify-category-api

Version:
88 lines (74 loc) 3.48 kB
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();