aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.41k stars 2.12k forks source link

Model queries not querying for custom types #12987

Closed malaquf closed 6 months ago

malaquf commented 7 months ago

Before opening, please confirm:

JavaScript Framework

Vue

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify Gen 2 (Preview)

Environment information

``` # Put output below this line System: OS: macOS 13.2 CPU: (10) arm64 Apple M1 Max Memory: 11.71 GB / 64.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 21.6.0 - /opt/homebrew/bin/node npm: 10.2.4 - /opt/homebrew/bin/npm pnpm: 8.14.1 - /opt/homebrew/bin/pnpm Browsers: Chrome: 121.0.6167.139 Safari: 16.3 npmPackages: @aws-amplify/backend: ^0.10.3 => 0.10.3 @aws-amplify/backend-cli: ^0.10.0 => 0.10.0 @aws-amplify/datastore: ^5.0.15 => 5.0.15 @nuxt/ui: ^2.13.0 => 2.13.0 @pinia/nuxt: ^0.5.1 => 0.5.1 aws-amplify: ^6.0.15 => 6.0.15 axios: ^1.6.7 => 1.6.7 json-editor-vue: ^0.12.0 => 0.12.0 nuxt: ^3.10.1 => 3.10.1 pinia: ^2.1.7 => 2.1.7 vue: ^3.4.16 => 3.4.16 vue-router: ^4.2.5 => 4.2.5 npmGlobalPackages: @aws-amplify/cli: 12.10.1 aws-cdk: 2.124.0 npm: 10.2.4 ```

Describe the bug

Hi! I'm using amplify gen 2 and facing the following issue.

Considering this mode:

const schema = a.schema({
    Product: a.model({
        name: a.string().required(),
        attributes: a.ref('Attributes'),
    }),

    Attributes: a.customType({
        a: a.string().required(),
        b: a.integer().required()
    })
});

the 'attributes' field is not queried when executing:

dataClient.models.Product.get({ id: id })

Only strings and enums of string types are queried, apparently because of the filtering in this method

function defaultSelectionSetForModel(modelDefinition: SchemaModel): string[] {
    // fields that are explicitly part of the graphql schema; not
    // inferred from owner auth rules.
    const { fields } = modelDefinition;
    const explicitFields = Object.values<any>(fields)
        // Default selection set omits model fields
        .map(
            ({ type, name }) =>
                (typeof type === 'string' ||
                    (typeof type === 'object' && typeof type?.enum === 'string')) &&
                name
        )
        .filter(Boolean);

    // fields used for owner auth rules that may or may not also
    // be explicit on the model.
    const ownerFields = resolveOwnerFields(modelDefinition);

    return Array.from(new Set(explicitFields.concat(ownerFields)));
}

Trying to retrieve it through a selection set results in a error here.

Expected behavior

All fields from my model are queried by default, independently of their types.

Reproduction steps

Setup the model above and try to get the record using the model as described.

Code Snippet

// Put your code below this line.
async fetchProduct(id: string) {
      return await dataClient.models.Product.get({ id: id })
},

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

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

cwomack commented 7 months ago

Hello, @malaquf 👋. It looks like that error is thrown when a field isn't recognized as a model field, but from what I can tell it looks like your schema definitions for both the Product model and Attributes type look proper.

Would you mind sharing the code that's making queries so that we can confirm your attributes type is being included in them? Are you trying to query any custom selection set or doing anything outside of what the Gen2 docs detail?

malaquf commented 7 months ago

Hello, @cwomack. I'm retrieving it through the model like this:

async fetchProduct(id: string) {
      return await dataClient.models.Product.get({ id: id })
}

I also tried to add a selection set, but then it also fails here.

For now, I workarounded it by replacing the model query by a graphql query:

async fetchProduct(id: string) {
return await dataClient.graphql({
        query: getProduct,
        variables: {id: id}
      })
}
cwomack commented 7 months ago

@malaquf, thank you for the quick response and additional context. We'll mark this as a bug for now and investigate further.

iartemiev commented 7 months ago

I believe this will be resolved in https://github.com/aws-amplify/amplify-js/pull/12750/files

iartemiev commented 6 months ago

This is resolved in aws-amplify@6.0.18. Please let us know if you run into any more issues with this feature.