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 248 forks source link

ModelMutation.delete not working for custom primary keys #1486

Closed tr-asimpson closed 2 years ago

tr-asimpson commented 2 years ago

Description

Hi,

I am attempting to delete an item using the GraphQL helpers as below. It seems this was previously working in 4.0.0

print("Deleting bike" + bike.toString());
      final request = ModelMutations.delete(bike);
      final response = await Amplify.API.mutate(request: request).response;

This is the response

I/flutter ( 9737): Mutation errors: [GraphQLResponseError{
I/flutter ( 9737):   "message": "The variables input contains a field name 'id' that is not defined for input object type 'DeleteBikeInput' "
I/flutter ( 9737): }]

This is the model

type Bike @model @auth(rules: [
  { allow: owner, operations: [create,delete]}
  { allow: private, operations: [read,update]}
  { allow: public, provider: apiKey, operations: [read,create,update,delete]}
]) @key(fields: ["key"]) {
  id: ID!
  key: String!
  name: String
  sharedUsers: String
  battery: Float
  autoUnlock: Boolean
  armed:  Boolean
  muteAudioAlarm: Boolean
  firmwareVersion: String
  locationLat: Float
  locationLon: Float
  locationAltitude: Float
  odometer: String
  tripOdometer: String
  owner: String
  updatedAt: AWSDateTime
  alarmTriggered: Boolean
}

I have attached the compiled schema.

schema.zip

Categories

Steps to Reproduce

Have a model with a custom primary key and attempt to delete an item using

      final request = ModelMutations.delete(class);
      final response = await Amplify.API.mutate(request: request).response;

See the response

I/flutter ( 9737): Mutation errors: [GraphQLResponseError{
I/flutter ( 9737):   "message": "The variables input contains a field name 'id' that is not defined for input object type 'DeleteBikeInput' "
I/flutter ( 9737): }]

You can also try deleteById


      final request = ModelMutations.deleteById(Bike.classType, bike.id);
      final response = await Amplify.API.mutate(request: request).response;

This is the response which is the same as not using deleteById

I/flutter ( 3195): Instance of 'GraphQLResponse<Bike>'
I/flutter ( 3195): Mutation errors: [GraphQLResponseError{
I/flutter ( 3195):   "message": "The variables input contains a field name 'id' that is not defined for input object type 'DeleteBikeInput' "
I/flutter ( 3195): }]```

Thanks for your help!

### Screenshots

_No response_

### Platforms

- [X] iOS
- [X] Android

### Environment

```bash
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.10.2, on Microsoft Windows [Version 10.0.19043.1586], locale en-AU)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.9.4)
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.64.2)
[√] Connected device (4 available)
[√] HTTP Host Availability

• No issues found!

Dependencies

Dart SDK 2.16.1
Flutter SDK 2.10.2

dependencies:
- amplify_analytics_pinpoint 0.4.2 [amplify_analytics_plugin_interface amplify_analytics_pinpoint_android amplify_analytics_pinpoint_ios amplify_core flutter plugin_platform_interface]
- amplify_api 0.4.2 [amplify_api_plugin_interface amplify_core collection flutter meta plugin_platform_interface]
- amplify_auth_cognito 0.4.2 [flutter amplify_auth_plugin_interface amplify_core amplify_auth_cognito_android amplify_auth_cognito_ios collection plugin_platform_interface]
- amplify_datastore 0.4.2 [flutter amplify_datastore_plugin_interface amplify_core plugin_platform_interface meta collection async]
- amplify_flutter 0.4.2 [amplify_analytics_plugin_interface amplify_api_plugin_interface amplify_auth_plugin_interface amplify_core amplify_datastore_plugin_interface amplify_storage_plugin_interface collection flutter json_annotation meta plugin_platform_interface]
- amplify_storage_s3 0.4.2 [flutter amplify_storage_plugin_interface plugin_platform_interface amplify_storage_s3_android amplify_storage_s3_ios amplify_core]
- another_flushbar 1.10.28 [flutter]
- another_transformer_page_view 1.1.0 [flutter]
- cupertino_icons 0.1.3
- firebase_core 1.12.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_messaging 11.2.8 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
- flutter 0.0.0 [characters collection material_color_utilities meta typed_data vector_math sky_engine]
- flutter_blue 0.8.0 [flutter convert protobuf rxdart collection meta]
- flutter_login 3.1.0 [flutter font_awesome_flutter provider another_transformer_page_view another_flushbar flutter_signin_button quiver url_launcher]
- flutter_progress_dialog 0.1.0 [flutter]
- flutter_settings_screens 0.3.2-null-safety [flutter path_provider provider shared_preferences pedantic]
- flutter_spinkit 5.1.0 [flutter]
- flutter_switch 0.3.2 [flutter]
- font_awesome_flutter 9.2.0 [flutter]
- get 4.6.1 [flutter]
- google_maps_flutter 2.1.1 [flutter flutter_plugin_android_lifecycle google_maps_flutter_platform_interface]
- image_picker 0.8.4+9 [flutter flutter_plugin_android_lifecycle image_picker_for_web image_picker_platform_interface]
- intl 0.17.0 [clock path]
- lint 1.7.2
- lite_rolling_switch 0.1.1 [flutter]
- location 4.3.0 [flutter location_platform_interface location_web]
- mqtt_client 9.6.5 [typed_data event_bus path crypto meta]
- nordic_dfu 3.3.0 [flutter]
- overlay_support 1.2.1 [flutter async]
- package_info_plus 1.3.0 [flutter package_info_plus_platform_interface package_info_plus_linux package_info_plus_macos package_info_plus_windows package_info_plus_web]
- path_provider 2.0.8 [flutter path_provider_android path_provider_ios path_provider_linux path_provider_macos path_provider_platform_interface path_provider_windows]
- pedantic 1.11.1
- percent_indicator 2.1.9+1 [flutter]
- permission_handler 9.2.0 [flutter meta permission_handler_android permission_handler_apple permission_handler_windows permission_handler_platform_interface]
- provider 6.0.2 [collection flutter nested]
- quiver 3.0.1+1 [matcher]
- rflutter_alert 1.1.0 [flutter]
- shared_preferences 2.0.12 [flutter shared_preferences_android shared_preferences_ios shared_preferences_linux shared_preferences_macos shared_preferences_platform_interface shared_preferences_web shared_preferences_windows]
- simple_animations 2.5.1 [flutter supercharged sa_v1_migration pedantic]
- slider_button 1.0.0 [vibration flutter]
- supercharged 1.12.0 [supercharged_dart flutter]
- syncfusion_flutter_gauges 18.4.49 [flutter syncfusion_flutter_core intl]
- url_launcher 6.0.20 [flutter url_launcher_android url_launcher_ios url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows]
- wakelock 0.6.1+2 [flutter meta wakelock_macos wakelock_platform_interface wakelock_web wakelock_windows]

transitive dependencies:
- amplify_analytics_pinpoint_android 0.4.2 [flutter]
- amplify_analytics_pinpoint_ios 0.4.2 [flutter]
- amplify_analytics_plugin_interface 0.4.2 [amplify_core flutter meta]
- amplify_api_plugin_interface 0.4.2 [amplify_core collection flutter json_annotation meta]
- amplify_auth_cognito_android 0.4.2 [flutter]
- amplify_auth_cognito_ios 0.4.2 [amplify_core flutter]
- amplify_auth_plugin_interface 0.4.2 [flutter meta amplify_core]
- amplify_core 0.4.2 [flutter plugin_platform_interface collection date_time_format meta uuid]
- amplify_datastore_plugin_interface 0.4.2 [flutter meta collection amplify_core]
- amplify_storage_plugin_interface 0.4.2 [flutter meta amplify_core]
- amplify_storage_s3_android 0.4.2 [flutter]
- amplify_storage_s3_ios 0.4.2 [flutter]
- async 2.8.2 [collection meta]
- characters 1.2.0
- charcode 1.3.1
- clock 1.1.0
- collection 1.15.0
- convert 3.0.1 [typed_data]
- cross_file 0.3.2 [flutter js meta]
- crypto 3.0.1 [collection typed_data]
- date_time_format 2.0.1
- event_bus 2.0.0
- ffi 1.1.2
- file 6.1.2 [meta path]
- firebase_core_platform_interface 4.2.5 [collection flutter meta plugin_platform_interface]
- firebase_core_web 1.6.1 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- firebase_messaging_platform_interface 3.2.1 [firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_web 2.2.9 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta]
- fixnum 1.0.0
- flutter_plugin_android_lifecycle 2.0.5 [flutter]
- flutter_signin_button 2.0.0 [flutter font_awesome_flutter]
- flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta typed_data vector_math]
- google_maps_flutter_platform_interface 2.1.5 [collection flutter plugin_platform_interface stream_transform]
- http 0.13.4 [async http_parser meta path]
- http_parser 4.0.0 [charcode collection source_span string_scanner typed_data]
- image_picker_for_web 2.1.6 [flutter flutter_web_plugins image_picker_platform_interface]
- image_picker_platform_interface 2.4.4 [cross_file flutter http plugin_platform_interface]
- js 0.6.3
- json_annotation 4.4.0 [meta]
- location_platform_interface 2.3.0 [flutter meta plugin_platform_interface]
- location_web 3.1.1 [flutter flutter_web_plugins http_parser js location_platform_interface meta]
- matcher 0.12.11 [stack_trace]
- material_color_utilities 0.1.3
- meta 1.7.0
- nested 1.0.0 [flutter]
- package_info_plus_linux 1.0.3 [package_info_plus_platform_interface flutter path]
- package_info_plus_macos 1.3.0 [flutter]
- package_info_plus_platform_interface 1.0.2 [flutter meta plugin_platform_interface]
- package_info_plus_web 1.0.4 [flutter flutter_web_plugins http meta package_info_plus_platform_interface]
- package_info_plus_windows 1.0.4 [package_info_plus_platform_interface ffi flutter win32]
- path 1.8.0
- path_provider_android 2.0.11 [flutter path_provider_platform_interface]
- path_provider_ios 2.0.7 [flutter path_provider_platform_interface]
- path_provider_linux 2.1.5 [ffi flutter path path_provider_platform_interface xdg_directories]
- path_provider_macos 2.0.5 [flutter path_provider_platform_interface]
- path_provider_platform_interface 2.0.3 [flutter platform plugin_platform_interface]
- path_provider_windows 2.0.5 [ffi flutter path path_provider_platform_interface win32]
- permission_handler_android 9.0.2+1 [flutter permission_handler_platform_interface]
- permission_handler_apple 9.0.3 [flutter permission_handler_platform_interface]
- permission_handler_platform_interface 3.7.0 [flutter meta plugin_platform_interface]
- permission_handler_windows 0.1.0 [flutter permission_handler_platform_interface]
- platform 3.1.0
- plugin_platform_interface 2.1.2 [meta]
- process 4.2.4 [file path platform]
- protobuf 2.0.1 [fixnum collection]
- rxdart 0.26.0
- sa_v1_migration 1.1.2 [flutter]
- shared_preferences_android 2.0.10 [flutter shared_preferences_platform_interface]
- shared_preferences_ios 2.0.9 [flutter shared_preferences_platform_interface]
- shared_preferences_linux 2.0.4 [file flutter path path_provider_linux shared_preferences_platform_interface]
- shared_preferences_macos 2.0.2 [flutter shared_preferences_platform_interface]
- shared_preferences_platform_interface 2.0.0 [flutter]
- shared_preferences_web 2.0.3 [flutter flutter_web_plugins shared_preferences_platform_interface]
- shared_preferences_windows 2.0.4 [file flutter path path_provider_platform_interface path_provider_windows shared_preferences_platform_interface]
- sky_engine 0.0.99
- source_span 1.8.1 [collection path term_glyph]
- stack_trace 1.10.0 [path]
- stream_transform 2.0.0
- string_scanner 1.1.0 [charcode source_span]
- supercharged_dart 1.4.0
- syncfusion_flutter_core 18.4.49 [flutter]
- term_glyph 1.2.0
- typed_data 1.3.0 [collection]
- url_launcher_android 6.0.14 [flutter url_launcher_platform_interface]
- url_launcher_ios 6.0.14 [flutter url_launcher_platform_interface]
- url_launcher_linux 2.0.3 [flutter]
- url_launcher_macos 2.0.3 [flutter]
- url_launcher_platform_interface 2.0.5 [flutter plugin_platform_interface]
- url_launcher_web 2.0.6 [flutter flutter_web_plugins url_launcher_platform_interface]
- url_launcher_windows 2.0.2 [flutter]
- uuid 3.0.5 [crypto]
- vector_math 2.1.1
- vibration 1.7.3 [flutter vibration_web]
- vibration_web 1.6.2 [flutter flutter_web_plugins]
- wakelock_macos 0.4.0 [flutter flutter_web_plugins wakelock_platform_interface]
- wakelock_platform_interface 0.3.0 [flutter meta]
- wakelock_web 0.4.0 [flutter flutter_web_plugins js wakelock_platform_interface]
- wakelock_windows 0.2.0 [flutter wakelock_platform_interface win32]
- win32 2.3.6 [ffi]
- xdg_directories 0.2.0 [meta path process]

Device

Samsung S21 Ultra

OS

Android 11

CLI Version

7.6.23

Additional Context

No response

HuiSF commented 2 years ago

Thanks @tr-asimpson for reporting this issue.

Observing the attached compiled GraphQL schema, we can see this input type:

input DeleteBikeInput {
  key: String!
}

type Mutation {
  ...
  deleteBike(input: DeleteBikeInput!, condition: ModelBikeConditionInput): Bike @aws_api_key @aws_cognito_user_pools
  ...
}

The CLI GraphQL transformer seems honor the custom PK settings @key(fields: ["key"]), where the id fields is not the primary key.

Currently amplify-codegen and amplify-flutter don't fully support custom primary key. I will investigate this feature gap, and also test and verify the behavior GraphQL transformer v2. Where the schema would be:

type Bike @model @auth(rules: [
  { allow: owner, operations: [create,delete]}
  { allow: private, operations: [read,update]}
  { allow: public, provider: apiKey, operations: [read,create,update,delete]}
])  {
  id: ID!
  key: String! @primaryKey
  name: String
  sharedUsers: String
  battery: Float
  autoUnlock: Boolean
  armed:  Boolean
  muteAudioAlarm: Boolean
  firmwareVersion: String
  locationLat: Float
  locationLon: Float
  locationAltitude: Float
  odometer: String
  tripOdometer: String
  owner: String
  updatedAt: AWSDateTime
  alarmTriggered: Boolean
}
HuiSF commented 2 years ago

Hi @tr-asimpson I did some digging, unfortunately, that should be case that amplify-codegen and amplify-flutter (amplify-ios and amplify-flutter, the dependencies of amplify-fluter) have never fully supported custom primary key.

With the current implementation of all platform libraries, it always assumes id field is the primary key, therefore when you do

final request = ModelMutations.delete(bike);

It internally generates a GraphQL document that supplies the id field as the parameter, however, in the compiled GraphQL type, it expects the key field.

This feature gap will be addressed with https://github.com/aws-amplify/amplify-flutter/issues/1426.

The workaround you can take:

  1. Not to use custom primary key Is there any specific reason to use @key(fields: ["key"])? If it's for creating index, can you use global secondary index instead (@key(name: "byKey", fields: ["key"]))?
  2. If option 1 is not possible for you, you may need to compose GraphQL document manually to delete a model with custom primary key e.g.
    // following the type DeleteBikeInput
    // input: { key: \$key } is expected to invoke deleteBike mutation
    String graphQLDocument =
      '''mutation deleteBike(\$key: ID!) {
            deleteTodo(input: { key: \$key }) {
              id
              key
              // ... other fields
            }
      }''';
    var operation = Amplify.API.mutate(
      request: GraphQLRequest<String>(document: graphQLDocument, variables: {
    'key': 'the-key-you-want-to-delete'
    }));
tr-asimpson commented 2 years ago

Thankyou @HuiSF I have implemented the manual GraphQL request for now.

Appreciate the help and all the work you and the team put into this amazing plugin!

Thanks.

HuiSF commented 2 years ago

Glad to hear @tr-asimpson I'm going to close this issue in favor of https://github.com/aws-amplify/amplify-flutter/issues/1426 please feel free to follow up, and if you have any specific use cases with custom primary key, please post in the linked issue. Thanks!