aws-appsync-community icon indicating copy to clipboard operation
aws-appsync-community copied to clipboard

How can I resolve the issue of being unable to utilize the codegen auto-generated AppSync API code in my Amplify Angular application?

Open saidberk27 opened this issue 1 year ago • 0 comments

Discussed in https://github.com/aws/aws-appsync-community/discussions/367

Originally posted by saidberk27 August 14, 2024 I am relatively new to AWS and Angular development. I am currently working on a project where AWS IoT sends data to a specific topic, which triggers a Lambda function. This Lambda function then stores the data in DynamoDB, and my AppSync API reads from this DynamoDB table.

Objective: My goal is to create a real-time IoT web application. Specifically, I want to frequently check DynamoDB for any updates, as I expect changes to occur approximately six times per minute due to the IoT device's activity.

Current Progress: I have tested my AppSync API, and it successfully reacts to new data published to the IoT channel. I can see the newly added item's partition key (though not the full data), indicating that the API is responsive to IoT events.

Issue: I am encountering difficulties when attempting to integrate this API with my Angular 18 application, which is built using AWS Amplify.

I have followed the documentation to configure my application, as shown below:

// app.config.ts

Amplify.configure(outputs); // For auth and data
Amplify.configure({
  API: {
    GraphQL: {
      endpoint: 'https://xxx.appsync-api.xx-xx-2.amazonaws.com/graphql',
      region: 'xx-xx-2',
      defaultAuthMode: 'apiKey',
      apiKey: 'da2-xxx'
    }
  }
});

Subsequently, I used the codegen feature to generate a service file for my API.

/* tslint:disable */
/* eslint-disable */
//  This file was automatically generated and should not be edited.
import { Injectable } from "@angular/core";
import { Client, generateClient, GraphQLResult } from "aws-amplify/api";
import { Observable } from "rxjs";

export type __SubscriptionContainer = {
  onCreateIotTest: OnCreateIotTestSubscription;
  onUpdateIotTest: OnUpdateIotTestSubscription;
  onDeleteIotTest: OnDeleteIotTestSubscription;
};

export type CreateIotTestInput = {
  iot_test: string;
};

export type IotTest = {
  __typename: "IotTest";
  iot_test: string;
};

export type UpdateIotTestInput = {
  iot_test: string;
};

export type DeleteIotTestInput = {
  iot_test: string;
};

export type TableIotTestFilterInput = {
  iot_test?: TableStringFilterInput | null;
};

export type TableStringFilterInput = {
  ne?: string | null;
  eq?: string | null;
  le?: string | null;
  lt?: string | null;
  ge?: string | null;
  gt?: string | null;
  contains?: string | null;
  notContains?: string | null;
  between?: Array<string | null> | null;
  beginsWith?: string | null;
  attributeExists?: boolean | null;
  size?: ModelSizeInput | null;
};

export type ModelSizeInput = {
  ne?: number | null;
  eq?: number | null;
  le?: number | null;
  lt?: number | null;
  ge?: number | null;
  gt?: number | null;
  between?: Array<number | null> | null;
};

export type IotTestConnection = {
  __typename: "IotTestConnection";
  items?: Array<IotTest | null> | null;
  nextToken?: string | null;
};

export type CreateIotTestMutation = {
  __typename: "IotTest";
  iot_test: string;
};

export type UpdateIotTestMutation = {
  __typename: "IotTest";
  iot_test: string;
};

export type DeleteIotTestMutation = {
  __typename: "IotTest";
  iot_test: string;
};

export type GetIotTestQuery = {
  __typename: "IotTest";
  iot_test: string;
};

export type ListIotTestsQuery = {
  __typename: "IotTestConnection";
  items?: Array<{
    __typename: "IotTest";
    iot_test: string;
  } | null> | null;
  nextToken?: string | null;
};

export type OnCreateIotTestSubscription = {
  __typename: "IotTest";
  iot_test: string;
};

export type OnUpdateIotTestSubscription = {
  __typename: "IotTest";
  iot_test: string;
};

export type OnDeleteIotTestSubscription = {
  __typename: "IotTest";
  iot_test: string;
};

@Injectable({
  providedIn: "root"
})
export class APIService {
  public client: Client;
  constructor() {
    this.client = generateClient();
  }
  async CreateIotTest(
    input: CreateIotTestInput
  ): Promise<CreateIotTestMutation> {
    const statement = `mutation CreateIotTest($input: CreateIotTestInput!) {
        createIotTest(input: $input) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {
      input
    };
    const response = (await this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    })) as any;
    return <CreateIotTestMutation>response.data.createIotTest;
  }
  async UpdateIotTest(
    input: UpdateIotTestInput
  ): Promise<UpdateIotTestMutation> {
    const statement = `mutation UpdateIotTest($input: UpdateIotTestInput!) {
        updateIotTest(input: $input) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {
      input
    };
    const response = (await this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    })) as any;
    return <UpdateIotTestMutation>response.data.updateIotTest;
  }
  async DeleteIotTest(
    input: DeleteIotTestInput
  ): Promise<DeleteIotTestMutation> {
    const statement = `mutation DeleteIotTest($input: DeleteIotTestInput!) {
        deleteIotTest(input: $input) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {
      input
    };
    const response = (await this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    })) as any;
    return <DeleteIotTestMutation>response.data.deleteIotTest;
  }
  async GetIotTest(iot_test: string): Promise<GetIotTestQuery> {
    const statement = `query GetIotTest($iot_test: String!) {
        getIotTest(iot_test: $iot_test) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {
      iot_test
    };
    const response = (await this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    })) as any;
    return <GetIotTestQuery>response.data.getIotTest;
  }
  async ListIotTests(
    filter?: TableIotTestFilterInput,
    limit?: number,
    nextToken?: string
  ): Promise<ListIotTestsQuery> {
    const statement = `query ListIotTests($filter: TableIotTestFilterInput, $limit: Int, $nextToken: String) {
        listIotTests(filter: $filter, limit: $limit, nextToken: $nextToken) {
          __typename
          items {
            __typename
            iot_test
          }
          nextToken
        }
      }`;
    const gqlAPIServiceArguments: any = {};
    if (filter) {
      gqlAPIServiceArguments.filter = filter;
    }
    if (limit) {
      gqlAPIServiceArguments.limit = limit;
    }
    if (nextToken) {
      gqlAPIServiceArguments.nextToken = nextToken;
    }
    const response = (await this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    })) as any;
    return <ListIotTestsQuery>response.data.listIotTests;
  }
  OnCreateIotTestListener(
    iot_test?: string
  ): Observable<
    GraphQLResult<Pick<__SubscriptionContainer, "onCreateIotTest">>
  > {
    const statement = `subscription OnCreateIotTest($iot_test: String) {
        onCreateIotTest(iot_test: $iot_test) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {};
    if (iot_test) {
      gqlAPIServiceArguments.iot_test = iot_test;
    }
    return this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    }) as any;
  }

  OnUpdateIotTestListener(
    iot_test?: string
  ): Observable<
    GraphQLResult<Pick<__SubscriptionContainer, "onUpdateIotTest">>
  > {
    const statement = `subscription OnUpdateIotTest($iot_test: String) {
        onUpdateIotTest(iot_test: $iot_test) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {};
    if (iot_test) {
      gqlAPIServiceArguments.iot_test = iot_test;
    }
    return this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    }) as any;
  }

  OnDeleteIotTestListener(
    iot_test?: string
  ): Observable<
    GraphQLResult<Pick<__SubscriptionContainer, "onDeleteIotTest">>
  > {
    const statement = `subscription OnDeleteIotTest($iot_test: String) {
        onDeleteIotTest(iot_test: $iot_test) {
          __typename
          iot_test
        }
      }`;
    const gqlAPIServiceArguments: any = {};
    if (iot_test) {
      gqlAPIServiceArguments.iot_test = iot_test;
    }
    return this.client.graphql({
      query: statement,
      variables: gqlAPIServiceArguments
    }) as any;
  }
}

I then created a basic Angular component to interact with this API:

import { Component, OnInit } from '@angular/core';
import { APIService, CreateIotTestInput, DeleteIotTestInput, UpdateIotTestInput } from '../API.service';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-iot-test',
  template: `
    <div>
      <h1>Iot Test Component</h1>
      <button (click)="createIotTest()">Create Iot Test</button>
      <button (click)="updateIotTest()">Update Iot Test</button>
      <button (click)="deleteIotTest()">Delete Iot Test</button>
      <button (click)="getIotTest()">Get Iot Test</button>
      <button (click)="listIotTests()">List Iot Tests</button>
    </div>
  `,
  standalone: true,
  imports: [CommonModule],
  providers: [APIService]
})
export class IotTestComponent implements OnInit {
  constructor(private apiService: APIService) { }

  ngOnInit(): void {
  }

  createIotTest(): void {
    const input: CreateIotTestInput = {
      iot_test: 'New Iot Test'
    };
    this.apiService.CreateIotTest(input).then((response) => {
      console.log(response);
    });
  }

  updateIotTest(): void {
    const input: UpdateIotTestInput = {
      iot_test: 'Updated Iot Test'
    };
    this.apiService.UpdateIotTest(input).then((response) => {
      console.log(response);
    });
  }

  deleteIotTest(): void {
    const input: DeleteIotTestInput = {
      iot_test: 'Iot Test to delete'
    };
    this.apiService.DeleteIotTest(input).then((response) => {
      console.log(response);
    });
  }

  getIotTest(): void {
    const iot_test = 'Iot Test to get';
    this.apiService.GetIotTest(iot_test).then((response) => {
      console.log(response);
    });
  }

  listIotTests(): void {
    this.apiService.ListIotTests().then((response) => {
      console.log(response);
    });
  }
}

When I try to interact somehow with API service functions, I get validation errors. for example when I click List IoT Tests button I get two errors.

"Validation error of type UnknownType: Unknown type TableIotTestFilterInput"

and

"Validation error of type FieldUndefined: Field 'listIotTests' in type 'Query' is undefined @ 'listIotTests'"

FYI: I am running on localhost currently

saidberk27 avatar Aug 14 '24 09:08 saidberk27