aws / aws-appsync-community

The AWS AppSync community
https://aws.amazon.com/appsync
Apache License 2.0
506 stars 32 forks source link

Numbers from DynamoDB results can't be converted to string #308

Open sashee opened 1 year ago

sashee commented 1 year ago

I have items coming from DynamoDB. When a field is a number then when I use something like ctx.result.num + "" the result is "null".

For example, I have a table with this item:

In the resolver, I get this item:

export function request(ctx) {
    return {
        version : "2018-05-29",
        operation : "GetItem",
        key : {
            id : {S: "1"}
        },
        consistentRead : true
    }
}

In the response handler, I try to convert the field to a string:

export function response(ctx) {
    return {
        res: ctx.result.num,
        normal: ctx.result.num + "",
        fixed: ctx.result.num + 0 + "",
    }
}

The result I get:

{"res":100,"normal":"null","fixed":"100"}"

Both the typeof ctx.result.num and typeof (ctx.result.num + 0) yields number, but there is clearly a difference between them.

A full reproduction example:

provider "aws" {
}
resource "random_id" "id" {
  byte_length = 8
}
resource "aws_iam_role" "appsync" {
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Effect": "Allow"
    }
  ]
}
EOF
}
data "aws_iam_policy_document" "appsync" {
  statement {
    actions = [
      "dynamodb:GetItem",
    ]
    resources = [
      aws_dynamodb_table.test.arn,
    ]
  }
}
resource "aws_iam_role_policy" "appsync" {
  role   = aws_iam_role.appsync.id
  policy = data.aws_iam_policy_document.appsync.json
}
resource "aws_appsync_graphql_api" "appsync" {
  name                = "test"
  schema              = <<EOF
type Query {
    test: AWSJSON
}
schema {
    query: Query
}
EOF
  authentication_type = "AWS_IAM"
}
resource "aws_appsync_datasource" "ddb_test" {
  api_id           = aws_appsync_graphql_api.appsync.id
  name             = "ddb_test"
  service_role_arn = aws_iam_role.appsync.arn
  type             = "AMAZON_DYNAMODB"
  dynamodb_config {
    table_name = aws_dynamodb_table.test.name
  }
}

resource "aws_dynamodb_table" "test" {
  name         = "test-${random_id.id.hex}"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "id"
  attribute {
    name = "id"
    type = "S"
  }
}

resource "aws_dynamodb_table_item" "item" {
  table_name = aws_dynamodb_table.test.name
  hash_key   = aws_dynamodb_table.test.hash_key
  item = <<ITEM
{
  "id": {"S": "1"},
    "num": {"N": "100"}
}
ITEM
}

resource "aws_appsync_resolver" "test" {
  api_id = aws_appsync_graphql_api.appsync.id
  type              = "Query"
  field             = "test"
  runtime {
    name            = "APPSYNC_JS"
    runtime_version = "1.0.0"
  }
  code = <<EOF
export function request(ctx) {
    return {};
}
export function response(ctx) {
    return ctx.result;
}
EOF
  kind = "PIPELINE"
  pipeline_config {
    functions = [
      aws_appsync_function.test.function_id,
    ]
  }
}
resource "aws_appsync_function" "test" {
  api_id            = aws_appsync_graphql_api.appsync.id
  data_source       = aws_appsync_datasource.ddb_test.name
    name = "test"
  runtime {
    name            = "APPSYNC_JS"
    runtime_version = "1.0.0"
  }
  code = <<EOF
import {util} from "@aws-appsync/utils";
export function request(ctx) {
    return {
        version : "2018-05-29",
        operation : "GetItem",
        key : {
            id : {S: "1"}
        },
        consistentRead : true
    }
}
export function response(ctx) {
    if (ctx.error) {
        return util.error(ctx.error.message, ctx.error.type);
    }
    return {
        res: ctx.result.num,
        normal: ctx.result.num + "",
        fixed: ctx.result.num + 0 + "",
    }
}
EOF
}
query MyQuery {
  test
}