amplify-codegen
amplify-codegen copied to clipboard
Wrong type for codegen models for items with AWSJSON in their fields (DataStore)
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
- [X] I have read the guide for submitting bug reports.
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Authentication, GraphQL API, DataStore, Storage
Amplify Categories
No response
Environment information
# Put output below this line
System:
OS: macOS 12.2.1
CPU: (8) x64 Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
Memory: 1.01 GB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.13.1 - ~/.nvm/versions/node/v16.13.1/bin/node
npm: 7.19.0 - {REDACTED}/node_modules/.bin/npm
Watchman: 2022.02.14.00 - /usr/local/bin/watchman
npmPackages:
-: 0.0.1 => 0.0.1
@aws-amplify/ui-react: ^2.8.0 => 2.8.0
@aws-amplify/ui-react-internal: undefined ()
@aws-amplify/ui-react-legacy: undefined ()
@material-ui/core: ^4.12.2 => 4.12.2
@material-ui/icons: ^4.11.2 => 4.11.2
@testing-library/jest-dom: ^5.14.1 => 5.14.1
@testing-library/react: ^11.2.7 => 11.2.7
@testing-library/user-event: ^12.8.3 => 12.8.3
@types/react: ^17.0.19 => 17.0.19
@types/react-dom: ^17.0.9 => 17.0.9
@types/react-router-dom: ^5.3.3 => 5.3.3
@uiw/react-md-editor: ^3.6.3 => 3.6.3
aws-amplify: ^4.3.14 => 4.3.14
bootstrap: ^4.6.0 => 4.6.0
g: ^2.0.1 => 2.0.1
npm: ^7.19.0 => 7.19.0
react: ^17.0.2 => 17.0.2
react-app-rewired: ^2.1.8 => 2.1.8
react-dom: ^17.0.2 => 17.0.2
react-lorem-ipsum: ^1.4.9 => 1.4.9
react-markdown: ^7.0.1 => 7.0.1
react-player: ^2.9.0 => 2.9.0
react-router-dom: ^5.2.0 => 5.2.0
react-scripts: 4.0.3 => 4.0.3
rehype-katex: ^5.0.0 => 5.0.0
remark-math: ^5.1.0 => 5.1.0
source-map-loader: ^3.0.0 => 3.0.0
ts-loader: ^9.2.5 => 9.2.5
typescript: ^4.3.5 => 4.3.5
uuid: ^8.3.2 => 8.3.2 (3.3.2, 3.4.0)
web-vitals: ^1.1.2 => 1.1.2
npmGlobalPackages:
@aws-amplify/cli: 7.6.22
aws-cdk: 2.3.0
corepack: 0.10.0
npm: 8.1.2
Describe the bug
When getting an item that has AWSJSON in its fields, DataStore returns a Typescript JSON object for the AWSJSON field instead of a string.
However, the codegen models for Typescript label the field as a string instead of an object. Therefore, this causes issues since Typescript thinks an object is a string.
Expected behavior
The codegen models should have labeled AWSJSON fields as objects instead of strings.
Reproduction steps
(Not tested, hypothesized reproduction steps)
- Create Schema with a type that has AWSJSON in one of its fields.
- Use DataStore to query for an item of the above type
- Log
typeof type.fieldand it should returnobjectinstead ofstring.
Code Snippet
# GraphQL Schema
type Post @model @auth(rules: [
{allow: private, operations: [read]},
]) {
id: ID!
content: AWSJSON
}
// Put your code below this line.
import Amplify from 'aws-amplify';
import * as models from 'src/models';
// ...
const posts = await Amplify.DataStore.query(models.Post);
console.log(typeof posts[0].content);
// Should give you "object"
console.log("a" + posts[0].content);
// Should give you "a[Object object]"
console.log(posts[0].content);
// Should give you a JSON object
// src/models/index.d.ts
export declare class Post {
readonly id: string;
readonly content?: string; // <--- this gives errors
readonly createdAt?: string;
readonly updatedAt?: string;
// ...
}
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
Workarounds
Use // @ts-ignore when assigning the value to another place and act as it is a JSON object.
Other symptoms
May cause A cross-origin error was thrown. React doesn’t have access to the actual error object in development. in React.
May be related to GraphQL Transformer V2 issues: https://github.com/aws-amplify/amplify-adminui/issues/426
Hi @thecodehen 👋 Thanks for raising this issue. It has been transferred to the CLI repo because it seems the issue has to do with codegen rather than the JS Library and/or DataStore.
Thanks! Another thing to add is that the data returned by API.GraphQL used to be in string form, but I'm not sure whether it's because of DataStore or the upgrade from Transformer V1 to V2.
Hi @thecodehen , thanks for bringing this to our attention. I was able to reproduce the issue. The same behavior is also observed for the types generated using amplify codegen types . We will have a fix for this issue in upcoming releases, once we verify the expected behavior.
Just to add some additional metadata, I created a test app to look at the different ways this surfaces. Note: I'm on amplify CLI version 9.2.1 and didn't explore the dimension of past releases. https://github.com/alharris-at/codegen-396-repro
My findings:
API Interface
Write only works when serialize to a string, so if we want to support object as an input type, it'll require library updates I think.
Retrieve always returns a string-ified version of the AWSJSON object.
Due to the simplicity of the API category interface, this isn't wholly surprising, there's no significant serde layer in API, so we expect correctly serialized values as inputs to graphql, and return serialized outputs for most things, i.e. the layer speaks JSON, and is therefore restricted by its limitations (this includes, dates, times, objects represented as strings in the backend, etc.).
From my perspective this is reasonable behavior, as it is inline with the rest of the behavior here.
DataStore Interface
Write works for either a serialized version of the AWSJSON object, or an object directly as well. Looks like the library is marshalling back to string as necessary.
Read always returns a parsed version of the AWSJSON object, not a string.
Updating the generated types to use object rather than string just works, suggesting that the DataStore use-case can be fixed purely in the codegen layer.
Because of the split behavior in datastore (write string, return object), we should make some change here to normalize.
I took a look at the behavior of AWSDateTime, to see how other serialized types are behaving today. They appear to be represented in the model as a string as well (not necessarily "correct" behavior) on both read and write.
While I'm not sure if that's the right long-term behavior for our system, it means that DataStore reads of AWSJSON is the only really out-of-band behavior here, and everything else appears consistent, if not ideal.
I'll raise this with the team, and propose a next step in this issue after that.
Hi,
Is there a plan to deal with this bug (as it makes the entire AWSJSON type difficult to use with TypeScript).
Or is there a recommended workaround that doesn't involve manually hacking the Schema after every pull?
Thank you