aws-amplify / amplify-flutter

A declarative library with an easy-to-use interface for building Flutter applications on AWS.
https://docs.amplify.aws
Apache License 2.0
1.33k stars 247 forks source link

Amplify Codegen for Flutter generating invalid `ModelProvider.dart` #5187

Open felixeriksson opened 3 months ago

felixeriksson commented 3 months ago

Description

Hello! I have an existing AppSync API that I want to generate models for in a Flutter app, for use with the Amplify AppSync client. The schema of the API is attached.

It seems that if the schema does not contain any @model directive on any type (which is the situation I'm in, as all the backend resources for my API are defined outside of the Flutter app project), the generated ModelProvider.dart is invalid, as it has no implementation of getModelTypeByModelName.

Missing concrete implementation of 'ModelProviderInterface.getModelTypeByModelName'.
Try implementing the missing method, or make the class abstract.

I have a fresh installation of @aws-amplify/cli@12.12.4 Output of npm list -g --depth=1:

+-- @aws-amplify/cli@12.12.4
| +--  error: ENOENT: no such file or directory, open 'C:\Users\felix\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\@octokit\endpoint\package.json
| +--  error: ENOENT: no such file or directory, open 'C:\Users\felix\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\@octokit\request\package.json
| +-- axios@1.7.2
| +--  error: ENOENT: no such file or directory, open 'C:\Users\felix\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\esm\package.json
| +-- rimraf@3.0.2
| `-- tar-stream@2.2.0
+-- aws-cdk@2.143.1
| `-- UNMET OPTIONAL DEPENDENCY fsevents@2.3.2
+-- firebase-tools@13.8.2
| +-- @google-cloud/cloud-sql-connector@1.3.0
| +-- @google-cloud/pubsub@3.7.5
| +-- abort-controller@3.0.0
| +-- ajv@6.12.6
| +-- archiver@5.3.2
| +-- async-lock@1.3.2
| +-- body-parser@1.20.2
| +-- chokidar@3.6.0
| +-- cjson@0.3.3
| +-- cli-table@0.3.11
| +-- colorette@2.0.20
| +-- commander@4.1.1
| +-- configstore@5.0.1
| +-- cors@2.8.5
| +-- cross-env@5.2.1
| +-- cross-spawn@7.0.3
| +-- csv-parse@5.5.5
| +-- deep-equal-in-any-order@2.0.6
| +-- exegesis@4.1.2
| +-- exegesis-express@4.0.0
| +-- express@4.19.2
| +-- filesize@6.4.0
| +-- form-data@4.0.0
| +-- fs-extra@10.1.0
| +-- fuzzy@0.1.3
| +-- gaxios@6.5.0
| +-- glob@7.2.3
| +-- google-auth-library@9.9.0
| +-- inquirer@8.2.6
| +-- inquirer-autocomplete-prompt@2.0.1
| +-- jsonwebtoken@9.0.2
| +-- leven@3.1.0
| +-- libsodium-wrappers@0.7.13
| +-- lodash@4.17.21
| +-- marked@4.3.0
| +-- marked-terminal@5.2.0
| +-- mime@2.6.0
| +-- minimatch@3.1.2
| +-- morgan@1.10.0
| +-- node-fetch@2.7.0
| +-- open@6.4.0
| +-- ora@5.4.1
| +-- p-limit@3.1.0
| +-- pg@8.11.5
| +-- portfinder@1.0.32
| +-- progress@2.0.3
| +-- proxy-agent@6.4.0
| +-- retry@0.13.1
| +-- rimraf@3.0.2
| +-- semver@7.6.2
| +-- sql-formatter@15.3.1
| +-- stream-chain@2.2.5
| +-- stream-json@1.8.0
| +-- strip-ansi@6.0.1
| +-- superstatic@9.0.3
| +-- tar@6.2.1
| +-- tcp-port-used@1.0.2
| +-- tmp@0.2.3
| +-- triple-beam@1.4.1
| +-- universal-analytics@0.5.3
| +-- update-notifier-cjs@5.1.6
| +-- uuid@8.3.2
| +-- winston@3.13.0
| +-- winston-transport@4.7.0
| +-- ws@7.5.9
| `-- yaml@2.4.2
`-- npm@6.14.9
  +-- abbrev@1.1.1
  +-- ansicolors@0.3.2
  +-- ansistyles@0.1.3
  +-- aproba@2.0.0
  +-- archy@1.0.0
  +-- bin-links@1.1.8
  +-- bluebird@3.5.5
  +-- byte-size@5.0.1
  +-- cacache@12.0.3
  +-- call-limit@1.1.1
  +-- chownr@1.1.4
  +-- ci-info@2.0.0
  +-- cli-columns@3.1.2
  +-- cli-table3@0.5.1
  +-- cmd-shim@3.0.3
  +-- columnify@1.5.4
  +-- config-chain@1.1.12
  +-- debuglog@1.0.1
  +-- detect-indent@5.0.0
  +-- detect-newline@2.1.0
  +-- dezalgo@1.0.3
  +-- editor@1.0.0
  +-- figgy-pudding@3.5.1
  +-- find-npm-prefix@1.0.2
  +-- fs-vacuum@1.2.10
  +-- fs-write-stream-atomic@1.0.10
  +-- gentle-fs@2.3.1
  +-- glob@7.1.6
  +-- graceful-fs@4.2.4
  +-- has-unicode@2.0.1
  +-- hosted-git-info@2.8.8
  +-- iferr@1.0.2
  +-- imurmurhash@0.1.4
  +-- infer-owner@1.0.4
  +-- inflight@1.0.6
  +-- inherits@2.0.4
  +-- ini@1.3.5
  +-- init-package-json@1.10.3
  +-- is-cidr@3.0.0
  +-- json-parse-better-errors@1.0.2
  +-- JSONStream@1.3.5
  +-- lazy-property@1.0.0
  +-- libcipm@4.0.8
  +-- libnpm@3.0.1
  +-- libnpmaccess@3.0.2
  +-- libnpmhook@5.0.3
  +-- libnpmorg@1.0.1
  +-- libnpmsearch@2.0.2
  +-- libnpmteam@1.0.2
  +-- libnpx@10.2.4
  +-- lock-verify@2.1.0
  +-- lockfile@1.0.4
  +-- lodash._baseindexof@3.1.0
  +-- lodash._baseuniq@4.6.0
  +-- lodash._bindcallback@3.0.1
  +-- lodash._cacheindexof@3.0.2
  +-- lodash._createcache@3.1.2
  +-- lodash._getnative@3.9.1
  +-- lodash.clonedeep@4.5.0
  +-- lodash.restparam@3.6.1
  +-- lodash.union@4.6.0
  +-- lodash.uniq@4.5.0
  +-- lodash.without@4.4.0
  +-- lru-cache@5.1.1
  +-- meant@1.0.2
  +-- mississippi@3.0.0
  +-- mkdirp@0.5.5
  +-- move-concurrently@1.0.1
  +-- node-gyp@5.1.0
  +-- nopt@4.0.3
  +-- normalize-package-data@2.5.0
  +-- npm-audit-report@1.3.3
  +-- npm-cache-filename@1.0.2
  +-- npm-install-checks@3.0.2
  +-- npm-lifecycle@3.1.5
  +-- npm-package-arg@6.1.1
  +-- npm-packlist@1.4.8
  +-- npm-pick-manifest@3.0.2
  +-- npm-profile@4.0.4
  +-- npm-registry-fetch@4.0.7
  +-- npm-user-validate@1.0.1
  +-- npmlog@4.1.2
  +-- once@1.4.0
  +-- opener@1.5.1
  +-- osenv@0.1.5
  +-- pacote@9.5.12
  +-- path-is-inside@1.0.2
  +-- promise-inflight@1.0.1
  +-- qrcode-terminal@0.12.0
  +-- query-string@6.8.2
  +-- qw@1.0.1
  +-- read@1.0.7
  +-- read-cmd-shim@1.0.5
  +-- read-installed@4.0.3
  +-- read-package-json@2.1.1
  +-- read-package-tree@5.3.1
  +-- readable-stream@3.6.0
  +-- readdir-scoped-modules@1.1.0
  +-- request@2.88.0
  +-- retry@0.12.0
  +-- rimraf@2.7.1
  +-- safe-buffer@5.1.2
  +-- sha@3.0.0
  +-- slide@1.1.6
  +-- sorted-object@2.0.1
  +-- ssri@6.0.1
  +-- tar@4.4.13
  +-- text-table@0.2.0
  +-- tiny-relative-date@1.3.0
  +-- umask@1.1.0
  +-- unique-filename@1.1.1
  +-- unpipe@1.0.0
  +-- update-notifier@2.5.0
  +-- uuid@3.3.3
  +-- validate-npm-package-license@3.0.4
  +-- validate-npm-package-name@3.0.0
  +-- which@1.3.1
  +-- worker-farm@1.7.0
  `-- write-file-atomic@2.4.3

A similar issue can be found here: https://github.com/aws-amplify/amplify-flutter/issues/1455

Categories

Steps to Reproduce

For an existing AppSync API, run (using aws-cli/2.1.22): aws appsync get-introspection-schema --api-id <API-ID> --region <REGION> --format SDL schema.graphql Then amplify codegen models --model-schema schema.graphql --target flutter --output-dir ./api-models

Screenshots

bild

Platforms

Flutter Version

3.22.2

Amplify Flutter Version

2.3.0 (amplify_flutter, amplify_api and amplify_auth_cognito)

Deployment Method

Amplify CLI

Schema

schema {
  query: Query
  mutation: Mutation
}

type AddToTenantResponse {
  success: Boolean
}

type ColtivaDevice {
  device_id: String!
  device_name: String!
  plant_species: String
  pumps: [Pump!]!
  sensors: [Sensor!]!
}

#  To be deprecated, use Tenant and ColtivaDevice instead
type GreenwatchDeviceData {
  device_ids: [String!]
  device_names: [String!]
  plant_species: [String]
  pumps: [[Pump]]
  sensors: [[Sensor]]
  tenant_name: String!
}

type GreenwatchSensorData {
  EC: Float
  air_temperature: Float
  humidity: Float
  pH: Float
  timestamp: Int!
  water_level: Float
  water_temperature: Float
}

type Mutation {
  addToTenant(device_id: ID!, tenant_id: ID!): AddToTenantResponse
  removeFromTenant(device_id: ID!, tenant_id: ID!): RemoveFromTenantResponse
  #  volume_to_pump is in milliliters
  runRefillPump(device_id: ID!, pump_no: Int!, tenant_id: ID!, volume_to_pump: Int!): RunPumpResponse
  #  Note: setDeviceProperties behaves in a PUT-like manner; any pump or sensor omitted in the EditableDeviceProperties payload are removed.
  setDeviceProperties(input: SetDevicePropertiesInput!): SetDevicePropertiesResponse
  storeFirebaseCloudMessagingToken(fcm_token: String!, tenant_id: ID!): StoreFirebaseCloudMessagingTokenResponse
}

type Pump {
  pump_id: Int!
  pump_name: String!
}

type Query {
  #  To be deprecated, use "tenant" instead
  getDevices(tenant_id: ID!): GreenwatchDeviceData
  getRecentSensorData(device_id: ID!, newer_than: Int!, tenant_id: ID!): [GreenwatchSensorData]
  tenant(tenant_id: ID!): Tenant
}

type RemoveFromTenantResponse {
  success: Boolean
}

# # Mutation responses
type RunPumpResponse {
  command_sent: Boolean
}

type Sensor {
  lower_threshold: Float!
  lower_threshold_alarms: Boolean
  sensor_friendly_name: String!
  sensor_name: String!
  units: String!
  upper_threshold: Float!
  upper_threshold_alarms: Boolean
}

type SetDevicePropertiesResponse {
  device: ColtivaDevice
}

type StoreFirebaseCloudMessagingTokenResponse {
  success: Boolean
}

type Tenant {
  devices: [ColtivaDevice!]
  tenant_id: ID!
  tenant_name: String!
  users: [User!]
}

type User {
  #  AWS Cognito ID
  user_email: String!
  user_id: ID!
}

input EditableDeviceProperties {
  device_name: String!
  pumps: EditablePumps!
  sensors: EditableSensors!
}

# # Mutation inputs
input EditableLiquidProperties {
  concentration: Float
  type: String
}

input EditablePumpProperties {
  liquid: EditableLiquidProperties
  model: String
  name: String!
}

input EditablePumps {
  pump_1: EditablePumpProperties!
  pump_2: EditablePumpProperties!
  pump_3: EditablePumpProperties!
  pump_4: EditablePumpProperties!
  pump_5: EditablePumpProperties!
  pump_6: EditablePumpProperties!
  pump_7: EditablePumpProperties!
}

input EditableSensorProperties {
  lower_threshold: Float!
  lower_threshold_alarms: Boolean!
  upper_threshold: Float!
  upper_threshold_alarms: Boolean!
}

input EditableSensors {
  EC: EditableSensorProperties!
  air_temperature: EditableSensorProperties!
  humidity: EditableSensorProperties!
  pH: EditableSensorProperties!
  water_level: EditableSensorProperties!
  water_temperature: EditableSensorProperties!
}

input SetDevicePropertiesInput {
  device_id: ID!
  properties: EditableDeviceProperties!
  tenant_id: ID!
}
Jordan-Nelson commented 3 months ago

Hi @felixeriksson - Thanks for opening the issue. The code generation will not work without @model annotations, which are not present in the schema. You may need to edit the schema manually for codgen to work properly. I have reached out to our CLI team to ask if this is expected. I will let you when I have an update.

Jordan-Nelson commented 3 months ago

Are you trying to use Amplify DataStore or Amplify GraphQL API?

felixeriksson commented 3 months ago

Hi Jordan, thanks for the reply! I'm trying to configure Amplify with an existing GraphQL API (defined in CF in another repo), so I guess that would be Amplify GraphQL API. I've consulted the documentation here, and used amplify codegen models.

felixeriksson commented 3 months ago

Hi Jordan, thanks for the reply! I'm trying to configure Amplify with an existing GraphQL API (defined in CF in another repo), so I guess that would be Amplify GraphQL API. I've consulted the documentation here, and used amplify codegen models.

...thinking more closely about it, I don't believe the changes I did in amplifyconfiguration.json, according to the docs linked above, had any influence on the output when I ran

aws appsync get-introspection-schema --api-id <API-ID> --region <REGION> --format SDL schema.graphql
amplify codegen models --model-schema schema.graphql --target flutter --output-dir ./api-models

I haven't fully understood what you're supposed to be able to achieve by editing amplifyconfiguration.json as per the instructions. What I'm looking for is

  1. generated model classes for GraphQL types,
  2. and for GraphQL inputs
  3. and some way to not have to hand-write the GraphQL request document, like what seems to be used here
Jordan-Nelson commented 3 months ago

@felixeriksson thanks for the info. I suspect the following commands are either not correct or do not include a proper call out that manual modifications to the schema may be required, but I am still trying to confirm this with our AppSync and codgen teams. I will let you know when I have more info.

aws appsync get-introspection-schema --api-id <API-ID> --region <REGION> --format SDL schema.graphql
amplify codegen models --model-schema schema.graphql --target flutter --output-dir ./api-models