amplify-category-api
amplify-category-api copied to clipboard
Support AppSync JavaScript Resolvers
Is this feature request related to a new or existing Amplify category?
No response
Is this related to another service?
Appsync JavaScript resolvers
Describe the feature you'd like to request
New feature in appsync how to use within amplify?
https://aws.amazon.com/blogs/aws/aws-appsync-graphql-apis-supports-javascript-resolvers/
Describe the solution you'd like
Steps to use within amplify
Describe alternatives you've considered
Manual work around that doesn't change the way we deploy
Additional context
No response
Is this something that you'd be interested in working on?
- [ ] 👋 I may be able to implement this feature request
Would this feature include a breaking change?
- [ ] ⚠️ This feature might incur a breaking change
bump
Need this soon please!
Third'd - this would be a great feature to have!
Would be much appreciated by developers
We would appreciate this too!
bump
bump!
bump
bump!!
➕ 1️⃣
bump
Honestly changing all the vlt templates to JS would likely enable to Amplify community to issue patches easier and fixes / plugins for issues surrounding resolvers.
Any plans for this rebuild of the resolvers?
bump
bump
Seems like AWS phases out of VTL if favor of APPSYNC_JS (source: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference.html),
are there any updates on this feature?
bump
its a nightmare to do graphql with appsync.. i update to node 16, update my sls to 3, update appsync plugin to support js resolver and, what, the simulator broke everything
Hi - while we update our documentation to illustrate how to do this with the Amplify CLI, I do want to bring attention to the fact that the GraphQL API category is now available first-class as a CDK construct. In the CDK construct, you can use JavaScript resolvers. Check out our announcement post here: https://aws.amazon.com/blogs/mobile/announcing-aws-amplifys-graphql-api-cdk-construct-deploy-real-time-graphql-api-and-data-stack-on-aws/
Yes please
This would be lovely, yes please!
bump
bump
BUMP
bump 🤭
@renebrandel - you mentioned there'd be updates to the documentation, but in the mean time, can we get even a rough overview/walkthrough of how to do it "by hand" for existing amplify projects that are cli-dependent/cli-generated?
Please? :)
I took a look here: https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html
And then I got impatient, and thought maybe I'd give this a try. I kinda took a sledgehammer to it, so please forgive me if there are more elegant ways to achieve this.
In case anybody is as masochistic as I am, I think I got pretty close with this.
I don't think it works yet (it's 4:00 AM here and I need to sleep), but it's a close-enough starting point, in case anyone wants to hack on this together.
👉 If anyone does bother to try this, and is successful (or finds ways to make it work), please share back your solution 😎.
amplify add custom --> name: MyCustomResolvers
cdk-stack.ts
import type { Construct } from 'constructs'
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper'
import * as cdk from 'aws-cdk-lib'
import * as appsync from 'aws-cdk-lib/aws-appsync'
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'
import type { AmplifyDependentResourcesAttributes } from '../../types/amplify-dependent-resources-ref'
export class cdkStack extends cdk.Stack {
constructor(
scope: Construct,
id: string,
props?: cdk.StackProps,
amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps,
) {
super(scope, id, props)
/* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
const _env = new cdk.CfnParameter(this, 'env', {
type: 'String',
description: 'Current Amplify CLI env name',
})
// Get the project name from AmplifyHelper
// and create a standard prefix for all resources - "projectName-env"
const { projectName, envName } = AmplifyHelpers.getProjectInfo()
const _resourcePrefix = `${projectName}-${envName}`
/*
* 🛑 📢
* There is a known bug (https://github.com/aws-amplify/amplify-cli/issues/13532) that *may* prevent
* the use of the addResourceDependency function from AmplifyHelpers.
*
* If you run into that bug, you can use the following workaround to reference dependent resources in your CDK stack.
*
* The formula is: category + resourceName + outputName
*
* For a GraphQL API example: apiMyApiNameGraphQLAPIIdOutput
* For an S3 Storage example: storageMyProjectStorageStorageBucketName
*
* Where:
* category: api
* resourceName: <YOUR_API_NAME>
* outputName: GraphQLAPIIdOutput
*
* const resourceCategory = 'api'
* const resourceName = 'myprojectV2AwesomeAPI'
* const outputName = 'GraphQLAPIIdOutput'
* const GraphQLAPIIdOutput = resourceCategory + resourceName + outputName
*
*/
const apiResourceReference: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(
this,
amplifyResourceProps.category,
amplifyResourceProps.resourceName,
[
{
category: 'api',
resourceName: 'myprojectV2AwesomeAPI',
},
],
)
// Instantiate a reference to the API using the API ID from the Amplify-generated stack
const api = appsync.GraphqlApi.fromGraphqlApiAttributes(this, 'api', {
graphqlApiId: apiResourceReference.api.myprojectV2AwesomeAPI.GraphQLAPIIdOutput,
})
// Time to get our CloudFormation on - there's no escaping it!
const graphqlApiId = apiResourceReference.api.myprojectV2AwesomeAPI.GraphQLAPIIdOutput
const tableName = 'UserTable'
const importString = `\${${graphqlApiId}}:GetAtt:${tableName}:Name`
/* Get the name of the table using cloudformation stack outputs
* We are attempting to mimic this:
*
* "Fn::ImportValue": {
* "Fn::Sub": "${apimyprojectV2AwesomeAPIGraphQLAPIIdOutput}:GetAtt:UserTable:Name"
* }
*/
// Get the name of the table using cloudformation stack outputs - e.g. User-5mt2wm3hzrgptjlq7qcbryxcgi-mybackend
const UserTableName = cdk.Fn.importValue(cdk.Fn.sub(importString))
// Instantiate a reference to the DynamoDB table using the table name from the Amplify-generated stack
const userTableDDB = dynamodb.Table.fromTableName(this, 'table', UserTableName)
// Create a new AppSync function and pass in the API and the DynamoDB table objects
const appsyncFuncScanUsersTable = new appsync.AppsyncFunction(this, 'func-scan-users', {
name: 'scan_users_func_1',
api,
dataSource: api.addDynamoDbDataSource('table-for-posts', userTableDDB),
code: appsync.Code.fromInline(`
export function request(ctx) {
return { operation: 'Scan' };
}
export function response(ctx) {
return ctx.result.items;
}
`),
runtime: appsync.FunctionRuntime.JS_1_0_0,
})
// Create a new AppSync resolver
const _resolver = new appsync.Resolver(this, 'custom-resolver', {
api,
typeName: 'Query',
fieldName: 'getPost',
code: appsync.Code.fromInline(`
export function request(ctx) {
return {};
}
export function response(ctx) {
return ctx.prev.result;
}
`),
runtime: appsync.FunctionRuntime.JS_1_0_0,
pipelineConfig: [appsyncFuncScanUsersTable],
})
}
}
package.json
{
"name": "custom-resource",
"version": "1.0.0",
"description": "",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@aws-amplify/cli-extensibility-helper": "^3.0.25",
"aws-cdk-lib": "~2.80.0",
"constructs": "^10.3.0"
},
"devDependencies": {
"typescript": "^5.4.2"
},
"resolutions": {
"aws-cdk-lib": "~2.80.0"
}
}
^^ This gets close, but it won't work. There's 16 hours of my life I won't get back. Maybe someone can figure out what I'm doing wrong by trying it themselves. I'm good and stuck.
Abandon all hope, ye who enter here. Waiting for any help or instruction from @renebrandel & our Amplify friends... 🫠
Hi - @armenr - sorry for the dropping the ball here. So here's a working sample that should work for you.
For the JS resolvers, I build a quick "echo this message" resolver example. The graphQL schema looks like this:
input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!
type Todo @model {
id: ID!
name: String!
description: String
}
type Query {
echo(message: String): String # your custom queries here
}
The custom stack looks like this:
import * as cdk from 'aws-cdk-lib';
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import { AmplifyDependentResourcesAttributes } from '../../types/amplify-dependent-resources-ref';
import { Construct } from 'constructs';
const jsResolverTemplate = `
export function request(ctx) {
return {
payload: null
}
}
export function response(ctx) {
return ctx.arguments.message
}
`
export class cdkStack extends cdk.Stack {
constructor(
scope: Construct,
id: string,
props?: cdk.StackProps,
amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps
) {
super(scope, id, props);
/* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
new cdk.CfnParameter(this, 'env', {
type: 'String',
description: 'Current Amplify CLI env name'
});
// Access other Amplify Resources
const retVal: AmplifyDependentResourcesAttributes =
AmplifyHelpers.addResourceDependency(
this,
amplifyResourceProps.category,
amplifyResourceProps.resourceName,
[
{
category: 'api',
resourceName: 'gen1jsresolver'
}
]
);
const resolver = new appsync.CfnResolver(this, 'CustomResolver', {
// apiId: retVal.api.new.GraphQLAPIIdOutput,
// https://github.com/aws-amplify/amplify-cli/issues/9391#event-5843293887
// If you use Amplify you can access the parameter via Ref since it's a CDK parameter passed from the root stack.
// Previously the ApiId is the variable Name which is wrong , it should be variable value as below
apiId: cdk.Fn.ref(retVal.api.gen1jsresolver.GraphQLAPIIdOutput),
fieldName: 'echo',
typeName: 'Query', // Query | Mutation | Subscription
code: jsResolverTemplate,
dataSourceName: 'NONE_DS', // DataSource name
runtime: {
name: 'APPSYNC_JS',
runtimeVersion: '1.0.0'
}
});
}
}
Do you mind sharing more about the exact error you're facing? My guess is that this line is probably where the error is coming from:
graphqlApiId: apiResourceReference.api.myprojectV2AwesomeAPI.GraphQLAPIIdOutput,
My guess is that the resolution of the reference doesn't happen correctly, thus the API won't be referenced. It should be this:
graphqlApiId: cdk.Fn.ref(apiResourceReference.api.myprojectV2AwesomeAPI.GraphQLAPIIdOutput),
@armenr - also cut a docs PR https://github.com/aws-amplify/docs/pull/7087