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

AppSync empty selectionSetList in the GraphQL Info Object #358

Open
vasyl-nvt opened this issue Apr 4, 2024 · 2 comments
Open

AppSync empty selectionSetList in the GraphQL Info Object #358

vasyl-nvt opened this issue Apr 4, 2024 · 2 comments

Comments

@vasyl-nvt
Copy link

Hello,

It seems selectionSetList is always empty when running queries returning a union type.

Simplified schema example:

    type Post {
      id: ID!
      content: String!
    }

    type QueryError {
      message: String!
    }

    union QueryResult = Post | QueryError
    
    type Query {
      getPost(id: String!): QueryResult
    }

Query Example:

    query GetPostQuery {
       getPost(id: "post-guid") {
            ... on Post {
                id
                content
            }
            ... on QueryError {
                message
            }
       }
    }

Lambda function receives $event.info.selectionSetList = [] for such type of queries on AWS AppSync.

Is there anything one can do to make it work?

P.S: It works correctly when running locally using Amplify AppSyncSimulator.

@osadi
Copy link

osadi commented May 5, 2024

I ran in to the same issue. And I don't know how many times I read the documentation, but the last time I read it I saw this:
https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html#aws-appsync-resolver-context-reference-info-js

selectionSetList exposes only fields that belong to the current type. If the current type is an interface or union, only selected fields that belong to the interface are exposed.

So it seems like it's by design and not much that can be done about it.. I have a similar setup to you, where they can't share fields in an interface so I'm kind of stuck.

Maybe something like this could work, and passing it the ctx.info.selectionSetGraphQL, which seems to be populated:

export const gqlToSelectionSetList = (str: string) => {
  const START_TOKEN = '{';
  const END_TOKEN = '}';
  const FRAGMENT_TOKEN = '.';
  const SPACE_TOKEN = ' ';
  const FRAGMENT_DECLARATION_TOKEN = 'on';

  const selectionSetList: string[] = [];
  const path: string[] = [];

  let curr: string = '';
  let prev: string = '';

  for (const c of str.replaceAll('\n', '')) {
    switch (c) {
      case FRAGMENT_TOKEN: {
        break;
      }
      case SPACE_TOKEN: {
        if (curr !== FRAGMENT_DECLARATION_TOKEN && curr !== '') {
          selectionSetList.push([...path, curr].join('/'));
          prev = curr;
        }
        curr = '';
        break;
      }
      case START_TOKEN: {
        if (prev) path.push(prev);
        break;
      }
      case END_TOKEN: {
        path.pop();
        break;
      }
      default: {
        curr = curr + c;
      }
    }
  }
  return selectionSetList;
};

I have no idea how robust this would be, or if this is a solution 😄

@vasyl-nvt
Copy link
Author

@osadi Thanks for pointing out to the documentation. It seems to explain the behaviour.
But to me it looks like selectionSetList is a result of parsing a string selectionSetGraphQL and should be populated accordingly. AppSync simulator does it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants