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.42k stars 2.12k forks source link

GraphQL Call on Many-to-many Relationship Does Not Return Related Items #13860

Open desert-digital opened 2 weeks ago

desert-digital commented 2 weeks ago

Before opening, please confirm:

JavaScript Framework

Angular

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify CLI

Environment information

``` # Put output below this line System: OS: macOS 12.7.6 CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz Memory: 2.49 GB / 16.00 GB Shell: 6.21.00 - /bin/tcsh Binaries: Node: 20.10.0 - /usr/local/bin/node Yarn: 1.22.22 - ~/Development/Javascript/compass/compass-frontend/node_modules/.bin/yarn npm: 10.2.3 - /usr/local/bin/npm pnpm: 9.11.0 - /usr/local/bin/pnpm Browsers: Chrome: 129.0.6668.60 Safari: 17.6 npmPackages: @angular-devkit/build-angular: ^18.2.6 => 18.2.6 @angular-eslint/builder: ^18.2.0 => 18.3.1 @angular-eslint/eslint-plugin: ^18.2.0 => 18.3.1 @angular-eslint/eslint-plugin-template: ^18.2.0 => 18.3.1 @angular-eslint/schematics: ^18.2.0 => 18.3.1 @angular-eslint/template-parser: ^18.2.0 => 18.3.1 @angular/animations: ^18.2.6 => 18.2.6 @angular/cdk: ^18.2.6 => 18.2.6 @angular/cli: ~18.2.6 => 18.2.6 @angular/common: ^18.2.6 => 18.2.6 @angular/compiler: ^18.2.6 => 18.2.6 @angular/compiler-cli: ^18.2.6 => 18.2.6 @angular/core: ^18.2.6 => 18.2.6 @angular/forms: ^18.2.6 => 18.2.6 @angular/material: ^18.2.5 => 18.2.6 @angular/platform-browser: ^18.2.6 => 18.2.6 @angular/platform-browser-dynamic: ^18.2.6 => 18.2.6 @angular/router: ^18.2.6 => 18.2.6 @aws-amplify/api: ^6.0.28 => 6.0.51 @aws-amplify/api/internals: undefined () @aws-amplify/api/server: undefined () @aws-amplify/auth: ^6.0.27 => 6.4.2 @aws-amplify/auth/cognito: undefined () @aws-amplify/auth/cognito/server: undefined () @aws-amplify/auth/enable-oauth-listener: undefined () @aws-amplify/auth/server: undefined () @aws-amplify/core: ^6.0.27 => 6.4.2 @aws-amplify/core/internals/adapter-core: undefined () @aws-amplify/core/internals/aws-client-utils: undefined () @aws-amplify/core/internals/aws-client-utils/composers: undefined () @aws-amplify/core/internals/aws-clients/cognitoIdentity: undefined () @aws-amplify/core/internals/aws-clients/pinpoint: undefined () @aws-amplify/core/internals/providers/pinpoint: undefined () @aws-amplify/core/internals/utils: undefined () @aws-amplify/core/server: undefined () @aws-amplify/storage: ^6.0.27 => 6.6.7 @aws-amplify/storage/s3: undefined () @aws-amplify/storage/s3/server: undefined () @aws-amplify/storage/server: undefined () @aws-amplify/ui-angular: ^5.0.26 => 5.0.26 @types/d3: ^7.4.0 => 7.4.3 @types/jasmine: ~4.3.2 => 4.3.6 @typescript-eslint/eslint-plugin: ^8.0.0 => 8.7.0 @typescript-eslint/parser: ^8.0.0 => 8.7.0 amplify: ^0.0.11 => 0.0.11 angular: ^1.8.3 => 1.8.3 aws-amplify: ^6.0.28 => 6.6.2 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/data: undefined () aws-amplify/data/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () chart.js: ^4.3.0 => 4.4.4 chart.js-auto: undefined () chart.js-helpers: undefined () d3: ^7.8.5 => 7.9.0 eslint: ^9.11.0 => 9.11.1 jasmine-core: ~5.0.0 => 5.0.1 (4.6.1) karma: ~6.4.2 => 6.4.4 karma-chrome-launcher: ~3.2.0 => 3.2.0 karma-coverage: ~2.2.0 => 2.2.1 karma-coverage-coffee-example: 1.0.0 karma-jasmine: ~5.1.0 => 5.1.0 karma-jasmine-html-reporter: ~2.1.0 => 2.1.0 ng2-charts: ^4.1.1 => 4.1.1 npm-check-updates: ^16.10.12 => 16.14.20 rxjs: ~7.8.1 => 7.8.1 rxjs/ajax: undefined () rxjs/fetch: undefined () rxjs/operators: undefined () rxjs/testing: undefined () rxjs/webSocket: undefined () tslib: ^2.5.3 => 2.7.0 (2.6.3) typescript: ^5.2.0 => 5.5.4 yarn: ^1.22.0 => 1.22.22 zone.js: ~0.14.0 => 0.14.10 npmGlobalPackages: @angular/cli: 17.3.3 @aws-amplify/cli: 11.0.2 bootstrap: 3.3.7 bower: 1.8.0 browser-sync: 2.17.5 corepack: 0.22.0 firebase-tools: 3.0.8 generator-angular: 0.15.1 generator-bootstrap: 0.2.2 generator-gulp-angular: 1.1.1 generator-karma: 2.0.0 generator-node-webkit: 2.0.0-alpha.3 generator-nwjs: 0.0.3 generator-oldmen: 0.1.13 generator-react-gulp-browserify-less: 1.0.1 grunt-cli: 1.2.0 gulp: 3.9.1 http-server: 0.9.0 istanbul: 0.4.5 jasmine-node: 1.14.5 jekyll-cli: 0.3.9 karma-cli: 1.0.1 mocha: 3.2.0 n: 5.0.1 nmp: 1.0.3 nodewebkit: 0.11.6 npm-check-updates: 16.10.12 npm: 10.2.3 protractor: 7.0.0 typescript: 5.4.4 yo: 1.8.5 ```

Describe the bug

No items are returned by GraphQL call on many-to-many relation. Items exist in the correctly named DynamoDB join table. Specific error is "TypeError: checklistModel.actionModels.items is not iterable"

The definition of the ChecklistModel and ActionModel types are below. All models in the schema file are public (to eliminate any security related errors that may be causing this issue).

type ActionModel @model @auth(rules: [{ allow: public }]){
  id: ID!
  company: String!
  name: String
  notes: String 
  duration: Int
  checklists: [ChecklistModel] @manyToMany(relationName: "ChecklistActions")
}

type ChecklistModel @model @auth(rules: [{ allow: public }]){
  id: ID!
  company: String!
  name: String
  notes: String
  duration: Int
  preCharter: Boolean
  actionModels: [ActionModel] @manyToMany(relationName: "ChecklistActions")
  workflows: [WorkflowModel] @manyToMany(relationName: "WorkflowChecklists") 
}

Expected behavior

checklistModel.actionModels.items is an array with one item (and so therefore iterable)

Reproduction steps

  1. Select 'Checklist Admin'
  2. Select a Checklist item
  3. Open the context-based menu, and select 'edit'

The error occurs when the EditChecklist component is opened.

Screen Shot 2024-09-27 at 14 11 16

Code Snippet

// Put your code below this line.

// Code used to create a Checklist Model with Action Models
// In the add-checklist component

  async onAddChecklistPressed(model: ChecklistModel, formDirective: FormGroupDirective) {
    try {
      this._checklistModelsService.createChecklistModel(model, this.checklist).then(() => {
        this._snackBar.open('Created a new checklist', 'OK', { duration: 3000 });
        this.checklistForm.reset();
        formDirective.resetForm();
        this.checklist = [];
        this._getActions();
      });
    } catch (error) {
      this._snackBar.open('Error creating the checklist', 'OK', { duration: 3000 });
    }
  }

// In the ChecklistModel service

  async createChecklistModel(checklistModel: ChecklistModel, actions: ActionModel[]) {
    const checklistMutationResult = await this.client.graphql({
      query: createChecklistModel,
      variables: {
        input: {
          company: 'seaforth',
          name: checklistModel.name,
          duration: checklistModel.duration,
          notes: checklistModel.notes,
          preCharter: checklistModel.preCharter,
        }
      }
    });

    const checklist = checklistMutationResult.data.createChecklistModel;

    for (const action of actions) {
      await this.client.graphql({
        query: createChecklistActions,
        variables: {
          input: {
            actionModelId: action.id,
            checklistModelId: checklist.id
          },
        }
      });
    }

    const updatedChecklist = await this.getChecklistModelFromId(checklist.id);
    console.log(updatedChecklist.actionModels);
  }

// Code to retrieve the ChecklistModel
// In the ChecklistModel service

  async getChecklistModelFromId(id: string): Promise<ChecklistModel> {
    const checklistResult = await this.client.graphql({
      query: getChecklistModel,
      variables: { id: id }
    })
    return checklistResult.data.getChecklistModel as ChecklistModel;
  }

Log output

The item from the join table is shown below. The actionModelId and checklistModelId match the ids from the corresponding ActionModel and ChecklistModel tables. The value returned from the getChecklistModelFromId is also attached.

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

Screen Shot 2024-09-27 at 14 18 49

Screen Shot 2024-09-27 at 14 19 26

Screen Shot 2024-09-27 at 14 20 29

Screen Shot 2024-09-27 at 14 31 13

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

chrisbonifacio commented 6 days ago

Hi @desert-digital 👋 thanks for raising this issue and providing detailed reproduction steps!

I will attempt to reproduce and report back with any findings.