1

I am having an issue while creating AWS::Appsync:Resolver Cloudformation in Serverless Framework using Javascript resolver.

My Javascript Resolver code in root dir /src/resolvers/jsResolver.js which I have attached to AWS::AppSync::Resolver cloudformation in code block. I have also installed npm plugin for appsync utils in my package.json

import { util } from '@aws-appsync/utils';

 export function request(ctx) {
    const {source, args} = ctx
    return {
    operation: 'Invoke',
    payload: { field: ctx, arguments: args, source },
  };
}

export function response(ctx) {
    util.error("Failed to fetch relatedPosts", "LambdaFailure", ctx.prev.result)
    return ctx.result;
  }

My AWS::AppSync::Resolver Cloudformation is below in YML file also I have used Code as its Mandatory if I have declared it as APPSYNC_JS Runtime

AppSyncJsResolver:
  Type: AWS::AppSync::Resolver 
  Properties:
    ApiId: !GettAtt Graphql.APiId
    Kind: PIPELINE
    Code: ./src/resolvers/jsResolver.js <—- Here my code is breaking up with error contains one or more error
    TypeName: Query
    FieldName: getInfo
    Runtime:
      Name: APPSYNC_JS
      RuntimeVersion: 1.0.0
    PipelineConfig:
      Functions:
        - !GetAtt AppSyncFunction.FunctionId 

I have tried above code as per AWS Cloudformation documentation for Appsync available where they have mentioned that in AWS::AppSync::Resolver for creating Javascript Resolver using Cloudformation as below one of the properties. which I have included in my AWS::AppSync::Resolver

Code  
  The resolver code that contains the request and response functions. When code is 
  used, the runtime is required. The runtime value must be APPSYNC_JS.

Required: No

Type: String

Required: No

Type: String

So I've tried this and cant find enough solutions regarding Javascript Resolvers all are available with VTL template specific.

With above code my CloudFormation build failed with the following error: An error occurred: AppSyncJSResolver- The code contains one or more errors. (Service: AWSAppSync; Status Code: 400; Error Code: BadRequestException; Request ID: 0245d64d-...; Proxy: null)

  • AppSyncJSResolver- which is my AWS::AppSync::Resolver in above code. and I have code property in that which giving me an error. I have verified with multiple sources and I am not finding any errors with my Javascript Resolver file /src/resolvers/jsResolver.js which I have declared in AppSyncJSResolver AWS::AppSync::Resolver in code property, I am not sure why I’m getting this error, any help would be great.
  • You shouldn't need to install utils anywhere. It's available in the environment already. – Graham Hesketh Feb 13 '23 at 00:21
  • 1
    It might be that if you want to have your code read from file you have to use the CodeS3Location parameter instead of the Code parameter which would treat it as an asset. I think the Code parameter expects inline code. You could also try inlining the code as it is short. I deploy from cdk and I can see it is using the CodeS3Location parameter in the CloudFormation output as my code is read from file. – Graham Hesketh Feb 13 '23 at 00:39
  • 1
    CodeS3Location value would look like: s3://my-bucket-name/my-filename.js The bucket name is probably some bucket SAM is using for deployment assets. – Graham Hesketh Feb 13 '23 at 00:46
  • Hello Graham thanks for your response, but don’t you think if we use S3 bucket for this it will be costly so everytime our appsync make call it will also use resources in S3 which mean our resolver code so wouldn’t it will make it bit costly. And also use storage in S3 bucket. – Cloudformation Feb 13 '23 at 14:46
  • 1
    Code property under Appsync resolver expects a string or a JSON object that represents the code, not the location of the code file. You can include it as a string in the Code parameter. Or as @GrahamHesketh suggested you use s3 to store your resolver files and point it to that location using the CodeS3Location parameter. – salt-pepper Feb 13 '23 at 15:57
  • 1
    @Cloudformation the code for the function is not called from S3 it is only stored there during the deployment phase at which point it is copied into the AppSync function where it is called so there is no lookup to S3 during its actual use. This is how code gets deployed from files in tools such as CDK or SAM and these files are knowns as assets. – Graham Hesketh Feb 13 '23 at 19:22
  • Thanks @GrahamHesketh and salt-pepper for your inputs that what I have thought initially but thanks for clearing out my doubts I will try with suggested solutions. I am getting response back with inline code for now. Now I will implement it using CodeS3Location. One more question how I will write test cases for those file which is gonna be on S3 bucket. Question is kinda silly one but wants to know its flow, as I am not gonna have that resolver js file on my VS code structure. – Cloudformation Feb 13 '23 at 20:37
  • @GrahamHesketh also one follow up question with your previous response if the file in S3 will copied to appsync function, is it safe to remove file at some point let’s say once we deploy our code or we need to keep it. Please also advice how I will write test cases for those resolver files. Thanks – Cloudformation Feb 13 '23 at 20:42
  • Disclaimer, I don't work with SAM so it may be different but I'm guessing it follows very similar principles to CDK. You have a project locally where you write the file and can do local testing prior to deployment, and/or deploy the project to a sandbox cloud environment for testing. The code file will regularly reside in a special bucket reserved for cloud deployments and the "sam deploy" command will send it there on your behalf. You don't manage the file being deployed to S3. The cost of storing it there will be negligible. – Graham Hesketh Feb 14 '23 at 12:11
  • Have a read of how the "sam package" and "sam deploy" commands work, note "sam deploy" will run "sam package" on your behalf. https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-package.html https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html – Graham Hesketh Feb 14 '23 at 12:14
  • @GrahamHesketh I am not using SAM for my deployment I am using Serverless Framework to deploy code from locally to cloud. I have used cloudformation for JavaScript resolver since their plugin doesn’t have support for it yet. So most of js/node files for testing more like unit testing I have locally on VS. – Cloudformation Feb 14 '23 at 14:24
  • Oh ok, still similar concepts should hold in serverless framework. They are all just wrappers for cloudformation at the end of the day. Word of advice from early experience, the JS env in AppSync functions is quite different from what you might expect in node running on your machine. They have limited functionality and so it is worth testing functions in a deployed sandbox and/or in the console. – Graham Hesketh Feb 14 '23 at 15:02
  • 1
    @GrahamHesketh: I have responded with answers thanks for your suggestions. hope this will help to others. – Cloudformation Feb 14 '23 at 17:45

1 Answers1

1

To answering my own question, The way I resolve it via two ways.

1. We can write whole Resolver code in YML Cloudformation in Code property like below. Make sure your resolver code should be inside of your Code property and use "|" special character (Multi-line code) after Code property.

AppSyncJsResolver:
  Type: AWS::AppSync::Resolver 
  Properties:
    ApiId: !GettAtt Graphql.APiId
    Kind: PIPELINE
    Code: | 
         import { util } from '@aws-appsync/utils';
         export function request(ctx) {
         const {source, args} = ctx
         return {
         operation: 'Invoke',
         payload: { field: ctx, arguments: args, source },
        };
        }
        export function response(ctx) {
        util.error("Failed to fetch relatedPosts", "LambdaFailure",ctx.prev.result)
        return ctx.result;
        }
    TypeName: Query
    FieldName: getInfo
    Runtime:
      Name: APPSYNC_JS
      RuntimeVersion: 1.0.0
    PipelineConfig:
      Functions:
        - !GetAtt AppSyncFunction.FunctionId

2. If you want to keep your business logic out of YML file and keep it separate then you can use CodeS3Location property in your javascript resolver like below.

first create bucket in S3 and store your javascript resolver file with your resolver code in bucket. make sure you give enough IAM permission to your appsync to access your S3 bucket.

After above step you can rewrite your YML Cloudformation like below

AppSyncJsResolver:
  Type: AWS::AppSync::Resolver 
  Properties:
    ApiId: !GettAtt Graphql.APiId
    Kind: PIPELINE
    CodeS3Location:s3://my-bucket-name/my-filename.js
    TypeName: Query
    FieldName: getInfo
    Runtime:
      Name: APPSYNC_JS
      RuntimeVersion: 1.0.0
    PipelineConfig:
      Functions:
        - !GetAtt AppSyncFunction.FunctionId

Hope this help others and will contribute more about Javascript Resolver so it will be easier for other to find more complex solutions and get as much as resources about Javascript Resolver. Thanks to @Graham Hesketh for your suggestions.