Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Feb 21, 2024

Upgrade guide

Amplify Flutter v2 has changes in Auth, Analytics, Storage, GraphQL API & DataStore that may require migration when upgrading from v1.

Auth

Time Based One Time Password (TOTP) Exception Handling

In Amplify Flutter v1, Amplify.Auth.verifyTotpSetup() throws an EnableSoftwareTokenMfaException if the provided code was incorrect. In Amplify Flutter v2 a CodeMismatchException is thrown.

Auth Flow in Amplify Config

In Amplify Flutter v1, the value of “authenticationFlowType” from the Amplify configuration object is used as the default AuthenticationFlowType if none is provided when calling Amplify.Auth.signIn().

In Amplify Flutter v2, default type is AuthenticationFlowType.userSrpAuth. To change the authentication flow type, you can provide a value in the sign in options under options parameter..

await Amplify.Auth.signIn(
username: 'username',
password: 'password',
options: const SignInOptions(
pluginOptions: CognitoSignInPluginOptions(
authFlowType: AuthenticationFlowType.userSrpAuth,
),
),
)

Analytics

Configuration of autoFlushEventsInterval

In Amplify Flutter v1, the autoFlushEventsInterval value was configured manually in the amplifyconfiguration.dart file. In Amplify Flutter v2, the autoFlushEventsInterval value is not read from amplifyconfiguration.dart but instead is passed directly to the AmplifyAnalyticsPinpoint() constructor under the AnalyticsPinpointPluginOptions. The default value for autoFlushEventsInterval remains at 30 seconds, consistent with the behavior in Amplify Flutter v1.

Storage

key and StorageAccessLevel have been replaced by StoragePath

In Amplify Flutter v1, files operations were performed based on a key and an AccessLevel. Amplify translated these values to a full file path. The AccessLevel (guest, protected, or private) determined what prefix to use (“public/”, “protected/<user_identity_id>/”, or “private/<user_identity_id>/”). Amplify Flutter v1 forms the full path using the prefix and the provided key.

Amplify Flutter v2 allows for full control of the path of the storage object. Storage paths can be constructed either from a static string or from the current users identity id using the StoragePath class.

To migrate from v1 to v2, replace all uses of key with path and remove uses of StorageAccessLevel. The path should include the prefix that was previously added by Amplify automatically.

Example Migration for Public Files
// upload file to "public/file.txt" in Amplify Flutter v1
Amplify.Storage.uploadFile(
localFile: file,
key: 'file.txt',
options: StorageUploadFileOptions(
accessLevel: StorageAccessLevel.guest,
),
);
// upload file to "public/file.txt" in Amplify Flutter v2
Amplify.Storage.uploadFile(
localFile: file,
path: const StoragePath.fromString("public/file.txt"),
);
Example Migration for Protected Files
// upload file to "protected/<user_identity_id>/file.txt" in Amplify Flutter v1
Amplify.Storage.uploadFile(
localFile: file,
key: 'file.txt',
options: StorageUploadFileOptions(
accessLevel: StorageAccessLevel.protected,
),
);
// upload file to "protected/<user_identity_id>/file.txt" in Amplify Flutter v2
Amplify.Storage.uploadFile(
localFile: file,
path: StoragePath.fromIdentityId(
(identityId) => "protected/$identityId/file.txt",
),
);
Example Migration for Private Files
// upload file to "private/<user_identity_id>/file.txt" in Amplify Flutter v1
Amplify.Storage.uploadFile(
localFile: file,
key: 'file.txt',
options: StorageUploadFileOptions(
accessLevel: StorageAccessLevel.private,
),
);
// upload file to "private/<user_identity_id>/file.txt" in Amplify Flutter v2
Amplify.Storage.uploadFile(
localFile: file,
path: StoragePath.fromIdentityId(
(identityId) => "private/$identityId/file.txt",
),
);

Prefix Resolver has been removed

With the introduction of StoragePath, there is no need for a prefix resolver. Simply specify the full path when constructing the StoragePath.

Delimiter has been moved to the List API Options

In Amplify Flutter v1 AmplifyStorageS3 accepted a delimiter option. This was used in list operations to determine sub paths. This option is now available as part of the List API options.

final result = Amplify.Storage.list(
path: const StoragePath.fromString('public/album/'),
options: const StorageListOptions(
pageSize: 50,
pluginOptions: S3ListPluginOptions(
excludeSubPaths: true,
delimiter: '/'
),
),
);

DataStore

Configuration

In Amplify Flutter v1, the AmplifyDataStore() constructor allows for the customization of the plugin through optional parameters such as errorHandler, conflictHandler, syncExpression, syncInterval, syncMaxRecords, syncPageSize, and authModeStrategy. In Amplify Flutter v2, these parameters have been relocated under DataStorePluginOptions, with default values that mirror those of Amplify Flutter v1.

Models & Query Predicates (GraphQL API & DataStore)

Configuration

In Amplify Flutter v1, the AmplifyAPI() constructor accepts optional parameters such as authProviders, baseHttpClient, modelProvider, and subscriptionOptions. In Amplify Flutter v2, these parameters have been relocated to APIPluginOptions.

Generated Models

Model.fromJson()

Amplify Flutter v2 now decodes AppSync GraphQL responses in their original shape (#816). In doing so, we’ve removed the previous transformations that happened after receiving an AppSync response. This requires data Models to be regenerated with the latest Amplify CLI. After upgrading to Amplify Flutter v2 please run the following:

$ amplify upgrade
# from the root of your Flutter project
$ amplify codegen models
Model.getId()

Amplify Flutter v2 removes all usage of the generated Model.getId() method. Replace all instances of Model.getId() and with Model.modelIdentifier.

Nested Model Query Predicates

Query predicates for nested model relationships when passing Model.id for equal and not equal operations are no longer supported. Please update your query predicates to use Model.modelIdentifier, for example:

- Post.BLOG.eq(blog1.id)
+ Post.BLOG.eq(blog1.modelIdentifier)

Or

- Post.BLOG.eq("1234") =>
+ Post.BLOG.eq(BlogModelIdentifier(id: "1234"))

Support For Only Custom Primary Key Enabled Back-Ends

Amplify Flutter V2 no longer supports the Amplify CLI feature flag respectprimarykeyattributesonconnectionfield to be disabled.

If this feature flag is already enabled in your current project you can skip this section.

graphql.schemaFeature Flag OnFeature Flag off
has @primaryKeyNo further action requiredStart at step 1.
no @primaryKeyNo further action requiredSkip to step 4.

If the feature flag is turned off AND your model schema has the @primaryKey annotation, please follow these migration steps.

If the feature flag is turned off, but your graphql.schema does not contain references to @primaryKey, jump to step 4.

  1. Remove @primaryKey references from your graphql.schema
  2. Run $ amplify push
  3. Run $ amplify codegen models
  4. Enabled the feature flag:
    1. Locate amplify/cli.json inside your project
    2. Enable the feature flag:
"features": {
"graphqltransformer": {
...
"respectprimarykeyattributesonconnectionfield": true,
...
},
}
  1. Run $ amplify push
  2. Run $ amplify codegen models