aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
75 stars 62 forks source link

[Amplify Gen2] Property Todo does not exist on type for a new Scaffolded Todo Gen2 project #2369

Open ujjwol05 opened 1 month ago

ujjwol05 commented 1 month ago

Environment information

System:
  OS: macOS 14.4
  CPU: (8) x64 Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
  Memory: 93.27 MB / 16.00 GB
  Shell: /bin/zsh
Binaries:
  Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
  Yarn: 1.22.11 - /usr/local/bin/yarn
  npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 0.12.1
  @aws-amplify/backend-cli: 0.11.1
  aws-amplify: 6.0.20
  aws-cdk: 2.133.0
  aws-cdk-lib: 2.133.0
  typescript: 5.4.2
AWS environment variables:
  AWS_SDK_LOAD_CONFIG = 1
  AWS_STS_REGIONAL_ENDPOINTS = regional
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
No CDK environment variables

Description

When attempting to retrieve data from the Todo model using client.models.Todo.list(), TypeScript throws an error indicating that the 'Todo' property does not exist on the type.

// TodoList.tsx

import type {Schema} from "@/amplify/data/resource";

// generate your data client using the Schema from your backend
const client = generateClient<Schema>();

export default function TodoList() {
    const [todos, setTodos] = useState<Schema["Todo"][]>([]);

    async function listTodos() {
        // fetch all todos
        const {data} = await client.models.Todo.list();
        setTodos(data);
    }
    ......

data/resource.ts

import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

/*== STEP 1 ===============================================================
The section below creates a Todo database table with a "content" field. Try
adding a new "isDone" field as a boolean. The authorization rules below
specify that owners, authenticated via your Auth resource can "create",
"read", "update", and "delete" their own records. Public users,
authenticated via an API key, can only "read" records.
=========================================================================*/
const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
      done: a.boolean(),
      priority: a.enum(['low', 'medium', 'high'])
    })
    .authorization([a.allow.owner()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
      defaultAuthorizationMode: 'userPool'
  },
});

/*== STEP 2 ===============================================================
Go to your frontend source code. From your client-side code, generate a
Data client to make CRUDL requests to your table. (THIS SNIPPET WILL ONLY
WORK IN THE FRONTEND CODE FILE.)

Using JavaScript or Next.js React Server Components, Middleware, Server 
Actions or Pages Router? Review how to generate Data clients for those use
cases: https://docs.amplify.aws/gen2/build-a-backend/data/connect-to-API/
=========================================================================*/

/*
"use client"
import { generateClient } from "aws-amplify/data";
import { type Schema } from "@/amplify/data/resource";

const client = generateClient<Schema>() // use this Data client for CRUDL requests
*/

/*== STEP 3 ===============================================================
Fetch records from the database and use them in your frontend component.
(THIS SNIPPET WILL ONLY WORK IN THE FRONTEND CODE FILE.)
=========================================================================*/

/* For example, in a React component, you can use this snippet in your
  function's RETURN statement */
// const { data: todos } = client.models.Todo.list()

// return <ul>{todos.map(todo => <li key={todo.id}>{todo.content}</li>)}</ul>
edwardfoyle commented 1 month ago

Hi @ujjwol05 this might be related to https://github.com/aws-amplify/amplify-backend/issues/1069 Can you try installing the latest beta versions of @aws-amplify/backend and @aws-amplify/backend-cli and see if that resolves the issue?

ujjwol05 commented 1 month ago

Hi @ujjwol05 this might be related to aws-amplify/amplify-backend#1069 Can you try installing the latest beta versions of @aws-amplify/backend and @aws-amplify/backend-cli and see if that resolves the issue?

ok upgrading helped me a bit.

The type infered for 'data' looks correct for me

 const {data} = await client.models.Todo.list()

But, Todo from the models still does not exist on the type.

const {data} = await client.models.Todo
renebrandel commented 1 month ago

@ujjwol05 - can you paste in your latest package.json?

ujjwol05 commented 1 month ago

@renebrandel


{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "sandbox-delete":  "npx amplify sandbox delete",
    "sandbox":  "npx amplify sandbox"
  },
  "dependencies": {
    "@aws-amplify/ui-react": "^6.1.6",
    "aws-amplify": "^6.0.20",
    "next": "14.1.3",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@aws-amplify/backend": "^0.13.0-beta.9",
    "@aws-amplify/backend-cli": "^0.12.0-beta.10",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "aws-cdk": "^2.133.0",
    "aws-cdk-lib": "^2.133.0",
    "constructs": "^10.3.0",
    "esbuild": "^0.20.2",
    "eslint": "^8",
    "eslint-config-next": "14.1.3",
    "tsx": "^4.7.1",
    "typescript": "^5.4.0"
  }
}
phani-srikar commented 1 month ago

Hi @ujjwol05, good to know that the upgrade resolved your issue with list queries. For the other snippet you shared i.e

const {data} = await client.models.Todo

Can you clarify what is missing here? I believe in order to get the data, you should perform any operation like get or list which might be missing in your code.

ujjwol05 commented 1 month ago

Hi @ujjwol05, good to know that the upgrade resolved your issue with list queries. For the other snippet you shared i.e

const {data} = await client.models.Todo

Can you clarify what is missing here? I believe in order to get the data, you should perform any operation like get or list which might be missing in your code.

Yes, The process of accessing type from the Todo model can be accomplished through either the get() or list() methods. However, I was expecting the functionality of client.models to provide a list of available models already ,which isn't the case for me now .Because the client.model isn't aware of the available models, As a consequence, I find myself in the position of manually typing the required models on the front end. ( no auto-completion )

oldu73 commented 1 month ago

Hi,

Below, what I did and worked for me to fix same Type issue:

phani-srikar commented 1 month ago

@ujjwol05 can you please try the above steps and see if that works for you as well? Thanks

ujjwol05 commented 3 weeks ago

@ujjwol05 can you please try the above steps and see if that works for you as well? Thanks

Did all the steps except the last 2 steps and i have same issue.

tulsirai commented 2 weeks ago

For this issue was cuased by using the @latest version of libraries. Don't use the 'latest'!!! Use the 'Beta' version, thus do the followings - Either Clean up your existing project

  1. deleted node_modules folder and file package-lock.json
  2. npm install --save-dev @aws-amplify/backend@beta @aws-amplify/backend-cli@beta
  3. npm install

Or start from scractch by following this Amplify docs for Next.js App Router (Client Components) https://docs.amplify.aws/gen2/start/quickstart/nextjs-app-router-client-components/

Hope this helps!

AnilMaktala commented 1 week ago

Hey @ujjwol05, This issue has been resolved in latest version, Please try upgrading your lib to below vesions and let us know if it resolves your issue?

    "@aws-amplify/backend": "^0.13.0-beta.20",
    "@aws-amplify/backend-cli": "^0.12.0-beta.22",
hardchor commented 1 week ago

I believe it's been (partially) fixed in the latest beta (for models), but doesn't work for custom queries/mutations. Here's my example:

// resource.ts
const schema = a.schema({
  AgentResponse: a.customType({
    name: a.string(),
  }),

  listAgents: a
    .query()
    .returns(a.ref("AgentResponse").array())
    .handler(a.handler.function(listAgentsHandler)),
});

// index.tsx
async function App() {
  // this code works, but typescript is throwing "Property 'listAgents' does not exist on type 'CustomQueries<InternalClientSchema<ModelSchema<{ types: { AgentResponse: CustomType<{ fields: { name: ModelField<Nullable<string>, never, undefined>;  }; }>; listAgents: CustomOperation<...>; ...'.ts(2339)"
  const { data: agents, errors } = await cookiesClient.queries.listAgents();

  // listAgents is however defined under models (which it shouldn't) and the below code doesn't actually work: "Error: Cannot read properties of undefined (reading 'list')"
  const { data: agents, errors } = await cookiesClient.models.listAgents.list();

  return ();
}
hangoocn commented 10 hours ago

The quickstart vite-react app does not build succesfully due to type error of Schema["Todo"]; I am using 1.0.0 version of @aws-amplify/backend, the type of Schema["Todo"] does not match the type of actual data item returned from await client.models.Todo.list(), Schema["TODO"] has a wrapping type prop.

So If I replace useState<Schema["Todo"][]>([]); with useState<Schema["Todo"]["type"][]>([]);, the build will success without error, I assume this is not by design but a bug.