amplify-cli: Amplify codegen models on Datastore cannot generate Type with no @model directive

Describe the bug I have a schema with no @model directive, it’s only use as typings on my typescript project. When I tried amplify datastore amplify codegen models, cli says

Unknown type Content for field value. Did you forget to add the @model directive
Error: Unknown type Value for field value. Did you forget to add the @model directive

Amplify CLI Version 4.6.0

To Reproduce Simply create a schema.graphql like this

type Post @model {
  id: ID!
  title: String!
  content: Content!
  price: Int
  rating: Float
}

type Content {
  id: String
  name: String
}

then run amplify codegen models to generate the model.

Expected behavior No error.

Desktop (please complete the following information):

  • OS: Ubuntu 18.04
  • Node Version: 10.16.0

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 19
  • Comments: 53 (6 by maintainers)

Most upvoted comments

Thank you for bringing this issue up. We are actively evaluating how we can add support non model types in DataStore.

Amplify CLI has added support for types without @model directive version 4.17.2. If you encounter any issues with model generation, please open an new issue.

Also support for this is released in the latest version of Amplify JavaScript. Please have a test.

Any update on this?

Wanted to provide an update to all customers on this thread. As @yuth mentioned we’ve been working on this and have a couple of releases in flight. You can see PRs here:

https://github.com/aws-amplify/amplify-js/pull/5128 https://github.com/aws-amplify/amplify-cli/pull/3718

We’ll update soon when releases are ready for testing.

I can confirm the changes, all working and syncing in all devices 😃

Simple test for the geolocation case requested by @sacrampton + some other directives for testing purpose.

type Restaurant
  @model
  @auth(rules: [{allow: private}]) {
  id: ID!
  name: String!
  guests: [Guest] @connection(name: "RestaurantGuests")
  rating: Int!
  location: Location
}

type Location {
  lat: Float
  lon: Float
}

type Guest
  @model
  @auth(rules: [{allow: private}]) {
  id: ID!
  name: String!
  restaurant: Restaurant @connection(name: "RestaurantGuests")
}

Boom! Thanks all for this much waited request. 🎉🚀


src/models/schema.js

"nonModels": {
        "Location": {
            "name": "Location",
            "fields": {
                "lat": {
                    "name": "lat",
                    "isArray": false,
                    "type": "Float",
                    "isRequired": false,
                    "attributes": []
                },
                "lon": {
                    "name": "lon",
                    "isArray": false,
                    "type": "Float",
                    "isRequired": false,
                    "attributes": []
                }
            }
        }
    }

We’re actively working on this, while we cannot guarantee a date we hope to have something in the coming weeks or two

I can’t get this to work when using this with flutter it does not create the object

This is huge! I will be testing this out shortly and let you know if I find anything. Great work guys.

My concern with this stuff is geolocations - the documentation tells you how to create a custom geolocation search resolver that creates ElasticSearch GeoPoints. I’m not sure this works with DataStore and I’m not sure there is any work around to this.

https://aws-amplify.github.io/docs/cli-toolchain/graphql#add-a-custom-geolocation-search-resolver-that-targets-an-elasticsearch-domain-created-by-searchable

The workaround is saying have this when doing codegen for models

type Location @model {
  lat: Float
  lon: Float
}

Then have this when doing amplify push…

type Location {
  lat: Float
  lon: Float
}

Is this even valid?

@sacrampton This is not a valid option. Datastore doesn’t support nested types yet. If you use codegen with @model but then remove it for amplify push you will end up with different structures. I have tested it, you can still use Datastore.save locally and it works but it will not synchronize via apsync. If it helps I can post the error messages in this thread.

Ok good news, I’m not sure what happened as I deleted the API and recreated it before, but something was out of sync, and after further schema modifications and more amplify codegen models and amplify push commands later, and it’s all working and syncing in RN 🎉

Panic over, and overarching excitement back again!

+1

Here is my schema:

type Event @model @searchable { id: ID! date: String! maxSubscribers: Int totalSubscribers: Int polygon: Location Timetable: [Timetable] lastDateToSubscribe: String eventOwner: Subscriber! @connection name: String! description: String coordinates: [Coordinate] planned: Boolean subscribers: [EventSubscribers] @connection(name: “Event”) }

type EventSubscribers @model(queries: null) @key(fields: [“eventID”, “createdAt”]) { eventID: String! createdAt: String! subscriber: Subscriber! @connection(name: “EventSubscriber”) event: Event! @connection(name: “Event”) totalPersons: Int! }

type Subscriber @model { id: ID! name: String email: String phone: String device: String expoToken: String addressLocation: Location address: String complete: Boolean events: [EventSubscribers] @connection(name: “EventSubscriber”) planning: [Planning] @connection(name: “SubscriberPlanning”) }

type Planning @model { id: ID! event: Event subscriber: Subscriber @connection(name: “SubscriberPlanning”) location: Location description: String type: String time: String notificationSend: Boolean }

type Location { type: String coordinates: [[[Float]]] } type Coordinate { longitude: Float latitude: Float }

type Timetable { description: String startTime: String endTime: String }

input LocationInput { type: String coordinates: [[[Float]]] }

type EventConnection { items: [Event] total: Int nextToken: String }

input PointInput { type: String coordinates: [Float] }

type Query { nearbyEvent(location: PointInput!): EventConnection }

type Mutation { sendNotification(input: NotificationInput): NotificationResult @function(name: “sendNotifications-${env}”) createPayment(input: PaymentInput): PaymentResult @function(name: “makePayment-${env}”) }

input PaymentInput { amount: Float total: Int }

type PaymentResult { statusCode: Int body: String }

type NotificationResult { result: String } input NotificationInput { action: String data: String }

@sacrampton I am using iOS target at this moment, but I suppose it works the same way with other target platforms. When I say import I mean import the code to Xcode (iOS IDE).

  1. First I set my graph with @model directives and generate front-end code. It can be generated with the amplify CLI ($amplify codegen models) or with specific method for each target platform: Once generated I get front-end code for my target platform (iOS) on project-root-directory/amplify/generated/models(app/src/main/java/com/amplifyframework.datastore.generated.model on Android, and ./models on Javascript). This is done locally (on your machine without any backend involved) through the codegen.

  2. Then I copy manually those files to a safe path or rename them (so in next codegen executions doesn’t get overridden), and import them to my project.

    1. iOS: import them to Xcode and add them as target for build time.
    1. Android: IDK
    1. Javascript: import { Post, Content } from "./safe-models"; *When I say import, I mean import them to the app code, with your IDE/whatever. As this is the front-end code to be used when compiling your app.
  1. Remove the @model directive, and $amplify api push.

This works, but it is just a workaround, as requires manual handling every time you update your schema.

Hmm it seems I can’t reproduce it now. Maybe I missed something last time. I’ll open an issue if it happens again.

@jackatkoeln thanks for confirming it.

@mdebo - My workaround is still the one outlined by @lazy-var in https://github.com/aws-amplify/amplify-cli/issues/2988#issuecomment-567711467 to codegen with the @model annotations on all nested-types but then remove them before doing an amplify push.

Not ideal in the long run but at least for the the short term it’s an option.

Edit: @jackatkoeln confirmed below that this actually doesn’t work because it won’t sync correctly with the backend. Apologies for adding to the confusion here.

@sacrampton I think both will overlap somewhere. The approach I am following is:

  1. Generate the code with @model directive: $amplify codegen models, and import it to the project (manually so later it doesn’t get overridden).
  2. Remove the @model directive, and $amplify api push.

I still couldn’t test it as I am migrating other code from the previous SDK. Also I am using custom resolvers that can make it a little bit trickier until I manage to confirm if it works.

you can give it a try.

I have the same issue - my use case is for geolocations (lat/lon) that are passed to ElasticSearch as a geopoint for geospatial queries. Without this being fixed we can’t move forward.