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

Variables Inside Fragments behaving oddly? #3324

Closed
vade opened this issue Jan 23, 2024 · 14 comments
Closed

Variables Inside Fragments behaving oddly? #3324

vade opened this issue Jan 23, 2024 · 14 comments
Labels

Comments

@vade
Copy link

vade commented Jan 23, 2024

Question

Hello

Firstly, thank you for all the work on Apollo. Seriously awesome stuff.

I'm using a feature of GQL where I have defined a query and various fragments use those query arguments.

This is similar to https://graphql.org/learn/queries/#fragments

query HeroComparison($first: Int = 3) {
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  friendsConnection(first: $first) {
    totalCount
    edges {
      node {
        name
      }
    }
  }
}

I have validated that on my GQL Servers GraphiQL Console, the exact same query and fragments are able to function, and the 'faceted' search arguments are passed through to the fragments and results are correct.

I'm using Django with Graphene on the back end, and I am able to get correct results on the server.

Apollo iOS is able to compile my Schema, Queries and Fragments, and run the query via swift. However, it the behavior of the results seem as though the variables from the top level query are not being passed to the lower level fragments arguments.

In other words, in my query below, the server populating and generating results for transcriptionSet and videosegmentSet as expected (variables pass through).

Apollo iOS appears to not be passing variables through. That diagnoses is just based on observation, im not entirely sure the best way to debug.

Question

  1. Are Variables inside fragments expected to work on Apollo iOS? Im assuming so?
  2. Are there any tricks to getting nested fragments to have variables passed to it correctly through some opt in via the Swift API that might not be readily obvious that I am missing?

Thank you again!

Here is my GraphGLConsole test:

fragment cursorInfo on PageInfo
{
    startCursor
    endCursor
    hasNextPage
    hasPreviousPage
}

fragment newVideoSegmentPreview on VideoSegmentNode
{
    id
    signedUrl
    s3Key
    s3Bucket
    
    inTime
    outTime
    inTimeBase
    outTimeBase

#    tags
#    {
#        ... taggedItem
#    }
}

fragment newTranscriptionPreview on TranscriptionNode
{
    id
    signedUrl
    s3Key
    s3Bucket
    
    inTime
    inTimeBase
    outTime
    outTimeBase

    transcript
    
 #   tags
 #   {
 #       ... taggedItem
 #   }
}
fragment videoAssetGeneralInfo on VideoAssetNode
{
    id
    created
    modified
    signedUrl
    s3Key
    s3Bucket
    
    localFilePathUrls
    assetJson
    cinemaNetVersion
    cinemaClipVersion
    transcriptVersion
    faceNetworkVersion
}

fragment newVideoAssetPreview on VideoAssetNode
{
    ... videoAssetGeneralInfo
  
  duration
  timeBase
        
  transcriptionSet(tagQuery: $tagQuery,
                   transcript: $transcript,
                   cinemaClipQuery: $cinemaClipQuery,
                   duration: $duration,
                   duration_Lt: $duration_Lt,
                   duration_Lte: $duration_Lte,
                   duration_Gt: $duration_Gt,
                   duration_Gte: $duration_Gte,
#                   orderBy: $orderBy,
#                   createdAtQuery: $created,
#                   modifiedAtQuery: $modified,
#                   after: $after
                  )
  {
    totalCount
    edgeCount
    pageInfo {
        startCursor
        endCursor
    }
    edges
    {
      node
      {
        ...newTranscriptionPreview
      }
    }

  }
  
  videosegmentSet(tagQuery: $tagQuery,
                  cinemaClipQuery: $cinemaClipQuery,
                  duration: $duration,
                  duration_Lt: $duration_Lt,
                  duration_Lte: $duration_Lte,
                  duration_Gt: $duration_Gt,
                  duration_Gte: $duration_Gte,
#                      orderBy: $orderBy,
#                      createdAtQuery: $created,
#                      modifiedAtQuery: $modified,
                   after: $after
                      )
  {
    totalCount
    edgeCount
    pageInfo {
        startCursor
        endCursor
    }
    edges
    {
      node
      {
        ...newVideoSegmentPreview
      }
    }
  }
}



query newLibraryVideoAssets($libraryID: String! = "TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2",
                             $tagQuery: JSONString ="{\"categories\":[{\"category\":\"Character\",\"tags\":[\"John McClane\"]}]}",
                             $cinemaClipQuery:CinemaCLIPQueryInput,
                             $transcript: String,
                             $duration: Float,
                             $duration_Lt: Float,
                             $duration_Lte: Float,
                             $duration_Gt: Float,
                             $duration_Gte: Float,
                             $orderBy: [String],
                             $created: JSONString,
                             #$modified: JSONString,
                             $after: String)
{
    allVideoAssets(libraryId:$libraryID, createdAtQuery:$created, orderBy:$orderBy, after:$after)
    {
        totalCount
        pageInfo
        {
            ... cursorInfo
        }
        edges
        {
            node
            {
                ... newVideoAssetPreview
            }
        }
    }
}

@vade vade added the question Issues that have a question which should be addressed label Jan 23, 2024
@vade
Copy link
Author

vade commented Jan 23, 2024

Forgot to mention I am on Apollo iOS 1.7.1

@AnthonyMDev
Copy link
Contributor

Thanks for the report @vade. Yes, variables should be passed through to fragments as you would expect. Let me do some testing and see if I can reproduce this issue myself first!

@AnthonyMDev AnthonyMDev added bug Generally incorrect behavior needs investigation labels Jan 23, 2024
@AnthonyMDev AnthonyMDev added awaiting response and removed question Issues that have a question which should be addressed labels Jan 23, 2024
@AnthonyMDev
Copy link
Contributor

I'm not sure how there could even be a bug here that would be causing variables not to work in fragments while they are still working for arguments in the query directly. The way that GraphQL works is that the client sends the body of the GraphQL query and a list of all variables to the server. The actual usage of those variables during GraphQL execution is a back end concern.

It's definitely odd that your server is returning the correct response when using GraphiQL but not Apollo iOS though. In order to get to the bottom of this, we are going to need to see what the difference in the actual HTTP requests being sent. Would you be able to debug this a bit further and show us what the HTTP request looks like?

If you are unable to post log data publicly, you can strip out whatever sensitive information you need to and e-mail me the results privately at [email protected]

@vade
Copy link
Author

vade commented Jan 23, 2024

Absolutely. Let me figure out the best way of handling that. Much appreciated @AnthonyMDev ! I'll try to get to this asap.

@vade
Copy link
Author

vade commented Jan 23, 2024

Interesting.

So one difference I note in the HTTP request to the /graphql endpoint is partially due to how the graphql console works.

I can't call the query newLibraryVideoAssets with variables, just with default values. This means that the Request data is slightly different.

I Can state that the Apollo IOS is properly sending the variables key in the Request payload as I'd expect:

variables': {'after': None, 'cinemaClipQuery': None, 'created': None, 'duration': None, 'duration_Gt': None, 'duration_Gte': None, 'duration_Lt': None, 'duration_Lte': None, 'libraryID': 'TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2', 'orderBy': ['-created'], 'tagQuery': '{"categories":[{"category":"Character","tags":["John McClane"]}]}', 'transcript': None}}

So that maybe means that there's subtle difference in our servers behavior. I may try to set up a 3rd party GQL client to validate the behavior and responses.

I'll keep you updated as I discover things. Apologies ahead of time for noise, and greatly appreciate the prompt responses

@vade
Copy link
Author

vade commented Jan 23, 2024

Using Hopscotch GQL Client to run the query also returns correct results from the server. So either im doing something dumb™ in my application code (entirely possible and likely) or something spookier is going on.

I'll continue to update as I find out. Thanks again.

@vade
Copy link
Author

vade commented Jan 23, 2024

Ok, so I will say the HTTP Request seems to be pretty differently structured between Hopsotch and our Apollo iOS client:

Im leaving formatting as is, just incase its of interest Also apologies for AS:LDJKA:SLDJAS I'm clearly a pro.

HOPSCOTCH:

 AS:LDJKA:SLDJAS {'query': 'fragment cursorInfo on PageInfo\n{\n    startCursor\n    endCursor\n    hasNextPage\n    hasPreviousPage\n}\n\nfragment newVideoSegmentPreview on VideoSegmentNode\n{\n    id\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    inTime\n    outTime\n    inTimeBase\n    outTimeBase\n\n#    tags\n#    {\n#        ... taggedItem\n#    }\n}\n\nfragment newTranscriptionPreview on TranscriptionNode\n{\n    id\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    inTime\n    inTimeBase\n    outTime\n    outTimeBase\n\n    transcript\n    \n #   tags\n #   {\n #       ... taggedItem\n #   }\n}\nfragment videoAssetGeneralInfo on VideoAssetNode\n{\n    id\n    created\n    modified\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    localFilePathUrls\n    assetJson\n    cinemaNetVersion\n    cinemaClipVersion\n    transcriptVersion\n    faceNetworkVersion\n}\n\nfragment newVideoAssetPreview on VideoAssetNode\n{\n    ... videoAssetGeneralInfo\n  \n  duration\n  timeBase\n        \n  transcriptionSet(tagQuery: $tagQuery,\n                   transcript: $transcript,\n                   cinemaClipQuery: $cinemaClipQuery,\n                   duration: $duration,\n                   duration_Lt: $duration_Lt,\n                   duration_Lte: $duration_Lte,\n                   duration_Gt: $duration_Gt,\n                   duration_Gte: $duration_Gte,\n#                   orderBy: $orderBy,\n#                   createdAtQuery: $created,\n#                   modifiedAtQuery: $modified,\n#                   after: $after\n                  )\n  {\n    totalCount\n    edgeCount\n    pageInfo {\n        startCursor\n        endCursor\n    }\n    edges\n    {\n      node\n      {\n        ...newTranscriptionPreview\n      }\n    }\n\n  }\n  \n  videosegmentSet(tagQuery: $tagQuery,\n                  cinemaClipQuery: $cinemaClipQuery,\n                  duration: $duration,\n                  duration_Lt: $duration_Lt,\n                  duration_Lte: $duration_Lte,\n                  duration_Gt: $duration_Gt,\n                  duration_Gte: $duration_Gte,\n#                      orderBy: $orderBy,\n#                      createdAtQuery: $created,\n#                      modifiedAtQuery: $modified,\n                   after: $after\n                      )\n  {\n    totalCount\n    edgeCount\n    pageInfo {\n        startCursor\n        endCursor\n    }\n    edges\n    {\n      node\n      {\n        ...newVideoSegmentPreview\n      }\n    }\n  }\n}\n\nquery newLibraryVideoAssets($libraryID: String!,\n                             $tagQuery: JSONString,\n                             $cinemaClipQuery:CinemaCLIPQueryInput,\n                             $transcript: String,\n                             $duration: Float,\n                             $duration_Lt: Float,\n                             $duration_Lte: Float,\n                             $duration_Gt: Float,\n                             $duration_Gte: Float,\n                             $orderBy: [String],\n                             $created: JSONString,\n                             #$modified: JSONString,\n                             $after: String)\n{\n    allVideoAssets(libraryId:$libraryID, createdAtQuery:$created, orderBy:$orderBy, after:$after)\n    {\n        totalCount\n        pageInfo\n        {\n            ... cursorInfo\n        }\n        edges\n        {\n            node\n            {\n                ... newVideoAssetPreview\n            }\n        }\n    }\n}\n', 'variables': {'libraryID': 'TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2', 'tagQuery': '{"categories":[{"category":"Character","tags":["John McClane"]}]}'}, 'operationName': 'newLibraryVideoAssets'}

Mac App w Apollo iOS:

AS:LDJKA:SLDJAS {'operationName': 'newLibraryVideoAssets', 'query': 'query newLibraryVideoAssets($libraryID: String!, $tagQuery: JSONString, $cinemaClipQuery: CinemaCLIPQueryInput, $transcript: String, $duration: Float, $duration_Lt: Float, $duration_Lte: Float, $duration_Gt: Float, $duration_Gte: Float, $orderBy: [String], $created: JSONString, $after: String) { allVideoAssets( libraryId: $libraryID createdAtQuery: $created orderBy: $orderBy after: $after ) { __typename totalCount pageInfo { __typename ...cursorInfo } edges { __typename node { __typename ...newVideoAssetPreview } } } }\nfragment cursorInfo on PageInfo { __typename startCursor endCursor hasNextPage hasPreviousPage }\nfragment newTranscriptionPreview on TranscriptionNode { __typename id signedUrl s3Key s3Bucket inTime inTimeBase outTime outTimeBase transcript }\nfragment newVideoAssetPreview on VideoAssetNode { __typename ...videoAssetGeneralInfo duration timeBase transcriptionSet( tagQuery: $tagQuery transcript: $transcript cinemaClipQuery: $cinemaClipQuery duration: $duration duration_Lt: $duration_Lt duration_Lte: $duration_Lte duration_Gt: $duration_Gt duration_Gte: $duration_Gte ) { __typename totalCount edgeCount pageInfo { __typename startCursor endCursor } edges { __typename node { __typename ...newTranscriptionPreview } } } videosegmentSet( tagQuery: $tagQuery cinemaClipQuery: $cinemaClipQuery duration: $duration duration_Lt: $duration_Lt duration_Lte: $duration_Lte duration_Gt: $duration_Gt duration_Gte: $duration_Gte after: $after ) { __typename totalCount edgeCount pageInfo { __typename startCursor endCursor } edges { __typename node { __typename ...newVideoSegmentPreview } } } }\nfragment newVideoSegmentPreview on VideoSegmentNode { __typename id signedUrl s3Key s3Bucket inTime outTime inTimeBase outTimeBase }\nfragment videoAssetGeneralInfo on VideoAssetNode { __typename id created modified signedUrl s3Key s3Bucket localFilePathUrls assetJson cinemaNetVersion cinemaClipVersion transcriptVersion faceNetworkVersion }', 'variables': {'after': None, 'cinemaClipQuery': None, 'created': None, 'duration': None, 'duration_Gt': None, 'duration_Gte': None, 'duration_Lt': None, 'duration_Lte': None, 'libraryID': 'TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2', 'orderBy': ['-created'], 'tagQuery': '{"categories":[{"tags":["John McClane"],"category":"Character"}]}', 'transcript': None}}

@vade
Copy link
Author

vade commented Jan 23, 2024

Cleaned up as JSON

Hopscotch (working as expected)

{
    "query": "fragment cursorInfo on PageInfo\n{\n    startCursor\n    endCursor\n    hasNextPage\n    hasPreviousPage\n}\n\nfragment newVideoSegmentPreview on VideoSegmentNode\n{\n    id\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    inTime\n    outTime\n    inTimeBase\n    outTimeBase\n\n#    tags\n#    {\n#        ... taggedItem\n#    }\n}\n\nfragment newTranscriptionPreview on TranscriptionNode\n{\n    id\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    inTime\n    inTimeBase\n    outTime\n    outTimeBase\n\n    transcript\n    \n #   tags\n #   {\n #       ... taggedItem\n #   }\n}\nfragment videoAssetGeneralInfo on VideoAssetNode\n{\n    id\n    created\n    modified\n    signedUrl\n    s3Key\n    s3Bucket\n    \n    localFilePathUrls\n    assetJson\n    cinemaNetVersion\n    cinemaClipVersion\n    transcriptVersion\n    faceNetworkVersion\n}\n\nfragment newVideoAssetPreview on VideoAssetNode\n{\n    ... videoAssetGeneralInfo\n  \n  duration\n  timeBase\n        \n  transcriptionSet(tagQuery: $tagQuery,\n                   transcript: $transcript,\n                   cinemaClipQuery: $cinemaClipQuery,\n                   duration: $duration,\n                   duration_Lt: $duration_Lt,\n                   duration_Lte: $duration_Lte,\n                   duration_Gt: $duration_Gt,\n                   duration_Gte: $duration_Gte,\n#                   orderBy: $orderBy,\n#                   createdAtQuery: $created,\n#                   modifiedAtQuery: $modified,\n#                   after: $after\n                  )\n  {\n    totalCount\n    edgeCount\n    pageInfo {\n        startCursor\n        endCursor\n    }\n    edges\n    {\n      node\n      {\n        ...newTranscriptionPreview\n      }\n    }\n\n  }\n  \n  videosegmentSet(tagQuery: $tagQuery,\n                  cinemaClipQuery: $cinemaClipQuery,\n                  duration: $duration,\n                  duration_Lt: $duration_Lt,\n                  duration_Lte: $duration_Lte,\n                  duration_Gt: $duration_Gt,\n                  duration_Gte: $duration_Gte,\n#                      orderBy: $orderBy,\n#                      createdAtQuery: $created,\n#                      modifiedAtQuery: $modified,\n                   after: $after\n                      )\n  {\n    totalCount\n    edgeCount\n    pageInfo {\n        startCursor\n        endCursor\n    }\n    edges\n    {\n      node\n      {\n        ...newVideoSegmentPreview\n      }\n    }\n  }\n}\n\nquery newLibraryVideoAssets($libraryID: String!,\n                             $tagQuery: JSONString,\n                             $cinemaClipQuery:CinemaCLIPQueryInput,\n                             $transcript: String,\n                             $duration: Float,\n                             $duration_Lt: Float,\n                             $duration_Lte: Float,\n                             $duration_Gt: Float,\n                             $duration_Gte: Float,\n                             $orderBy: [String],\n                             $created: JSONString,\n                             #$modified: JSONString,\n                             $after: String)\n{\n    allVideoAssets(libraryId:$libraryID, createdAtQuery:$created, orderBy:$orderBy, after:$after)\n    {\n        totalCount\n        pageInfo\n        {\n            ... cursorInfo\n        }\n        edges\n        {\n            node\n            {\n                ... newVideoAssetPreview\n            }\n        }\n    }\n}\n",
    "variables": {
        "libraryID": "TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2",
        "tagQuery": "{\"categories\":[{\"category\":\"Character\",\"tags\":[\"John McClane\"]}]}"
    },
    "operationName": "newLibraryVideoAssets"
}

Apollo iOS: (not working as expected)

{
    "operationName": "newLibraryVideoAssets",
    "query": "query newLibraryVideoAssets($libraryID: String!, $tagQuery: JSONString, $cinemaClipQuery: CinemaCLIPQueryInput, $transcript: String, $duration: Float, $duration_Lt: Float, $duration_Lte: Float, $duration_Gt: Float, $duration_Gte: Float, $orderBy: [String], $created: JSONString, $after: String) { allVideoAssets( libraryId: $libraryID createdAtQuery: $created orderBy: $orderBy after: $after ) { __typename totalCount pageInfo { __typename ...cursorInfo } edges { __typename node { __typename ...newVideoAssetPreview } } } }\nfragment cursorInfo on PageInfo { __typename startCursor endCursor hasNextPage hasPreviousPage }\nfragment newTranscriptionPreview on TranscriptionNode { __typename id signedUrl s3Key s3Bucket inTime inTimeBase outTime outTimeBase transcript }\nfragment newVideoAssetPreview on VideoAssetNode { __typename ...videoAssetGeneralInfo duration timeBase transcriptionSet( tagQuery: $tagQuery transcript: $transcript cinemaClipQuery: $cinemaClipQuery duration: $duration duration_Lt: $duration_Lt duration_Lte: $duration_Lte duration_Gt: $duration_Gt duration_Gte: $duration_Gte ) { __typename totalCount edgeCount pageInfo { __typename startCursor endCursor } edges { __typename node { __typename ...newTranscriptionPreview } } } videosegmentSet( tagQuery: $tagQuery cinemaClipQuery: $cinemaClipQuery duration: $duration duration_Lt: $duration_Lt duration_Lte: $duration_Lte duration_Gt: $duration_Gt duration_Gte: $duration_Gte after: $after ) { __typename totalCount edgeCount pageInfo { __typename startCursor endCursor } edges { __typename node { __typename ...newVideoSegmentPreview } } } }\nfragment newVideoSegmentPreview on VideoSegmentNode { __typename id signedUrl s3Key s3Bucket inTime outTime inTimeBase outTimeBase }\nfragment videoAssetGeneralInfo on VideoAssetNode { __typename id created modified signedUrl s3Key s3Bucket localFilePathUrls assetJson cinemaNetVersion cinemaClipVersion transcriptVersion faceNetworkVersion }",
    "variables": {
        "after": null,
        "cinemaClipQuery": null,
        "created": null,
        "duration": null,
        "duration_Gt": null,
        "duration_Gte": null,
        "duration_Lt": null,
        "duration_Lte": null,
        "libraryID": "TGlicmFyeU5vZGU6OTNlM2U0YjctODBlMi00Y2E0LThkZTEtMzVhNmU5NjUyYTk2",
        "orderBy": [
            "-created"
        ],
        "tagQuery": "{\"categories\":[{\"tags\":[\"John McClane\"],\"category\":\"Character\"}]}",
        "transcript": null
    }
}

@AnthonyMDev
Copy link
Contributor

Thanks for getting all of this data put together! As far as I can tell, Apollo is sending a properly formed GraphQL request with all of your variables intact.

The differences I see between the Hopscotch and Apollo versions are:

  • The fragments in the query string are in a different order
  • The Apollo query string strips out newline characters
  • The omitted variables are explicitly sent as null by Apollo
  • The orderBy variable has a value sent by Apollo. I'm assuming this is a default value that your schema provides, in which case it should be the same as when it's omitted.

Am I missing anything there?

I'm not sure what is causing your backend not to respect the variables properly when sent via Apollo, but I would assume this is a bug with the backend, since we are sending all the information in a GraphQL spec-compliant format.


The only thing I could think is that one of the variables that is being sent as null is actually relevant to your backend logic maybe? In which case, you can make those variables be omitted instead of null by initializing your query with each of those parameters values as .none instead of the default of .null. See our documentation on working with nullable arguments here.

@vade
Copy link
Author

vade commented Jan 23, 2024

Thanks! Yea, im wondering if there is some subtlety with the back end arguments. I actually just tried the null vs none and have variables matching, with no change.

I'll continue to explore, but for now this is smelling maybe more like a my problem than your problem sort of problem :)

Thank you again for the prompt responses!

@AnthonyMDev
Copy link
Contributor

Happy to help. Hope you sort this one out! I'm going to go ahead and close the issue for now.

If your investigations lead you back to thinking this is an Apollo issue, feel free to re-open this issue with new information or create a new one.

Even if it's not related to Apollo, I'd be curious to hear what the problem is once you figure it out! Good luck!

@AnthonyMDev AnthonyMDev closed this as not planned Won't fix, can't repro, duplicate, stale Jan 23, 2024
Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.

@vade
Copy link
Author

vade commented Jan 23, 2024

So this is totally my fault and a combination of some subtleties in my native app client decisions.

Context: Im exploring some new layouts in a modern data source and compositional layout NSCollectionView. Because my searches are now also sub-searches, im sort of grouping by the relay IDs of the primary top level items.

But, lo, those item ids dont change. So the internal book keeping of NSCollectionView never triggers to update the collection view items, and due to how I had wired it up, never re-draw.

Once I noticed that my data source was updating, but I saw no on screen changes, it occurred that my primary hashing ID for the collection view's data source never actually changed.

This is great news.

Thanks for your efforts, this is all now working as expect, including the pie on my face.

@AnthonyMDev
Copy link
Contributor

Haha, we all make those mistakes sometimes. :) Glad you've got it sorted out!

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

No branches or pull requests

2 participants