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
81 stars 71 forks source link

[Gen2] model datetime type can not be used as sortKeys of secondaryIndexes #2657

Open hangoocn opened 5 days ago

hangoocn commented 5 days ago

Environment information

System:
  OS: Windows 10 10.0.19045
  CPU: (12) x64 11th Gen Intel(R) Core(TM) i5-11400 @ 2.60GHz 
  Memory: 15.16 GB / 31.84 GB
Binaries:
  Node: 20.15.0 - C:\Program Files\nodejs\node.EXE
  Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
  npm: 9.8.1 - C:\Program Files\nodejs\npm.CMD
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 1.0.0
  @aws-amplify/backend-cli: 1.0.1
  aws-amplify: 6.2.0
  aws-cdk: 2.140.0
  aws-cdk-lib: 2.140.0
  typescript: 5.4.5
AWS environment variables:
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
  AWS_STS_REGIONAL_ENDPOINTS = regional
No CDK environment variables

Data packages

├─┬ @aws-amplify/backend-cli@1.0.1
│ └─┬ @aws-amplify/schema-generator@1.0.0
│   └── @aws-amplify/graphql-schema-generator@0.8.4
└─┬ @aws-amplify/backend@1.0.0
  └─┬ @aws-amplify/backend-data@1.0.0
    └── @aws-amplify/data-construct@1.8.1

Description

What I want to do is to sort results by createdAt, so below is what I did:

Create a model with datetime field and add a secondaryIndex like this:

 Message: a
    .model({
      roomId: a.id().required(),
      createdAt: a.datetime(),
      content: a.string().required(),
    })
    .secondaryIndexes(index => [index('roomId').sortKeys(['createdAt']).queryField('listByDate')])
    .authorization(allow => [
      allow.owner(),
    ]),

then run the query in the app:

client.models.Message.listByDate({ roomId }, { sortDirection: 'DESC' }

It will then show error Validation error of type UnknownType: Unknown type ModelAWSDateTimeKeyConditionInput.

I also noticed two patterns when testing it in sandbox:

  1. It is consistently reproducable when first remove other field like content from model, wait sandbox rebuild, then add it back
  2. If now change createdAt type to string, it will start to work, and then you change it back to datetime, it also work.
  3. Then you repeat step 1 above, it starts to not work again.

It always have the error when deploy to non-sandbox env.

I am not sure if this is correct way of sorting result by create time in gen 2, but this was what used to work in gen 1.

chrisbonifacio commented 2 days ago

Hi @hangoocn thanks for raising this issue. I was not able to reproduce the behavior described in the issue with the latest versions of amplify backend and library, the following backend schema, and frontend code:

  Message: a
    .model({
      roomId: a.id().required(),
      createdAt: a.datetime(),
      content: a.string().required(),
    })
    .secondaryIndexes((index) => [
      index("roomId").sortKeys(["createdAt"]).queryField("listByDate"),
    ])
    .authorization((allow) => [allow.owner()]),
"use client";
import { Authenticator } from "@aws-amplify/ui-react";
import "@aws-amplify/ui-react/styles.css";

import CustomerCreateForm from "@/ui-components/CustomerCreateForm";
import { generateClient } from "aws-amplify/api";
import { Schema } from "@/amplify/data/resource";

const client = generateClient<Schema>();

const App = () => {
  const createMessage = async () => {
    const { data, errors } = await client.models.Message.create({
      roomId: "123",
      content: "Hello",
    });

    console.log({ data, errors });
  };

  const listByDate = async () => {
    const { data, errors } = await client.models.Message.listByDate(
      { roomId: "123" },
      { sortDirection: "DESC" }
    );

    console.log({ data, errors });
  };

  return (
    <Authenticator>
      {({ user, signOut }) => {
        return (
          <>
            <h1>Hello {user?.username}</h1>
            <h1>Protected content!</h1>

            <button onClick={createMessage}>Create Message</button>
            <button onClick={listByDate}>List By Date</button>

            <CustomerCreateForm />
          </>
        );
      }}
    </Authenticator>
  );
};

export default App;

Result:

CleanShot 2024-06-26 at 10 52 00@2x

I was able to use createdAt with a sortDirection of DESC

Also, I did not run into any errors when changing sortDirection to ASC

CleanShot 2024-06-26 at 10 53 42@2x

chrisbonifacio commented 2 days ago

I noticed you might not be using the latest versions of the amplify packages. Can you upgrade aws-amplify, @aws-amplify/backend, and @aws-amplify/backend-cli to latest and see if that resolves the issue?

hangoocn commented 2 days ago

Hi @chrisbonifacio , I have upgraded my packages to below:

System:
  OS: Windows 11 10.0.22631
  CPU: (12) x64 11th Gen Intel(R) Core(TM) i5-11400 @ 2.60GHz
  Memory: 15.67 GB / 31.84 GB
Binaries:
  Node: 20.15.0 - C:\Program Files\nodejs\node.EXE
  Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
  npm: 9.8.1 - C:\Program Files\nodejs\npm.CMD
  pnpm: undefined - undefined
NPM Packages:
  @aws-amplify/backend: 1.0.3
  @aws-amplify/backend-cli: 1.0.4
  aws-amplify: 6.3.8
  aws-cdk: 2.140.0
  aws-cdk-lib: 2.140.0
  typescript: 5.4.5
AWS environment variables:
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
  AWS_STS_REGIONAL_ENDPOINTS = regional
No CDK environment variables

but still able to see the same error, "Validation error of type UnknownType: Unknown type ModelAWSDateTimeKeyConditionInput"

The error is not always reproducable even on my side, but I can reproduce most of time.

May I know if 'ModelAWSDateTimeKeyConditionInput' is an expected type? I want to have a try to debug on the amplify source code

chrisbonifacio commented 2 days ago

can you check and share the version of @aws-amplify/data-schema and @aws-amplify/data-schema-types in your dependencies (or node_modules)?

You might have to delete node_modules and reinstall your dependencies

hangoocn commented 12 hours ago

I checked they are: @aws-amplify/data-schema: 1.0.0 @aws-amplify/data-schema-types: 1.0.0

Even I install the latest of these files: "@aws-amplify/backend": "^1.0.4", "@aws-amplify/backend-cli": "^1.1.0",

It seems the latest @aws-amplify/backend-data depends on 1.0.0 version here, could you suggest a walkaround to use latest version?

chrisbonifacio commented 5 hours ago

You should be able to update them by running:

npm update @aws-amplify/data-schema @aws-amplify/data-schema-types