Skip to content

Commit

Permalink
wip preprocess schema hook for populating conversation supporting types
Browse files Browse the repository at this point in the history
  • Loading branch information
atierian committed Oct 11, 2024
1 parent 8a42356 commit eebcd28
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,39 @@ const getSchema = (fileName: string, substitutions: Record<string, string> = {})
const replaced = schema.replace(new RegExp(key, 'g'), value);
schema = replaced;
});
return schema + '\n' + conversationSchemaTypes;
return schema; // + '\n' + conversationSchemaTypes;
};

it('testme', () => {
const routeName = 'pirateChat';
const inputSchema = getSchema('conversation-route-custom-handler.graphql', { ROUTE_NAME: routeName });

const transformerManager = new TransformManager();
const stack = transformerManager.getTransformScope();
const customHandler = new Function(stack, 'conversation-handler', {
runtime: Runtime.NODEJS_18_X,
code: Code.fromInline('exports.handler = async (event) => { return "Hello World"; }'),
handler: 'index.handler',
});

const functionMap = {
[`Fn${routeName}`]: customHandler,
};

const out = transform(inputSchema, {}, defaultAuthConfig, functionMap, transformerManager);
expect(out).toBeDefined();

const expectedCustomHandlerArn = out.rawRootStack.resolve(customHandler.functionArn);
const conversationLambdaStackName = `${toUpper(routeName)}ConversationDirectiveLambdaStack`;
const conversationLambdaDataSourceName = `Fn${routeName}LambdaDataSource`;
const conversationLambdaDataSourceFunctionArnRef =
out.stacks[conversationLambdaStackName].Resources?.[conversationLambdaDataSourceName].Properties.LambdaConfig.LambdaFunctionArn.Ref;
const lambdaDataSourceFunctionArn =
out.rootStack.Resources?.[conversationLambdaStackName].Properties?.Parameters?.[conversationLambdaDataSourceFunctionArnRef];
expect(lambdaDataSourceFunctionArn).toEqual(expectedCustomHandlerArn);
});


describe('ConversationTransformer', () => {
describe('valid schemas', () => {
it.each([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
TransformerAuthProvider,
TransformerContextProvider,
TransformerPrepareStepContextProvider,
TransformerPreProcessContextProvider,
TransformerSchemaVisitStepContextProvider,
} from '@aws-amplify/graphql-transformer-interfaces';
import { DirectiveNode, FieldDefinitionNode, InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { DirectiveNode, FieldDefinitionNode, InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode, OperationDefinitionNode } from 'graphql';
import { ConversationModel } from './graphql-types/session-model';
import { MessageModel } from './graphql-types/message-model';
import { type ToolDefinition, type Tools } from './utils/tools';
Expand Down Expand Up @@ -67,6 +68,28 @@ export class ConversationTransformer extends TransformerPluginBase {
this.resolverGenerator = new ConversationResolverGenerator(functionNameMap);
}

preValidateSchema = (ctx: TransformerContextProvider): void => {
const mutations = ctx.inputDocument.definitions.filter(
(def): def is ObjectTypeDefinitionNode => def.kind === 'ObjectTypeDefinition' && def.name.value === 'Mutation',
);

const conversationMutations = mutations
.map((mut) => mut.fields)
.flat()
.map((field) => field?.directives)
.flat()
.find((directive): directive is DirectiveNode => directive?.name.value === 'conversation');

if (conversationMutations === undefined) {
console.log('no conversation mutations found');
return;
}

// TODO: add supporting types for conversation routes
// This is going to be a pain because DocumentNode.definitions is readonly.
// Maybe preValidateSchema can follow a similar pattern to mutateSchema and return a modified document?
};

/**
* Processes a field with the @conversation directive
* @param parent - The parent object type definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,13 @@ export class GraphQLTransform {
allModelDefinitions = allModelDefinitions.concat(...transformer.typeDefinitions, transformer.directive);
}

// Option 1. Add a preprocess step that corrects the schema before initial validation.
for (const transformer of this.transformers) {
if (isFunction(transformer.preValidateSchema)) {
transformer.preValidateSchema(context);
}
}

const errors = validateModelSchema({
kind: Kind.DOCUMENT,
definitions: allModelDefinitions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ export interface TransformerPluginProvider {

typeDefinitions: TypeDefinitionNode[];

/**
* A pre-processing step executed prior to and separate from initial GraphQL schema validation.
* This method is used by plugins to make any necessary schema modifications
* before validation is done.
*/
preValidateSchema?: (context: TransformerContextProvider) => void;

/**
* The first method call in the pre-processing lifecycle giving opportunity
* to build metadata prior to the mutation step which returns a mutated
Expand Down

0 comments on commit eebcd28

Please sign in to comment.