Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't send AWSJSON array values using aws-amplify and graphql #13298

Open
3 tasks done
rodrigogs opened this issue Apr 26, 2024 · 3 comments
Open
3 tasks done

Can't send AWSJSON array values using aws-amplify and graphql #13298

rodrigogs opened this issue Apr 26, 2024 · 3 comments
Assignees
Labels
GraphQL Related to GraphQL API issues question General question

Comments

@rodrigogs
Copy link

Before opening, please confirm:

JavaScript Framework

Vue

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify CLI

Environment information

# Put output below this line

  System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 63.16 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.19.0 - ~/.nvm/versions/node/v18.19.0/bin/node
    npm: 10.3.0 - ~/.nvm/versions/node/v18.19.0/bin/npm
    pnpm: 9.0.6 - ~/.nvm/versions/node/v18.19.0/bin/pnpm
  Browsers:
    Safari: 17.4.1
  npmPackages:
    @aws-sdk/client-dynamodb: ^3.556.0 => 3.556.0 
    @aws-sdk/lib-dynamodb: ^3.556.0 => 3.556.0 
    @mdi/font: ^7.4.47 => 7.4.47 
    @nuxt/eslint: ^0.3.9 => 0.3.9 
    @nuxtjs/i18n: ^8.3.0 => 8.3.1 
    @vee-validate/nuxt: ^4.12.6 => 4.12.6 
    @vee-validate/yup: ^4.12.6 => 4.12.6 
    aws-amplify: ^6.0.30 => 6.0.30 
    date-fns: ^3.6.0 => 3.6.0 
    nuxt: ^3.11.2 => 3.11.2 
    vite-plugin-vuetify: ^2.0.3 => 2.0.3 
    vue: ^3.4.21 => 3.4.25 
    vue-router: ^4.3.0 => 4.3.2 
    vuetify: ^3.5.16 => 3.5.17 
    yup: ^1.4.0 => 1.4.0 
  npmGlobalPackages:
    corepack: 0.22.0
    gpt-context-feeder: 0.0.1
    npm: 10.3.0
    pnpm: 9.0.6
    tunnelmole: 2.2.14

Describe the bug

I'm developing an application using Nuxt 3 and Amplify.

  • I created a data model using Ampify Studio:
    enum EventType {
      ECONOMY
      BUSINESS
      POLITICS
      SPORTS
      TECHNOLOGY
      ENTERTAINMENT
      OTHER
    }
    
    type Event @model @auth(rules: [{allow: public}]) {
      id: ID!
      type: EventType!
      title: String!
      description: String!
      date: AWSDate!
      relatedLinks: [AWSJSON]
      involvedPeople: [AWSJSON]
      involvedOrgs: [AWSJSON]
    }
  • I configured Amplify in my application:
    .graphqlconfig.yml
    projects:
    campobomonline:
     schemaPath: amplify/backend/api/campobomonline/build/schema.graphql
     includes:
       - lib/graphql/**/*.ts
     excludes:
       - ./amplify/**
       - lib/API.ts
     extensions:
       amplify:
         codeGenTarget: typescript
         generatedFileName: lib/API.ts
         docsFilePath: lib/graphql
         region: us-west-1
         apiId: null
         maxDepth: 2
    plugins/aws-amplify.ts
     import { Amplify } from 'aws-amplify'
     import awsExports from '~/lib/aws-exports'
     
     Amplify.configure(awsExports)
  • When sending empty JSONs, it works. But when I have any items I get { data: null, errors: [ { path: null, locations: [Array], message: "Variable 'involvedPeople' has an invalid value." } ] }
    dao.ts
    import { generateClient } from 'aws-amplify/api'
    import { createEvent, updateEvent, deleteEvent } from '~/lib/graphql/mutations'
    import { getEvent, listEvents } from '~/lib/graphql/queries'
    import type { EventPage } from '~/lib/events/model'
    import { type Event, type CreateEventInput, type UpdateEventInput, type DeleteEventInput, EventType } from '~/lib/API'
    
    class EventsDAO {
      private client
    
      constructor() {
        this.client = generateClient()
      }
    
      ...
      async createEvent(createInput: CreateEventInput): Promise<Event> {
        return await this.client.graphql({
          query: createEvent,
          variables: {
            input: {
              type: EventType.ECONOMY,
              title: 'Lorem ipsum dolor sit amet',
              description: 'Lorem ipsum dolor sit amet',
              date: '1970-01-01Z',
              // WORKS!
              relatedLinks: [],
              // DOESNT WORK!
              involvedPeople: ['foo'],
              involvedOrgs: [],
            },
          },
        }).then(({ data }) => data.createEvent)
      }
      ...
    
    }

Expected behavior

I should be able to send a JSON with items to the backend through the graphql API.

Reproduction steps

  1. Create a nuxt project https://nuxt.com/docs/getting-started/installation
  2. Configure Amplify https://nuxt.com/deploy/aws-amplify
  3. Create a schema having some JSON property using Amplify Studio and pull it from the cloud using amplify-cli. Follow Amplify instructions to configure it.
  4. Try to send a JSON with items using the graphql library.

Code Snippet

// Put your code below this line.
import { generateClient } from 'aws-amplify/api'
import { createEvent, updateEvent, deleteEvent } from '~/lib/graphql/mutations'
import { getEvent, listEvents } from '~/lib/graphql/queries'
import type { EventPage } from '~/lib/events/model'
import type { EventType, Event, CreateEventInput, UpdateEventInput, DeleteEventInput } from '~/lib/API'

class EventsDAO {
  private client

  constructor() {
    this.client = generateClient()
  }

  async createEvent(createInput: CreateEventInput): Promise<Event> {
    return this.client.graphql({
      query: createEvent,
      variables: {
        input: createInput,
      },
    }).then(({ data }) => data.createEvent)
  }

  async getEventById(id: string): Promise<Event> {
    return this.client.graphql({
      query: getEvent,
      variables: {
        id,
      },
    }).then(({ data }) => {
      if (!data.getEvent) {
        throw createError({ status: 404, message: 'Event not found' })
      }
      return data.getEvent
    })
  }

  async updateEvent(updateInput: UpdateEventInput): Promise<Event> {
    await this.getEventById(updateInput.id) // Check if event exists

    // TODO: Implement optimistic locking

    return this.client.graphql({
      query: updateEvent,
      variables: {
        input: updateInput,
      },
    }).then(({ data }) => data.updateEvent)
  }

  async deleteEvent(deleteInput: DeleteEventInput): Promise<void> {
    await this.client.graphql({
      query: deleteEvent,
      variables: {
        input: deleteInput,
      },
    }).then(({ data }) => {
      if (!data.deleteEvent) {
        throw createError({ status: 404, message: 'Event not found' })
      }
    })
  }

  async queryEventsByType(type: EventType, nextToken?: string | null): Promise<EventPage> {
    const results = await this.client.graphql({
      query: listEvents,
      variables: {
        filter: {
          type: {
            eq: type,
          },
        },
        nextToken,
      },
    })

    return {
      items: results.data.listEvents.items,
      nextToken: results.data.listEvents.nextToken,
    }
  }
}

export default EventsDAO

Log output

// Put your logs below this line
 ERROR  { data: null,
  errors:
   [ { path: null,
       locations: [Array],
       message: "Variable 'involvedOrgs' has an invalid value." } ] }

aws-exports.js

const awsmobile = {
    "aws_project_region": "us-west-1",
    "aws_appsync_graphqlEndpoint": "https://f6koholxxzc5pcqfwmtdjkdlsa.appsync-api.us-west-1.amazonaws.com/graphql",
    "aws_appsync_region": "us-west-1",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "MY_SECRET_API_KEY"
};

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@rodrigogs rodrigogs added the pending-triage Issue is pending triage label Apr 26, 2024
@rodrigogs
Copy link
Author

I could make it work by stringifying the JSON:

eg.:

  async createEvent(createInput: CreateEventInput): Promise<Event> {
    return this.client.graphql({
      query: createEvent,
      variables: {
        input: {
          ...createInput,
          involvedPeople: JSON.stringify(createInput.involvedPeople),
        },
      },
    }).then(({ data }) => data.createEvent)
  }

Given that the GraphQL schema specifies an array, it's logical to anticipate that the generated input would require an array and not a string. Ignoring the type error in the code might be a temporary workaround, but inherently, it doesn't seem appropriate.

@cwomack cwomack added the GraphQL Related to GraphQL API issues label Apr 26, 2024
@chrisbonifacio
Copy link
Contributor

Hi @rodrigogs this seems to be expected behavior. At this point, serialization of the data is up to the client.
If you would like for the library to handle serialization, I would recommend opening a feature request.

@chrisbonifacio chrisbonifacio added question General question pending-response Issue is pending response from the issue requestor and removed pending-triage Issue is pending triage labels Apr 29, 2024
@chrisbonifacio chrisbonifacio self-assigned this Apr 29, 2024
@rodrigogs
Copy link
Author

rodrigogs commented Apr 29, 2024

Hi @chrisbonifacio, I appreciate your response, but I must respectfully disagree with the notion that this is expected behavior. The inconsistency arises because the library's generated GraphQL types specify an array for AWSJSON fields, yet the underlying system only accepts a stringified JSON, which leads to confusion and the need for additional client-side handling that one could argue should be intrinsic to the library's functionality.

If the intent is indeed for clients to handle serialization, it would be beneficial for this to be explicitly documented, or better yet, for the type generation to align more closely with the actual data expectations—either by correcting the type definitions or by handling serialization/deserialization within the library itself. This would enhance developer experience and reduce potential errors. Would you consider revisiting this issue in light of this perspective?

@github-actions github-actions bot removed the pending-response Issue is pending response from the issue requestor label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GraphQL Related to GraphQL API issues question General question
Projects
None yet
Development

No branches or pull requests

3 participants