Skip to content

Instantly share code, notes, and snippets.

@jakubknejzlik
Last active August 25, 2023 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakubknejzlik/9d7829038c46f49b169c959ea52dfaab to your computer and use it in GitHub Desktop.
Save jakubknejzlik/9d7829038c46f49b169c959ea52dfaab to your computer and use it in GitHub Desktop.
CDK AppSync SFN DataSource
import { Construct } from "constructs";
import {
BaseResolverProps,
GraphqlApi,
HttpDataSource,
HttpDataSourceProps,
MappingTemplate,
} from "aws-cdk-lib/aws-appsync";
import { Stack } from "aws-cdk-lib";
import { StateMachine } from "aws-cdk-lib/aws-stepfunctions";
type AppsyncStateFunctionDataSourceType = "sync" | "async";
interface AppsyncStateFunctionDataSourceProps extends HttpDataSourceProps {
type: AppsyncStateFunctionDataSourceType;
}
export class AppsyncStateFunctionDataSource extends HttpDataSource {
private type: AppsyncStateFunctionDataSourceType;
constructor(
scope: Construct,
id: string,
props: Omit<AppsyncStateFunctionDataSourceProps, "endpoint">
) {
const { type, ...rest } = props;
const stack = Stack.of(scope);
super(scope, id, {
name: `StepFunctionsAsyncDataSource`,
description: "from appsync to StepFunctions",
authorizationConfig: {
signingRegion: stack.region,
signingServiceName: "states",
},
endpoint:
type === "async"
? `https://states.${stack.region}.amazonaws.com`
: `https://sync-states.${stack.region}.amazonaws.com`,
...rest,
});
this.type = type;
}
static fromApi(
scope: Construct,
id: string,
api: GraphqlApi,
type: "sync" | "async"
) {
return new AppsyncStateFunctionDataSource(scope, id, { api, type });
}
static fromApiAsync(scope: Construct, id: string, api: GraphqlApi) {
return new AppsyncStateFunctionDataSource(scope, id, {
api,
type: "async",
});
}
static fromApiSync(scope: Construct, id: string, api: GraphqlApi) {
return new AppsyncStateFunctionDataSource(scope, id, { api, type: "sync" });
}
public createResolver(
id: string,
config: {
stateMachine: StateMachine;
} & BaseResolverProps
) {
const { typeName, fieldName, stateMachine, ...rest } = config;
const execution =
this.type === "async" ? "StartExecution" : "StepFunctionsSync";
stateMachine.grant(this, `states:${execution}`);
return super.createResolver(id, {
typeName,
fieldName,
requestMappingTemplate: MappingTemplate.fromString(`
{
"version": "2018-05-29",
"method": "POST",
"resourcePath": "/",
"params": {
"headers": {
"content-type": "application/x-amz-json-1.0",
"x-amz-target":"AWSStepFunctions.${execution}"
},
"body": {
"stateMachineArn": "${stateMachine.stateMachineArn}",
"input": $utils.toJson($utils.toJson($ctx.args))
}
}
}`),
responseMappingTemplate: MappingTemplate.fromString(`
#set($body = $util.parseJson($context.result.body))
#if ($context.result.statusCode != 200)
$util.error($body.Message,$context.result.statusCode)
#else
#if ($body.status == "FAILED")
$util.error($body.cause,$body.status)
#end
${this.type === "async" ? "$context.result.body" : "$body.output"}
#end
`),
...rest,
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment