diff --git a/CHANGELOG.md b/CHANGELOG.md index 95ac776..a14396f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 15.0.0 + +* Breaking changes: + * Changed the typing of `AppwriteException`'s response parameter from a `dynamic` object to an optional string (`?String`). + +## 14.0.0 + +* Fixed realtime pong response. +* Fixed issues with `chunkedUpload` method. + ## 13.0.0 * Fixed realtime reconnection issues diff --git a/README.md b/README.md index fdfc026..b6c40f2 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Add this to your package's `pubspec.yaml` file: ```yml dependencies: - appwrite: ^14.0.0 + appwrite: ^15.0.0 ``` You can install packages from the command line: diff --git a/lib/query.dart b/lib/query.dart index e407f7f..4962c9e 100644 --- a/lib/query.dart +++ b/lib/query.dart @@ -9,9 +9,7 @@ class Query { Query._(this.method, [this.attribute = null, this.values = null]); Map<String, dynamic> toJson() { - final map = <String, dynamic>{ - 'method': method, - }; + final map = <String, dynamic>{'method': method}; if (attribute != null) { map['attribute'] = attribute; @@ -85,12 +83,18 @@ class Query { Query._('contains', attribute, value).toString(); static String or(List<String> queries) => - Query._('or', null, queries.map((query) => jsonDecode(query)).toList()) - .toString(); + Query._( + 'or', + null, + queries.map((query) => jsonDecode(query)).toList(), + ).toString(); static String and(List<String> queries) => - Query._('and', null, queries.map((query) => jsonDecode(query)).toList()) - .toString(); + Query._( + 'and', + null, + queries.map((query) => jsonDecode(query)).toList(), + ).toString(); /// Specify which attributes should be returned by the API call. static String select(List<String> attributes) => diff --git a/lib/services/account.dart b/lib/services/account.dart index c458467..8c93223 100644 --- a/lib/services/account.dart +++ b/lib/services/account.dart @@ -5,26 +5,24 @@ class Account extends Service { /// Initializes a [Account] service Account(super.client); - /// Get account - /// /// Get the currently logged in user. Future<models.User> get() async { const String apiPath = '/account'; final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Create account - /// /// Use this endpoint to allow a new user to register a new account in your /// project. After the user registration completes successfully, you can use /// the @@ -32,11 +30,12 @@ class Account extends Service { /// route to start verifying the user email address. To allow the new user to /// login to their new account, you need to create a new [account /// session](https://appwrite.io/docs/references/cloud/client-web/account#createEmailSession). - Future<models.User> create( - {required String userId, - required String email, - required String password, - String? name}) async { + Future<models.User> create({ + required String userId, + required String email, + required String password, + String? name, + }) async { const String apiPath = '/account'; final Map<String, dynamic> apiParams = { @@ -46,18 +45,18 @@ class Account extends Service { 'name': name, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Update email - /// /// Update currently logged in user account email address. After changing user /// address, the user confirmation status will get reset. A new confirmation /// email is not sent automatically however you can use the send confirmation @@ -66,8 +65,10 @@ class Account extends Service { /// This endpoint can also be used to convert an anonymous account to a normal /// one, by passing an email address and a new password. /// - Future<models.User> updateEmail( - {required String email, required String password}) async { + Future<models.User> updateEmail({ + required String email, + required String password, + }) async { const String apiPath = '/account/email'; final Map<String, dynamic> apiParams = { @@ -75,57 +76,57 @@ class Account extends Service { 'password': password, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// List identities - /// /// Get the list of identities for the currently logged in user. Future<models.IdentityList> listIdentities({List<String>? queries}) async { const String apiPath = '/account/identities'; - final Map<String, dynamic> apiParams = { - 'queries': queries, - }; + final Map<String, dynamic> apiParams = {'queries': queries}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.IdentityList.fromMap(res.data); } - /// Delete identity - /// /// Delete an identity by its unique ID. Future deleteIdentity({required String identityId}) async { - final String apiPath = '/account/identities/{identityId}' - .replaceAll('{identityId}', identityId); + final String apiPath = '/account/identities/{identityId}'.replaceAll( + '{identityId}', + identityId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Create JWT - /// /// Use this endpoint to create a JSON Web Token. You can use the resulting JWT /// to authenticate on behalf of the current user when working with the /// Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes @@ -136,155 +137,159 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Jwt.fromMap(res.data); } - /// List logs - /// /// Get the list of latest security activity logs for the currently logged in /// user. Each log returns user IP address, location and date and time of log. Future<models.LogList> listLogs({List<String>? queries}) async { const String apiPath = '/account/logs'; - final Map<String, dynamic> apiParams = { - 'queries': queries, - }; + final Map<String, dynamic> apiParams = {'queries': queries}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.LogList.fromMap(res.data); } - /// Update MFA - /// /// Enable or disable MFA on an account. Future<models.User> updateMFA({required bool mfa}) async { const String apiPath = '/account/mfa'; - final Map<String, dynamic> apiParams = { - 'mfa': mfa, - }; + final Map<String, dynamic> apiParams = {'mfa': mfa}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Create authenticator - /// /// Add an authenticator app to be used as an MFA factor. Verify the /// authenticator using the [verify /// authenticator](/docs/references/cloud/client-web/account#updateMfaAuthenticator) /// method. - Future<models.MfaType> createMfaAuthenticator( - {required enums.AuthenticatorType type}) async { - final String apiPath = - '/account/mfa/authenticators/{type}'.replaceAll('{type}', type.value); + Future<models.MfaType> createMfaAuthenticator({ + required enums.AuthenticatorType type, + }) async { + final String apiPath = '/account/mfa/authenticators/{type}'.replaceAll( + '{type}', + type.value, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaType.fromMap(res.data); } - /// Verify authenticator - /// /// Verify an authenticator app after adding it using the [add /// authenticator](/docs/references/cloud/client-web/account#createMfaAuthenticator) /// method. - Future<models.User> updateMfaAuthenticator( - {required enums.AuthenticatorType type, required String otp}) async { - final String apiPath = - '/account/mfa/authenticators/{type}'.replaceAll('{type}', type.value); - - final Map<String, dynamic> apiParams = { - 'otp': otp, - }; - - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; - - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + Future<models.User> updateMfaAuthenticator({ + required enums.AuthenticatorType type, + required String otp, + }) async { + final String apiPath = '/account/mfa/authenticators/{type}'.replaceAll( + '{type}', + type.value, + ); + + final Map<String, dynamic> apiParams = {'otp': otp}; + + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Delete authenticator - /// /// Delete an authenticator for a user by ID. Future deleteMfaAuthenticator({required enums.AuthenticatorType type}) async { - final String apiPath = - '/account/mfa/authenticators/{type}'.replaceAll('{type}', type.value); + final String apiPath = '/account/mfa/authenticators/{type}'.replaceAll( + '{type}', + type.value, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Create MFA challenge - /// /// Begin the process of MFA verification after sign-in. Finish the flow with /// [updateMfaChallenge](/docs/references/cloud/client-web/account#updateMfaChallenge) /// method. - Future<models.MfaChallenge> createMfaChallenge( - {required enums.AuthenticationFactor factor}) async { + Future<models.MfaChallenge> createMfaChallenge({ + required enums.AuthenticationFactor factor, + }) async { const String apiPath = '/account/mfa/challenge'; - final Map<String, dynamic> apiParams = { - 'factor': factor.value, - }; + final Map<String, dynamic> apiParams = {'factor': factor.value}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaChallenge.fromMap(res.data); } - /// Create MFA challenge (confirmation) - /// /// Complete the MFA challenge by providing the one-time password. Finish the /// process of MFA verification by providing the one-time password. To begin /// the flow, use /// [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) /// method. - Future<models.Session> updateMfaChallenge( - {required String challengeId, required String otp}) async { + Future<models.Session> updateMfaChallenge({ + required String challengeId, + required String otp, + }) async { const String apiPath = '/account/mfa/challenge'; final Map<String, dynamic> apiParams = { @@ -292,36 +297,36 @@ class Account extends Service { 'otp': otp, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// List factors - /// /// List the factors available on the account to be used as a MFA challange. Future<models.MfaFactors> listMfaFactors() async { const String apiPath = '/account/mfa/factors'; final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaFactors.fromMap(res.data); } - /// Get MFA recovery codes - /// /// Get recovery codes that can be used as backup for MFA flow. Before getting /// codes, they must be generated using /// [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) @@ -331,18 +336,18 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaRecoveryCodes.fromMap(res.data); } - /// Create MFA recovery codes - /// /// Generate recovery codes as backup for MFA flow. It's recommended to /// generate and show then immediately after user successfully adds their /// authehticator. Recovery codes can be used as a MFA verification type in @@ -353,18 +358,18 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaRecoveryCodes.fromMap(res.data); } - /// Regenerate MFA recovery codes - /// /// Regenerate recovery codes that can be used as backup for MFA flow. Before /// regenerating codes, they must be first generated using /// [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) @@ -374,43 +379,43 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MfaRecoveryCodes.fromMap(res.data); } - /// Update name - /// /// Update currently logged in user account name. Future<models.User> updateName({required String name}) async { const String apiPath = '/account/name'; - final Map<String, dynamic> apiParams = { - 'name': name, - }; + final Map<String, dynamic> apiParams = {'name': name}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Update password - /// /// Update currently logged in user password. For validation, user is required /// to pass in the new password, and the old password. For users created with /// OAuth, Team Invites and Magic URL, oldPassword is optional. - Future<models.User> updatePassword( - {required String password, String? oldPassword}) async { + Future<models.User> updatePassword({ + required String password, + String? oldPassword, + }) async { const String apiPath = '/account/password'; final Map<String, dynamic> apiParams = { @@ -418,25 +423,27 @@ class Account extends Service { 'oldPassword': oldPassword, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Update phone - /// /// Update the currently logged in user's phone number. After updating the /// phone number, the phone verification status will be reset. A confirmation /// SMS is not sent automatically, however you can use the [POST /// /account/verification/phone](https://appwrite.io/docs/references/cloud/client-web/account#createPhoneVerification) /// endpoint to send a confirmation SMS. - Future<models.User> updatePhone( - {required String phone, required String password}) async { + Future<models.User> updatePhone({ + required String phone, + required String password, + }) async { const String apiPath = '/account/phone'; final Map<String, dynamic> apiParams = { @@ -444,58 +451,56 @@ class Account extends Service { 'password': password, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Get account preferences - /// /// Get the preferences as a key-value object for the currently logged in user. Future<models.Preferences> getPrefs() async { const String apiPath = '/account/prefs'; final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Preferences.fromMap(res.data); } - /// Update preferences - /// /// Update currently logged in user account preferences. The object you pass is /// stored as is, and replaces any previous value. The maximum allowed prefs /// size is 64kB and throws error if exceeded. Future<models.User> updatePrefs({required Map prefs}) async { const String apiPath = '/account/prefs'; - final Map<String, dynamic> apiParams = { - 'prefs': prefs, - }; + final Map<String, dynamic> apiParams = {'prefs': prefs}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Create password recovery - /// /// Sends the user an email with a temporary secret key for password reset. /// When the user clicks the confirmation link he is redirected back to your /// app password reset URL with the secret key and email address values @@ -504,27 +509,26 @@ class Account extends Service { /// /account/recovery](https://appwrite.io/docs/references/cloud/client-web/account#updateRecovery) /// endpoint to complete the process. The verification link sent to the user's /// email address is valid for 1 hour. - Future<models.Token> createRecovery( - {required String email, required String url}) async { + Future<models.Token> createRecovery({ + required String email, + required String url, + }) async { const String apiPath = '/account/recovery'; - final Map<String, dynamic> apiParams = { - 'email': email, - 'url': url, - }; + final Map<String, dynamic> apiParams = {'email': email, 'url': url}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create password recovery (confirmation) - /// /// Use this endpoint to complete the user account password reset. Both the /// **userId** and **secret** arguments will be passed as query parameters to /// the redirect URL you have provided when sending your request to the [POST @@ -535,10 +539,11 @@ class Account extends Service { /// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) /// the only valid redirect URLs are the ones from domains you have set when /// adding your platforms in the console interface. - Future<models.Token> updateRecovery( - {required String userId, - required String secret, - required String password}) async { + Future<models.Token> updateRecovery({ + required String userId, + required String secret, + required String password, + }) async { const String apiPath = '/account/recovery'; final Map<String, dynamic> apiParams = { @@ -547,18 +552,18 @@ class Account extends Service { 'password': password, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// List sessions - /// /// Get the list of active sessions across different devices for the currently /// logged in user. Future<models.SessionList> listSessions() async { @@ -566,18 +571,18 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.SessionList.fromMap(res.data); } - /// Delete sessions - /// /// Delete all sessions from the user account and remove any sessions cookies /// from the end client. Future deleteSessions() async { @@ -585,18 +590,18 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Create anonymous session - /// /// Use this endpoint to allow a new user to register an anonymous account in /// your project. This route will also create a new session for the user. To /// allow the new user to convert an anonymous account to a normal account, you @@ -609,26 +614,28 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Create email password session - /// /// Allow the user to login into their account by providing a valid email and /// password combination. This route will create a new session for the user. /// /// A user is limited to 10 active sessions at a time by default. [Learn more /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). - Future<models.Session> createEmailPasswordSession( - {required String email, required String password}) async { + Future<models.Session> createEmailPasswordSession({ + required String email, + required String password, + }) async { const String apiPath = '/account/sessions/email'; final Map<String, dynamic> apiParams = { @@ -636,42 +643,41 @@ class Account extends Service { 'password': password, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Update magic URL session - /// /// Use this endpoint to create a session from token. Provide the **userId** /// and **secret** parameters from the successful response of authentication /// flows initiated by token creation. For example, magic URL and phone login. - Future<models.Session> updateMagicURLSession( - {required String userId, required String secret}) async { + Future<models.Session> updateMagicURLSession({ + required String userId, + required String secret, + }) async { const String apiPath = '/account/sessions/magic-url'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Create OAuth2 session - /// /// Allow the user to login to their account using the OAuth2 provider of their /// choice. Each OAuth2 provider should be enabled from the Appwrite console /// first. Use the success and failure arguments to provide a redirect URL's @@ -688,18 +694,22 @@ class Account extends Service { /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). /// - Future createOAuth2Session( - {required enums.OAuthProvider provider, - String? success, - String? failure, - List<String>? scopes}) async { - final String apiPath = '/account/sessions/oauth2/{provider}' - .replaceAll('{provider}', provider.value); + Future createOAuth2Session({ + required enums.OAuthProvider provider, + String? success, + String? failure, + List<String>? scopes, + }) async { + final String apiPath = '/account/sessions/oauth2/{provider}'.replaceAll( + '{provider}', + provider.value, + ); final Map<String, dynamic> params = { 'success': success, 'failure': failure, 'scopes': scopes, + 'project': client.config['project'], }; @@ -708,9 +718,9 @@ class Account extends Service { params.forEach((key, value) { if (value is List) { for (var item in value) { - query.add(Uri.encodeComponent(key + '[]') + - '=' + - Uri.encodeComponent(item)); + query.add( + Uri.encodeComponent(key + '[]') + '=' + Uri.encodeComponent(item), + ); } } else if (value != null) { query.add(Uri.encodeComponent(key) + '=' + Uri.encodeComponent(value)); @@ -719,129 +729,132 @@ class Account extends Service { Uri endpoint = Uri.parse(client.endPoint); Uri url = Uri( - scheme: endpoint.scheme, - host: endpoint.host, - port: endpoint.port, - path: endpoint.path + apiPath, - query: query.join('&')); + scheme: endpoint.scheme, + host: endpoint.host, + port: endpoint.port, + path: endpoint.path + apiPath, + query: query.join('&'), + ); return client.webAuth(url, callbackUrlScheme: success); } - /// Update phone session - /// /// Use this endpoint to create a session from token. Provide the **userId** /// and **secret** parameters from the successful response of authentication /// flows initiated by token creation. For example, magic URL and phone login. - Future<models.Session> updatePhoneSession( - {required String userId, required String secret}) async { + Future<models.Session> updatePhoneSession({ + required String userId, + required String secret, + }) async { const String apiPath = '/account/sessions/phone'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Create session - /// /// Use this endpoint to create a session from token. Provide the **userId** /// and **secret** parameters from the successful response of authentication /// flows initiated by token creation. For example, magic URL and phone login. - Future<models.Session> createSession( - {required String userId, required String secret}) async { + Future<models.Session> createSession({ + required String userId, + required String secret, + }) async { const String apiPath = '/account/sessions/token'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Get session - /// /// Use this endpoint to get a logged in user's session using a Session ID. /// Inputting 'current' will return the current session being used. Future<models.Session> getSession({required String sessionId}) async { - final String apiPath = - '/account/sessions/{sessionId}'.replaceAll('{sessionId}', sessionId); + final String apiPath = '/account/sessions/{sessionId}'.replaceAll( + '{sessionId}', + sessionId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Update session - /// /// Use this endpoint to extend a session's length. Extending a session is /// useful when session expiry is short. If the session was created using an /// OAuth provider, this endpoint refreshes the access token from the provider. Future<models.Session> updateSession({required String sessionId}) async { - final String apiPath = - '/account/sessions/{sessionId}'.replaceAll('{sessionId}', sessionId); + final String apiPath = '/account/sessions/{sessionId}'.replaceAll( + '{sessionId}', + sessionId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Session.fromMap(res.data); } - /// Delete session - /// /// Logout the user. Use 'current' as the session ID to logout on this device, /// use a session ID to logout on another device. If you're looking to logout /// the user on all devices, use [Delete /// Sessions](https://appwrite.io/docs/references/cloud/client-web/account#deleteSessions) /// instead. Future deleteSession({required String sessionId}) async { - final String apiPath = - '/account/sessions/{sessionId}'.replaceAll('{sessionId}', sessionId); + final String apiPath = '/account/sessions/{sessionId}'.replaceAll( + '{sessionId}', + sessionId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Update status - /// /// Block the currently logged in user account. Behind the scene, the user /// record is not deleted but permanently blocked from any access. To /// completely delete a user, use the Users API instead. @@ -850,27 +863,28 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.User.fromMap(res.data); } - /// Create push target - /// /// Use this endpoint to register a device for push notifications. Provide a /// target ID (custom or generated using ID.unique()), a device identifier /// (usually a device token), and optionally specify which provider should send /// notifications to this target. The target is automatically linked to the /// current session and includes device information like brand and model. - Future<models.Target> createPushTarget( - {required String targetId, - required String identifier, - String? providerId}) async { + Future<models.Target> createPushTarget({ + required String targetId, + required String identifier, + String? providerId, + }) async { const String apiPath = '/account/targets/push'; final Map<String, dynamic> apiParams = { @@ -879,65 +893,69 @@ class Account extends Service { 'providerId': providerId, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Target.fromMap(res.data); } - /// Update push target - /// /// Update the currently logged in user's push notification target. You can /// modify the target's identifier (device token) and provider ID (token, /// email, phone etc.). The target must exist and belong to the current user. /// If you change the provider ID, notifications will be sent through the new /// messaging provider instead. - Future<models.Target> updatePushTarget( - {required String targetId, required String identifier}) async { - final String apiPath = - '/account/targets/{targetId}/push'.replaceAll('{targetId}', targetId); - - final Map<String, dynamic> apiParams = { - 'identifier': identifier, - }; - - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; - - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + Future<models.Target> updatePushTarget({ + required String targetId, + required String identifier, + }) async { + final String apiPath = '/account/targets/{targetId}/push'.replaceAll( + '{targetId}', + targetId, + ); + + final Map<String, dynamic> apiParams = {'identifier': identifier}; + + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Target.fromMap(res.data); } - /// Delete push target - /// /// Delete a push notification target for the currently logged in user. After /// deletion, the device will no longer receive push notifications. The target /// must exist and belong to the current user. Future deletePushTarget({required String targetId}) async { - final String apiPath = - '/account/targets/{targetId}/push'.replaceAll('{targetId}', targetId); + final String apiPath = '/account/targets/{targetId}/push'.replaceAll( + '{targetId}', + targetId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Create email token (OTP) - /// /// Sends the user an email with a secret key for creating a session. If the /// provided user ID has not be registered, a new user will be created. Use the /// returned user ID and secret and submit a request to the [POST @@ -948,8 +966,11 @@ class Account extends Service { /// A user is limited to 10 active sessions at a time by default. [Learn more /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). - Future<models.Token> createEmailToken( - {required String userId, required String email, bool? phrase}) async { + Future<models.Token> createEmailToken({ + required String userId, + required String email, + bool? phrase, + }) async { const String apiPath = '/account/tokens/email'; final Map<String, dynamic> apiParams = { @@ -958,18 +979,18 @@ class Account extends Service { 'phrase': phrase, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create magic URL token - /// /// Sends the user an email with a secret key for creating a session. If the /// provided user ID has not been registered, a new user will be created. When /// the user clicks the link in the email, the user is redirected back to the @@ -984,11 +1005,12 @@ class Account extends Service { /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). /// - Future<models.Token> createMagicURLToken( - {required String userId, - required String email, - String? url, - bool? phrase}) async { + Future<models.Token> createMagicURLToken({ + required String userId, + required String email, + String? url, + bool? phrase, + }) async { const String apiPath = '/account/tokens/magic-url'; final Map<String, dynamic> apiParams = { @@ -998,18 +1020,18 @@ class Account extends Service { 'phrase': phrase, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create OAuth2 token - /// /// Allow the user to login to their account using the OAuth2 provider of their /// choice. Each OAuth2 provider should be enabled from the Appwrite console /// first. Use the success and failure arguments to provide a redirect URL's @@ -1024,18 +1046,22 @@ class Account extends Service { /// A user is limited to 10 active sessions at a time by default. [Learn more /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). - Future createOAuth2Token( - {required enums.OAuthProvider provider, - String? success, - String? failure, - List<String>? scopes}) async { - final String apiPath = '/account/tokens/oauth2/{provider}' - .replaceAll('{provider}', provider.value); + Future createOAuth2Token({ + required enums.OAuthProvider provider, + String? success, + String? failure, + List<String>? scopes, + }) async { + final String apiPath = '/account/tokens/oauth2/{provider}'.replaceAll( + '{provider}', + provider.value, + ); final Map<String, dynamic> params = { 'success': success, 'failure': failure, 'scopes': scopes, + 'project': client.config['project'], }; @@ -1044,9 +1070,9 @@ class Account extends Service { params.forEach((key, value) { if (value is List) { for (var item in value) { - query.add(Uri.encodeComponent(key + '[]') + - '=' + - Uri.encodeComponent(item)); + query.add( + Uri.encodeComponent(key + '[]') + '=' + Uri.encodeComponent(item), + ); } } else if (value != null) { query.add(Uri.encodeComponent(key) + '=' + Uri.encodeComponent(value)); @@ -1055,17 +1081,16 @@ class Account extends Service { Uri endpoint = Uri.parse(client.endPoint); Uri url = Uri( - scheme: endpoint.scheme, - host: endpoint.host, - port: endpoint.port, - path: endpoint.path + apiPath, - query: query.join('&')); + scheme: endpoint.scheme, + host: endpoint.host, + port: endpoint.port, + path: endpoint.path + apiPath, + query: query.join('&'), + ); return client.webAuth(url, callbackUrlScheme: success); } - /// Create phone token - /// /// Sends the user an SMS with a secret key for creating a session. If the /// provided user ID has not be registered, a new user will be created. Use the /// returned user ID and secret and submit a request to the [POST @@ -1076,27 +1101,26 @@ class Account extends Service { /// A user is limited to 10 active sessions at a time by default. [Learn more /// about session /// limits](https://appwrite.io/docs/authentication-security#limits). - Future<models.Token> createPhoneToken( - {required String userId, required String phone}) async { + Future<models.Token> createPhoneToken({ + required String userId, + required String phone, + }) async { const String apiPath = '/account/tokens/phone'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'phone': phone, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'phone': phone}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create email verification - /// /// Use this endpoint to send a verification message to your user email address /// to confirm they are the valid owners of that address. Both the **userId** /// and **secret** arguments will be passed as query parameters to the URL you @@ -1115,47 +1139,44 @@ class Account extends Service { Future<models.Token> createVerification({required String url}) async { const String apiPath = '/account/verification'; - final Map<String, dynamic> apiParams = { - 'url': url, - }; + final Map<String, dynamic> apiParams = {'url': url}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create email verification (confirmation) - /// /// Use this endpoint to complete the user email verification process. Use both /// the **userId** and **secret** parameters that were attached to your app URL /// to verify the user email ownership. If confirmed this route will return a /// 200 status code. - Future<models.Token> updateVerification( - {required String userId, required String secret}) async { + Future<models.Token> updateVerification({ + required String userId, + required String secret, + }) async { const String apiPath = '/account/verification'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Create phone verification - /// /// Use this endpoint to send a verification SMS to the currently logged in /// user. This endpoint is meant for use after updating a user's phone number /// using the @@ -1169,37 +1190,38 @@ class Account extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } - /// Update phone verification (confirmation) - /// /// Use this endpoint to complete the user phone verification process. Use the /// **userId** and **secret** that were sent to your user's phone number to /// verify the user email ownership. If confirmed this route will return a 200 /// status code. - Future<models.Token> updatePhoneVerification( - {required String userId, required String secret}) async { + Future<models.Token> updatePhoneVerification({ + required String userId, + required String secret, + }) async { const String apiPath = '/account/verification/phone'; - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Token.fromMap(res.data); } diff --git a/lib/services/avatars.dart b/lib/services/avatars.dart index 3bc203e..a02b2db 100644 --- a/lib/services/avatars.dart +++ b/lib/services/avatars.dart @@ -6,8 +6,6 @@ class Avatars extends Service { /// Initializes a [Avatars] service Avatars(super.client); - /// Get browser icon - /// /// You can use this endpoint to show different browser icons to your users. /// The code argument receives the browser code as it appears in your user [GET /// /account/sessions](https://appwrite.io/docs/references/cloud/client-web/account#getSessions) @@ -18,28 +16,34 @@ class Avatars extends Service { /// with preserved aspect ratio. If both dimensions are 0, the API provides an /// image at source quality. If dimensions are not specified, the default size /// of image returned is 100x100px. - Future<Uint8List> getBrowser( - {required enums.Browser code, - int? width, - int? height, - int? quality}) async { - final String apiPath = - '/avatars/browsers/{code}'.replaceAll('{code}', code.value); + Future<Uint8List> getBrowser({ + required enums.Browser code, + int? width, + int? height, + int? quality, + }) async { + final String apiPath = '/avatars/browsers/{code}'.replaceAll( + '{code}', + code.value, + ); final Map<String, dynamic> params = { 'width': width, 'height': height, 'quality': quality, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get credit card icon - /// /// The credit card endpoint will return you the icon of the credit card /// provider you need. Use width, height and quality arguments to change the /// output settings. @@ -49,28 +53,34 @@ class Avatars extends Service { /// image at source quality. If dimensions are not specified, the default size /// of image returned is 100x100px. /// - Future<Uint8List> getCreditCard( - {required enums.CreditCard code, - int? width, - int? height, - int? quality}) async { - final String apiPath = - '/avatars/credit-cards/{code}'.replaceAll('{code}', code.value); + Future<Uint8List> getCreditCard({ + required enums.CreditCard code, + int? width, + int? height, + int? quality, + }) async { + final String apiPath = '/avatars/credit-cards/{code}'.replaceAll( + '{code}', + code.value, + ); final Map<String, dynamic> params = { 'width': width, 'height': height, 'quality': quality, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get favicon - /// /// Use this endpoint to fetch the favorite icon (AKA favicon) of any remote /// website URL. /// @@ -80,16 +90,19 @@ class Avatars extends Service { final Map<String, dynamic> params = { 'url': url, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get country flag - /// /// You can use this endpoint to show different country flags icons to your /// users. The code argument receives the 2 letter country code. Use width, /// height and quality arguments to change the output settings. Country codes @@ -100,25 +113,34 @@ class Avatars extends Service { /// image at source quality. If dimensions are not specified, the default size /// of image returned is 100x100px. /// - Future<Uint8List> getFlag( - {required enums.Flag code, int? width, int? height, int? quality}) async { - final String apiPath = - '/avatars/flags/{code}'.replaceAll('{code}', code.value); + Future<Uint8List> getFlag({ + required enums.Flag code, + int? width, + int? height, + int? quality, + }) async { + final String apiPath = '/avatars/flags/{code}'.replaceAll( + '{code}', + code.value, + ); final Map<String, dynamic> params = { 'width': width, 'height': height, 'quality': quality, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get image from URL - /// /// Use this endpoint to fetch a remote image URL and crop it to any image size /// you want. This endpoint is very useful if you need to crop and display /// remote images in your app or in case you want to make sure a 3rd party @@ -130,24 +152,30 @@ class Avatars extends Service { /// of image returned is 400x400px. /// /// This endpoint does not follow HTTP redirects. - Future<Uint8List> getImage( - {required String url, int? width, int? height}) async { + Future<Uint8List> getImage({ + required String url, + int? width, + int? height, + }) async { const String apiPath = '/avatars/image'; final Map<String, dynamic> params = { 'url': url, 'width': width, 'height': height, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get user initials - /// /// Use this endpoint to show your user initials avatar icon on your website or /// app. By default, this route will try to print your logged-in user name or /// email initials. You can also overwrite the user name if you pass the 'name' @@ -164,8 +192,12 @@ class Avatars extends Service { /// image at source quality. If dimensions are not specified, the default size /// of image returned is 100x100px. /// - Future<Uint8List> getInitials( - {String? name, int? width, int? height, String? background}) async { + Future<Uint8List> getInitials({ + String? name, + int? width, + int? height, + String? background, + }) async { const String apiPath = '/avatars/initials'; final Map<String, dynamic> params = { @@ -173,21 +205,28 @@ class Avatars extends Service { 'width': width, 'height': height, 'background': background, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get QR code - /// /// Converts a given plain text to a QR code image. You can use the query /// parameters to change the size and style of the resulting image. /// - Future<Uint8List> getQR( - {required String text, int? size, int? margin, bool? download}) async { + Future<Uint8List> getQR({ + required String text, + int? size, + int? margin, + bool? download, + }) async { const String apiPath = '/avatars/qr'; final Map<String, dynamic> params = { @@ -195,11 +234,16 @@ class Avatars extends Service { 'size': size, 'margin': margin, 'download': download, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } } diff --git a/lib/services/databases.dart b/lib/services/databases.dart index 36f4a1d..5eaf1eb 100644 --- a/lib/services/databases.dart +++ b/lib/services/databases.dart @@ -6,45 +6,43 @@ class Databases extends Service { /// Initializes a [Databases] service Databases(super.client); - /// List documents - /// /// Get a list of all the user's documents in a given collection. You can use /// the query params to filter your results. - Future<models.DocumentList> listDocuments( - {required String databaseId, - required String collectionId, - List<String>? queries}) async { + Future<models.DocumentList> listDocuments({ + required String databaseId, + required String collectionId, + List<String>? queries, + }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents' .replaceAll('{databaseId}', databaseId) .replaceAll('{collectionId}', collectionId); - final Map<String, dynamic> apiParams = { - 'queries': queries, - }; + final Map<String, dynamic> apiParams = {'queries': queries}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.DocumentList.fromMap(res.data); } - /// Create document - /// /// Create a new Document. Before using this route, you should create a new /// collection resource using either a [server /// integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) /// API or directly from your database console. - Future<models.Document> createDocument( - {required String databaseId, - required String collectionId, - required String documentId, - required Map data, - List<String>? permissions}) async { + Future<models.Document> createDocument({ + required String databaseId, + required String collectionId, + required String documentId, + required Map data, + List<String>? permissions, + }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents' .replaceAll('{databaseId}', databaseId) @@ -56,55 +54,55 @@ class Databases extends Service { 'permissions': permissions, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Document.fromMap(res.data); } - /// Get document - /// /// Get a document by its unique ID. This endpoint response returns a JSON /// object with the document data. - Future<models.Document> getDocument( - {required String databaseId, - required String collectionId, - required String documentId, - List<String>? queries}) async { + Future<models.Document> getDocument({ + required String databaseId, + required String collectionId, + required String documentId, + List<String>? queries, + }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' .replaceAll('{databaseId}', databaseId) .replaceAll('{collectionId}', collectionId) .replaceAll('{documentId}', documentId); - final Map<String, dynamic> apiParams = { - 'queries': queries, - }; + final Map<String, dynamic> apiParams = {'queries': queries}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Document.fromMap(res.data); } - /// Update document - /// /// Update a document by its unique ID. Using the patch method you can pass /// only specific fields that will get updated. - Future<models.Document> updateDocument( - {required String databaseId, - required String collectionId, - required String documentId, - Map? data, - List<String>? permissions}) async { + Future<models.Document> updateDocument({ + required String databaseId, + required String collectionId, + required String documentId, + Map? data, + List<String>? permissions, + }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' .replaceAll('{databaseId}', databaseId) @@ -116,23 +114,24 @@ class Databases extends Service { 'permissions': permissions, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Document.fromMap(res.data); } - /// Delete document - /// /// Delete a document by its unique ID. - Future deleteDocument( - {required String databaseId, - required String collectionId, - required String documentId}) async { + Future deleteDocument({ + required String databaseId, + required String collectionId, + required String documentId, + }) async { final String apiPath = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' .replaceAll('{databaseId}', databaseId) @@ -141,12 +140,14 @@ class Databases extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } diff --git a/lib/services/functions.dart b/lib/services/functions.dart index c78d629..f13323a 100644 --- a/lib/services/functions.dart +++ b/lib/services/functions.dart @@ -6,48 +6,52 @@ class Functions extends Service { /// Initializes a [Functions] service Functions(super.client); - /// List executions - /// /// Get a list of all the current user function execution logs. You can use the /// query params to filter your results. - Future<models.ExecutionList> listExecutions( - {required String functionId, - List<String>? queries, - String? search}) async { - final String apiPath = '/functions/{functionId}/executions' - .replaceAll('{functionId}', functionId); + Future<models.ExecutionList> listExecutions({ + required String functionId, + List<String>? queries, + String? search, + }) async { + final String apiPath = '/functions/{functionId}/executions'.replaceAll( + '{functionId}', + functionId, + ); final Map<String, dynamic> apiParams = { 'queries': queries, 'search': search, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.ExecutionList.fromMap(res.data); } - /// Create execution - /// /// Trigger a function execution. The returned object will return you the /// current execution status. You can ping the `Get Execution` endpoint to get /// updates on the current execution status. Once this endpoint is called, your /// function execution process will start asynchronously. - Future<models.Execution> createExecution( - {required String functionId, - String? body, - bool? xasync, - String? path, - enums.ExecutionMethod? method, - Map? headers, - String? scheduledAt}) async { - final String apiPath = '/functions/{functionId}/executions' - .replaceAll('{functionId}', functionId); + Future<models.Execution> createExecution({ + required String functionId, + String? body, + bool? xasync, + String? path, + enums.ExecutionMethod? method, + Map? headers, + String? scheduledAt, + }) async { + final String apiPath = '/functions/{functionId}/executions'.replaceAll( + '{functionId}', + functionId, + ); final Map<String, dynamic> apiParams = { 'body': body, @@ -58,33 +62,37 @@ class Functions extends Service { 'scheduledAt': scheduledAt, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Execution.fromMap(res.data); } - /// Get execution - /// /// Get a function execution log by its unique ID. - Future<models.Execution> getExecution( - {required String functionId, required String executionId}) async { + Future<models.Execution> getExecution({ + required String functionId, + required String executionId, + }) async { final String apiPath = '/functions/{functionId}/executions/{executionId}' .replaceAll('{functionId}', functionId) .replaceAll('{executionId}', executionId); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Execution.fromMap(res.data); } diff --git a/lib/services/graphql.dart b/lib/services/graphql.dart index f653df6..32ea107 100644 --- a/lib/services/graphql.dart +++ b/lib/services/graphql.dart @@ -6,44 +6,44 @@ class Graphql extends Service { /// Initializes a [Graphql] service Graphql(super.client); - /// GraphQL endpoint - /// /// Execute a GraphQL mutation. Future query({required Map query}) async { const String apiPath = '/graphql'; - final Map<String, dynamic> apiParams = { - 'query': query, - }; + final Map<String, dynamic> apiParams = {'query': query}; final Map<String, String> apiHeaders = { 'x-sdk-graphql': 'true', 'content-type': 'application/json', }; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// GraphQL endpoint - /// /// Execute a GraphQL mutation. Future mutation({required Map query}) async { const String apiPath = '/graphql/mutation'; - final Map<String, dynamic> apiParams = { - 'query': query, - }; + final Map<String, dynamic> apiParams = {'query': query}; final Map<String, String> apiHeaders = { 'x-sdk-graphql': 'true', 'content-type': 'application/json', }; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } diff --git a/lib/services/locale.dart b/lib/services/locale.dart index 5779b36..8b746d5 100644 --- a/lib/services/locale.dart +++ b/lib/services/locale.dart @@ -6,8 +6,6 @@ class Locale extends Service { /// Initializes a [Locale] service Locale(super.client); - /// Get user locale - /// /// Get the current user location based on IP. Returns an object with user /// country code, country name, continent name, continent code, ip address and /// suggested currency. You can use the locale header to get the data in a @@ -19,18 +17,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Locale.fromMap(res.data); } - /// List locale codes - /// /// List of all locale codes in [ISO /// 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Future<models.LocaleCodeList> listCodes() async { @@ -38,18 +36,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.LocaleCodeList.fromMap(res.data); } - /// List continents - /// /// List of all continents. You can use the locale header to get the data in a /// supported language. Future<models.ContinentList> listContinents() async { @@ -57,18 +55,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.ContinentList.fromMap(res.data); } - /// List countries - /// /// List of all countries. You can use the locale header to get the data in a /// supported language. Future<models.CountryList> listCountries() async { @@ -76,18 +74,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.CountryList.fromMap(res.data); } - /// List EU countries - /// /// List of all countries that are currently members of the EU. You can use the /// locale header to get the data in a supported language. Future<models.CountryList> listCountriesEU() async { @@ -95,18 +93,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.CountryList.fromMap(res.data); } - /// List countries phone codes - /// /// List of all countries phone codes. You can use the locale header to get the /// data in a supported language. Future<models.PhoneList> listCountriesPhones() async { @@ -114,18 +112,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.PhoneList.fromMap(res.data); } - /// List currencies - /// /// List of all currencies, including currency symbol, name, plural, and /// decimal digits for all major and minor currencies. You can use the locale /// header to get the data in a supported language. @@ -134,18 +132,18 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.CurrencyList.fromMap(res.data); } - /// List languages - /// /// List of all languages classified by ISO 639-1 including 2-letter code, name /// in English, and name in the respective language. Future<models.LanguageList> listLanguages() async { @@ -153,12 +151,14 @@ class Locale extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.LanguageList.fromMap(res.data); } diff --git a/lib/services/messaging.dart b/lib/services/messaging.dart index 75a6630..236037f 100644 --- a/lib/services/messaging.dart +++ b/lib/services/messaging.dart @@ -6,36 +6,39 @@ class Messaging extends Service { /// Initializes a [Messaging] service Messaging(super.client); - /// Create subscriber - /// /// Create a new subscriber. - Future<models.Subscriber> createSubscriber( - {required String topicId, - required String subscriberId, - required String targetId}) async { - final String apiPath = '/messaging/topics/{topicId}/subscribers' - .replaceAll('{topicId}', topicId); + Future<models.Subscriber> createSubscriber({ + required String topicId, + required String subscriberId, + required String targetId, + }) async { + final String apiPath = '/messaging/topics/{topicId}/subscribers'.replaceAll( + '{topicId}', + topicId, + ); final Map<String, dynamic> apiParams = { 'subscriberId': subscriberId, 'targetId': targetId, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Subscriber.fromMap(res.data); } - /// Delete subscriber - /// /// Delete a subscriber by its unique ID. - Future deleteSubscriber( - {required String topicId, required String subscriberId}) async { + Future deleteSubscriber({ + required String topicId, + required String subscriberId, + }) async { final String apiPath = '/messaging/topics/{topicId}/subscribers/{subscriberId}' .replaceAll('{topicId}', topicId) @@ -43,12 +46,14 @@ class Messaging extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } diff --git a/lib/services/storage.dart b/lib/services/storage.dart index 082b5d4..9f70e55 100644 --- a/lib/services/storage.dart +++ b/lib/services/storage.dart @@ -5,32 +5,35 @@ class Storage extends Service { /// Initializes a [Storage] service Storage(super.client); - /// List files - /// /// Get a list of all the user files. You can use the query params to filter /// your results. - Future<models.FileList> listFiles( - {required String bucketId, List<String>? queries, String? search}) async { - final String apiPath = - '/storage/buckets/{bucketId}/files'.replaceAll('{bucketId}', bucketId); + Future<models.FileList> listFiles({ + required String bucketId, + List<String>? queries, + String? search, + }) async { + final String apiPath = '/storage/buckets/{bucketId}/files'.replaceAll( + '{bucketId}', + bucketId, + ); final Map<String, dynamic> apiParams = { 'queries': queries, 'search': search, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.FileList.fromMap(res.data); } - /// Create file - /// /// Create a new file. Before using this route, you should create a new bucket /// resource using either a [server /// integration](https://appwrite.io/docs/server/storage#storageCreateBucket) @@ -49,14 +52,17 @@ class Storage extends Service { /// If you're creating a new file using one of the Appwrite SDKs, all the /// chunking logic will be managed by the SDK internally. /// - Future<models.File> createFile( - {required String bucketId, - required String fileId, - required InputFile file, - List<String>? permissions, - Function(UploadProgress)? onProgress}) async { - final String apiPath = - '/storage/buckets/{bucketId}/files'.replaceAll('{bucketId}', bucketId); + Future<models.File> createFile({ + required String bucketId, + required String fileId, + required InputFile file, + List<String>? permissions, + Function(UploadProgress)? onProgress, + }) async { + final String apiPath = '/storage/buckets/{bucketId}/files'.replaceAll( + '{bucketId}', + bucketId, + ); final Map<String, dynamic> apiParams = { 'fileId': fileId, @@ -83,37 +89,38 @@ class Storage extends Service { return models.File.fromMap(res.data); } - /// Get file - /// /// Get a file by its unique ID. This endpoint response returns a JSON object /// with the file metadata. - Future<models.File> getFile( - {required String bucketId, required String fileId}) async { + Future<models.File> getFile({ + required String bucketId, + required String fileId, + }) async { final String apiPath = '/storage/buckets/{bucketId}/files/{fileId}' .replaceAll('{bucketId}', bucketId) .replaceAll('{fileId}', fileId); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.File.fromMap(res.data); } - /// Update file - /// /// Update a file by its unique ID. Only users with write permissions have /// access to update this resource. - Future<models.File> updateFile( - {required String bucketId, - required String fileId, - String? name, - List<String>? permissions}) async { + Future<models.File> updateFile({ + required String bucketId, + required String fileId, + String? name, + List<String>? permissions, + }) async { final String apiPath = '/storage/buckets/{bucketId}/files/{fileId}' .replaceAll('{bucketId}', bucketId) .replaceAll('{fileId}', fileId); @@ -123,18 +130,18 @@ class Storage extends Service { 'permissions': permissions, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.File.fromMap(res.data); } - /// Delete file - /// /// Delete a file by its unique ID. Only users with write permissions have /// access to delete this resource. Future deleteFile({required String bucketId, required String fileId}) async { @@ -144,57 +151,60 @@ class Storage extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Get file for download - /// /// Get a file content by its unique ID. The endpoint response return with a /// 'Content-Disposition: attachment' header that tells the browser to start /// downloading the file to user downloads directory. - Future<Uint8List> getFileDownload( - {required String bucketId, required String fileId}) async { + Future<Uint8List> getFileDownload({ + required String bucketId, + required String fileId, + }) async { final String apiPath = '/storage/buckets/{bucketId}/files/{fileId}/download' .replaceAll('{bucketId}', bucketId) .replaceAll('{fileId}', fileId); - final Map<String, dynamic> params = { - 'project': client.config['project'], - }; + final Map<String, dynamic> params = {'project': client.config['project']}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get file preview - /// /// Get a file preview image. Currently, this method supports preview for image /// files (jpg, png, and gif), other supported formats, like pdf, docs, slides, /// and spreadsheets, will return the file icon image. You can also pass query /// string arguments for cutting and resizing your preview image. Preview is /// supported only for image files smaller than 10MB. - Future<Uint8List> getFilePreview( - {required String bucketId, - required String fileId, - int? width, - int? height, - enums.ImageGravity? gravity, - int? quality, - int? borderWidth, - String? borderColor, - int? borderRadius, - double? opacity, - int? rotation, - String? background, - enums.ImageFormat? output}) async { + Future<Uint8List> getFilePreview({ + required String bucketId, + required String fileId, + int? width, + int? height, + enums.ImageGravity? gravity, + int? quality, + int? borderWidth, + String? borderColor, + int? borderRadius, + double? opacity, + int? rotation, + String? background, + enums.ImageFormat? output, + }) async { final String apiPath = '/storage/buckets/{bucketId}/files/{fileId}/preview' .replaceAll('{bucketId}', bucketId) .replaceAll('{fileId}', fileId); @@ -211,31 +221,38 @@ class Storage extends Service { 'rotation': rotation, 'background': background, 'output': output?.value, + 'project': client.config['project'], }; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } - /// Get file for view - /// /// Get a file content by its unique ID. This endpoint is similar to the /// download method but returns with no 'Content-Disposition: attachment' /// header. - Future<Uint8List> getFileView( - {required String bucketId, required String fileId}) async { + Future<Uint8List> getFileView({ + required String bucketId, + required String fileId, + }) async { final String apiPath = '/storage/buckets/{bucketId}/files/{fileId}/view' .replaceAll('{bucketId}', bucketId) .replaceAll('{fileId}', fileId); - final Map<String, dynamic> params = { - 'project': client.config['project'], - }; + final Map<String, dynamic> params = {'project': client.config['project']}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: params, responseType: ResponseType.bytes); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: params, + responseType: ResponseType.bytes, + ); return res.data; } } diff --git a/lib/services/teams.dart b/lib/services/teams.dart index ea04312..b8a7c30 100644 --- a/lib/services/teams.dart +++ b/lib/services/teams.dart @@ -6,8 +6,6 @@ class Teams extends Service { /// Initializes a [Teams] service Teams(super.client); - /// List teams - /// /// Get a list of all the teams in which the current user is a member. You can /// use the parameters to filter your results. Future<models.TeamList> list({List<String>? queries, String? search}) async { @@ -18,25 +16,26 @@ class Teams extends Service { 'search': search, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.TeamList.fromMap(res.data); } - /// Create team - /// /// Create a new team. The user who creates the team will automatically be /// assigned as the owner of the team. Only the users with the owner role can /// invite new members, add new owners and delete or update the team. - Future<models.Team> create( - {required String teamId, - required String name, - List<String>? roles}) async { + Future<models.Team> create({ + required String teamId, + required String name, + List<String>? roles, + }) async { const String apiPath = '/teams'; final Map<String, dynamic> apiParams = { @@ -45,57 +44,57 @@ class Teams extends Service { 'roles': roles, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Team.fromMap(res.data); } - /// Get team - /// /// Get a team by its ID. All team members have read access for this resource. Future<models.Team> get({required String teamId}) async { final String apiPath = '/teams/{teamId}'.replaceAll('{teamId}', teamId); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Team.fromMap(res.data); } - /// Update name - /// /// Update the team's name by its unique ID. - Future<models.Team> updateName( - {required String teamId, required String name}) async { + Future<models.Team> updateName({ + required String teamId, + required String name, + }) async { final String apiPath = '/teams/{teamId}'.replaceAll('{teamId}', teamId); - final Map<String, dynamic> apiParams = { - 'name': name, - }; + final Map<String, dynamic> apiParams = {'name': name}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Team.fromMap(res.data); } - /// Delete team - /// /// Delete a team using its ID. Only team members with the owner role can /// delete the team. Future delete({required String teamId}) async { @@ -103,43 +102,48 @@ class Teams extends Service { final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// List team memberships - /// /// Use this endpoint to list a team's members using the team's ID. All team /// members have read access to this endpoint. Hide sensitive attributes from /// the response by toggling membership privacy in the Console. - Future<models.MembershipList> listMemberships( - {required String teamId, List<String>? queries, String? search}) async { - final String apiPath = - '/teams/{teamId}/memberships'.replaceAll('{teamId}', teamId); + Future<models.MembershipList> listMemberships({ + required String teamId, + List<String>? queries, + String? search, + }) async { + final String apiPath = '/teams/{teamId}/memberships'.replaceAll( + '{teamId}', + teamId, + ); final Map<String, dynamic> apiParams = { 'queries': queries, 'search': search, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.MembershipList.fromMap(res.data); } - /// Create team membership - /// /// Invite a new member to join your team. Provide an ID for existing users, or /// invite unregistered users using an email or phone number. If initiated from /// a Client SDK, Appwrite will send an email or sms with a link to join the @@ -161,16 +165,19 @@ class Teams extends Service { /// Appwrite will accept the only redirect URLs under the domains you have /// added as a platform on the Appwrite Console. /// - Future<models.Membership> createMembership( - {required String teamId, - required List<String> roles, - String? email, - String? userId, - String? phone, - String? url, - String? name}) async { - final String apiPath = - '/teams/{teamId}/memberships'.replaceAll('{teamId}', teamId); + Future<models.Membership> createMembership({ + required String teamId, + required List<String> roles, + String? email, + String? userId, + String? phone, + String? url, + String? name, + }) async { + final String apiPath = '/teams/{teamId}/memberships'.replaceAll( + '{teamId}', + teamId, + ); final Map<String, dynamic> apiParams = { 'email': email, @@ -181,92 +188,95 @@ class Teams extends Service { 'name': name, }; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.post, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.post, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Membership.fromMap(res.data); } - /// Get team membership - /// /// Get a team member by the membership unique id. All team members have read /// access for this resource. Hide sensitive attributes from the response by /// toggling membership privacy in the Console. - Future<models.Membership> getMembership( - {required String teamId, required String membershipId}) async { + Future<models.Membership> getMembership({ + required String teamId, + required String membershipId, + }) async { final String apiPath = '/teams/{teamId}/memberships/{membershipId}' .replaceAll('{teamId}', teamId) .replaceAll('{membershipId}', membershipId); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Membership.fromMap(res.data); } - /// Update membership - /// /// Modify the roles of a team member. Only team members with the owner role /// have access to this endpoint. Learn more about [roles and /// permissions](https://appwrite.io/docs/permissions). /// - Future<models.Membership> updateMembership( - {required String teamId, - required String membershipId, - required List<String> roles}) async { + Future<models.Membership> updateMembership({ + required String teamId, + required String membershipId, + required List<String> roles, + }) async { final String apiPath = '/teams/{teamId}/memberships/{membershipId}' .replaceAll('{teamId}', teamId) .replaceAll('{membershipId}', membershipId); - final Map<String, dynamic> apiParams = { - 'roles': roles, - }; + final Map<String, dynamic> apiParams = {'roles': roles}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Membership.fromMap(res.data); } - /// Delete team membership - /// /// This endpoint allows a user to leave a team or for a team owner to delete /// the membership of any other team member. You can also use this endpoint to /// delete a user membership even if it is not accepted. - Future deleteMembership( - {required String teamId, required String membershipId}) async { + Future deleteMembership({ + required String teamId, + required String membershipId, + }) async { final String apiPath = '/teams/{teamId}/memberships/{membershipId}' .replaceAll('{teamId}', teamId) .replaceAll('{membershipId}', membershipId); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.delete, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.delete, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return res.data; } - /// Update team membership status - /// /// Use this endpoint to allow a user to accept an invitation to join a team /// after being redirected back to your app from the invitation email received /// by the user. @@ -274,71 +284,75 @@ class Teams extends Service { /// If the request is successful, a session for the user is automatically /// created. /// - Future<models.Membership> updateMembershipStatus( - {required String teamId, - required String membershipId, - required String userId, - required String secret}) async { + Future<models.Membership> updateMembershipStatus({ + required String teamId, + required String membershipId, + required String userId, + required String secret, + }) async { final String apiPath = '/teams/{teamId}/memberships/{membershipId}/status' .replaceAll('{teamId}', teamId) .replaceAll('{membershipId}', membershipId); - final Map<String, dynamic> apiParams = { - 'userId': userId, - 'secret': secret, - }; + final Map<String, dynamic> apiParams = {'userId': userId, 'secret': secret}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.patch, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.patch, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Membership.fromMap(res.data); } - /// Get team preferences - /// /// Get the team's shared preferences by its unique ID. If a preference doesn't /// need to be shared by all team members, prefer storing them in [user /// preferences](https://appwrite.io/docs/references/cloud/client-web/account#getPrefs). Future<models.Preferences> getPrefs({required String teamId}) async { - final String apiPath = - '/teams/{teamId}/prefs'.replaceAll('{teamId}', teamId); + final String apiPath = '/teams/{teamId}/prefs'.replaceAll( + '{teamId}', + teamId, + ); final Map<String, dynamic> apiParams = {}; - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; - final res = await client.call(HttpMethod.get, - path: apiPath, params: apiParams, headers: apiHeaders); + final res = await client.call( + HttpMethod.get, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Preferences.fromMap(res.data); } - /// Update preferences - /// /// Update the team's preferences by its unique ID. The object you pass is /// stored as is and replaces any previous value. The maximum allowed prefs /// size is 64kB and throws an error if exceeded. - Future<models.Preferences> updatePrefs( - {required String teamId, required Map prefs}) async { - final String apiPath = - '/teams/{teamId}/prefs'.replaceAll('{teamId}', teamId); - - final Map<String, dynamic> apiParams = { - 'prefs': prefs, - }; - - final Map<String, String> apiHeaders = { - 'content-type': 'application/json', - }; - - final res = await client.call(HttpMethod.put, - path: apiPath, params: apiParams, headers: apiHeaders); + Future<models.Preferences> updatePrefs({ + required String teamId, + required Map prefs, + }) async { + final String apiPath = '/teams/{teamId}/prefs'.replaceAll( + '{teamId}', + teamId, + ); + + final Map<String, dynamic> apiParams = {'prefs': prefs}; + + final Map<String, String> apiHeaders = {'content-type': 'application/json'}; + + final res = await client.call( + HttpMethod.put, + path: apiPath, + params: apiParams, + headers: apiHeaders, + ); return models.Preferences.fromMap(res.data); } diff --git a/lib/src/client.dart b/lib/src/client.dart index 61c1178..3af9d66 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -24,10 +24,10 @@ abstract class Client { String? get endPointRealtime => _endPointRealtime; /// Initializes a [Client]. - factory Client( - {String endPoint = 'https://cloud.appwrite.io/v1', - bool selfSigned = false}) => - createClient(endPoint: endPoint, selfSigned: selfSigned); + factory Client({ + String endPoint = 'https://cloud.appwrite.io/v1', + bool selfSigned = false, + }) => createClient(endPoint: endPoint, selfSigned: selfSigned); /// Handle OAuth2 session creation. Future webAuth(Uri url, {String? callbackUrlScheme}); diff --git a/lib/src/client_base.dart b/lib/src/client_base.dart index 108974d..731258d 100644 --- a/lib/src/client_base.dart +++ b/lib/src/client_base.dart @@ -30,7 +30,15 @@ abstract class ClientBase implements Client { ClientBase addHeader(String key, String value); @override - Future<String> ping(); + Future<String> ping() async { + final String apiPath = '/ping'; + final response = await call( + HttpMethod.get, + path: apiPath, + responseType: ResponseType.plain, + ); + return response.data; + } @override Future<Response> call( diff --git a/lib/src/client_browser.dart b/lib/src/client_browser.dart index 33550e6..d7c908f 100644 --- a/lib/src/client_browser.dart +++ b/lib/src/client_browser.dart @@ -12,10 +12,7 @@ import 'input_file.dart'; import 'upload_progress.dart'; import 'response.dart'; -ClientBase createClient({ - required String endPoint, - required bool selfSigned, -}) => +ClientBase createClient({required String endPoint, required bool selfSigned}) => ClientBrowser(endPoint: endPoint, selfSigned: selfSigned); class ClientBrowser extends ClientBase with ClientMixin { @@ -43,14 +40,16 @@ class ClientBrowser extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '14.0.0', + 'x-sdk-version': '15.0.0', 'X-Appwrite-Response-Format': '1.6.0', }; config = {}; - assert(_endPoint.startsWith(RegExp("http://|https://")), - "endPoint $_endPoint must start with 'http'"); + assert( + _endPoint.startsWith(RegExp("http://|https://")), + "endPoint $_endPoint must start with 'http'", + ); init(); } @@ -115,15 +114,6 @@ class ClientBrowser extends ClientBase with ClientMixin { return this; } - @override - Future<String> ping() async { - final String apiPath = '/ping'; - final response = await call(HttpMethod.get, - path: apiPath, responseType: ResponseType.plain); - - return response.data; - } - Future init() async { final cookieFallback = web.window.localStorage['cookieFallback']; if (cookieFallback != null) { @@ -150,8 +140,11 @@ class ClientBrowser extends ClientBase with ClientMixin { late Response res; if (size <= CHUNK_SIZE) { - params[paramName] = http.MultipartFile.fromBytes(paramName, file.bytes!, - filename: file.filename); + params[paramName] = http.MultipartFile.fromBytes( + paramName, + file.bytes!, + filename: file.filename, + ); return call( HttpMethod.post, path: path, @@ -178,12 +171,19 @@ class ClientBrowser extends ClientBase with ClientMixin { List<int> chunk = []; final end = min(offset + CHUNK_SIZE, size); chunk = file.bytes!.getRange(offset, end).toList(); - params[paramName] = http.MultipartFile.fromBytes(paramName, chunk, - filename: file.filename); + params[paramName] = http.MultipartFile.fromBytes( + paramName, + chunk, + filename: file.filename, + ); headers['content-range'] = 'bytes $offset-${min<int>((offset + CHUNK_SIZE - 1), size - 1)}/$size'; - res = await call(HttpMethod.post, - path: path, headers: headers, params: params); + res = await call( + HttpMethod.post, + path: path, + headers: headers, + params: params, + ); offset += CHUNK_SIZE; if (offset < size) { headers['x-appwrite-id'] = res.data['\$id']; @@ -224,7 +224,8 @@ class ClientBrowser extends ClientBase with ClientMixin { final cookieFallback = res.headers['x-fallback-cookies']; if (cookieFallback != null) { debugPrint( - 'Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.'); + 'Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.', + ); addHeader('X-Fallback-Cookies', cookieFallback); web.window.localStorage['cookieFallback'] = cookieFallback; } diff --git a/lib/src/client_io.dart b/lib/src/client_io.dart index 1ef21ca..11f3297 100644 --- a/lib/src/client_io.dart +++ b/lib/src/client_io.dart @@ -18,14 +18,8 @@ import 'package:flutter/foundation.dart'; import 'input_file.dart'; import 'upload_progress.dart'; -ClientBase createClient({ - required String endPoint, - required bool selfSigned, -}) => - ClientIO( - endPoint: endPoint, - selfSigned: selfSigned, - ); +ClientBase createClient({required String endPoint, required bool selfSigned}) => + ClientIO(endPoint: endPoint, selfSigned: selfSigned); class ClientIO extends ClientBase with ClientMixin { static const int CHUNK_SIZE = 5 * 1024 * 1024; @@ -52,9 +46,10 @@ class ClientIO extends ClientBase with ClientMixin { String endPoint = 'https://cloud.appwrite.io/v1', this.selfSigned = false, }) : _endPoint = endPoint { - _nativeClient = HttpClient() - ..badCertificateCallback = - ((X509Certificate cert, String host, int port) => selfSigned); + _nativeClient = + HttpClient() + ..badCertificateCallback = + ((X509Certificate cert, String host, int port) => selfSigned); _httpClient = IOClient(_nativeClient); _endPointRealtime = endPoint .replaceFirst('https://', 'wss://') @@ -64,14 +59,16 @@ class ClientIO extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '14.0.0', + 'x-sdk-version': '15.0.0', 'X-Appwrite-Response-Format': '1.6.0', }; config = {}; - assert(_endPoint.startsWith(RegExp("http://|https://")), - "endPoint $_endPoint must start with 'http'"); + assert( + _endPoint.startsWith(RegExp("http://|https://")), + "endPoint $_endPoint must start with 'http'", + ); init(); } @@ -147,15 +144,6 @@ class ClientIO extends ClientBase with ClientMixin { return this; } - @override - Future<String> ping() async { - final String apiPath = '/ping'; - final response = await call(HttpMethod.get, - path: apiPath, responseType: ResponseType.plain); - - return response.data; - } - Future init() async { if (_initProgress) return; _initProgress = true; @@ -166,8 +154,10 @@ class ClientIO extends ClientBase with ClientMixin { var device = ''; try { PackageInfo packageInfo = await PackageInfo.fromPlatform(); - addHeader('Origin', - 'appwrite-${Platform.operatingSystem}://${packageInfo.packageName}'); + addHeader( + 'Origin', + 'appwrite-${Platform.operatingSystem}://${packageInfo.packageName}', + ); //creating custom user agent DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); @@ -193,8 +183,10 @@ class ClientIO extends ClientBase with ClientMixin { final macinfo = await deviceInfoPlugin.macOsInfo; device = '(Macintosh; ${macinfo.model})'; } - addHeader('user-agent', - '${packageInfo.packageName}/${packageInfo.version} $device'); + addHeader( + 'user-agent', + '${packageInfo.packageName}/${packageInfo.version} $device', + ); } catch (e) { debugPrint('Error getting device info: $e'); device = Platform.operatingSystem; @@ -264,11 +256,16 @@ class ClientIO extends ClientBase with ClientMixin { if (size <= CHUNK_SIZE) { if (file.path != null) { params[paramName] = await http.MultipartFile.fromPath( - paramName, file.path!, - filename: file.filename); + paramName, + file.path!, + filename: file.filename, + ); } else { - params[paramName] = http.MultipartFile.fromBytes(paramName, file.bytes!, - filename: file.filename); + params[paramName] = http.MultipartFile.fromBytes( + paramName, + file.bytes!, + filename: file.filename, + ); } return call( HttpMethod.post, @@ -307,12 +304,19 @@ class ClientIO extends ClientBase with ClientMixin { raf!.setPositionSync(offset); chunk = raf.readSync(CHUNK_SIZE); } - params[paramName] = http.MultipartFile.fromBytes(paramName, chunk, - filename: file.filename); + params[paramName] = http.MultipartFile.fromBytes( + paramName, + chunk, + filename: file.filename, + ); headers['content-range'] = 'bytes $offset-${min<int>((offset + CHUNK_SIZE - 1), size - 1)}/$size'; - res = await call(HttpMethod.post, - path: path, headers: headers, params: params); + res = await call( + HttpMethod.post, + path: path, + headers: headers, + params: params, + ); offset += CHUNK_SIZE; if (offset < size) { headers['x-appwrite-id'] = res.data['\$id']; @@ -336,19 +340,20 @@ class ClientIO extends ClientBase with ClientMixin { Future webAuth(Uri url, {String? callbackUrlScheme}) { return FlutterWebAuth2.authenticate( url: url.toString(), - callbackUrlScheme: callbackUrlScheme != null && _customSchemeAllowed - ? callbackUrlScheme - : "appwrite-callback-" + config['project']!, - options: const FlutterWebAuth2Options( - intentFlags: ephemeralIntentFlags, - ), + callbackUrlScheme: + callbackUrlScheme != null && _customSchemeAllowed + ? callbackUrlScheme + : "appwrite-callback-" + config['project']!, + options: const FlutterWebAuth2Options(intentFlags: ephemeralIntentFlags), ).then((value) async { Uri url = Uri.parse(value); final key = url.queryParameters['key']; final secret = url.queryParameters['secret']; if (key == null || secret == null) { throw AppwriteException( - "Invalid OAuth2 Response. Key and Secret not available.", 500); + "Invalid OAuth2 Response. Key and Secret not available.", + 500, + ); } Cookie cookie = Cookie(key, secret); cookie.domain = Uri.parse(_endPoint).host; @@ -389,10 +394,7 @@ class ClientIO extends ClientBase with ClientMixin { res = await toResponse(streamedResponse); res = await _interceptResponse(res); - return prepareResponse( - res, - responseType: responseType, - ); + return prepareResponse(res, responseType: responseType); } catch (e) { if (e is AppwriteException) { rethrow; diff --git a/lib/src/client_mixin.dart b/lib/src/client_mixin.dart index 1078c31..cd8d386 100644 --- a/lib/src/client_mixin.dart +++ b/lib/src/client_mixin.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'dart:developer'; import 'enums.dart'; -class ClientMixin { +mixin ClientMixin { http.BaseRequest prepareRequest( HttpMethod method, { required Uri uri, @@ -26,14 +26,14 @@ class ClientMixin { } else { if (value is List) { value.asMap().forEach((i, v) { - (request as http.MultipartRequest) - .fields - .addAll({"$key[$i]": v.toString()}); + (request as http.MultipartRequest).fields.addAll({ + "$key[$i]": v.toString(), + }); }); } else { - (request as http.MultipartRequest) - .fields - .addAll({key: value.toString()}); + (request as http.MultipartRequest).fields.addAll({ + key: value.toString(), + }); } } }); @@ -51,17 +51,23 @@ class ClientMixin { }); } uri = Uri( - fragment: uri.fragment, - path: uri.path, - host: uri.host, - scheme: uri.scheme, - queryParameters: params, - port: uri.port); + fragment: uri.fragment, + path: uri.path, + host: uri.host, + scheme: uri.scheme, + queryParameters: params, + port: uri.port, + ); request = http.Request(method.name(), uri); } else { (request as http.Request).body = jsonEncode(params); } + headers['User-Agent'] = Uri.encodeFull(headers['User-Agent'] ?? ''); + headers['X-Forwarded-User-Agent'] = Uri.encodeFull( + headers['X-Forwarded-User-Agent'] ?? '', + ); + request.headers.addAll(headers); return request; } @@ -81,10 +87,10 @@ class ClientMixin { response['message'], response['code'], response['type'], - response, + res.body, ); } else { - throw AppwriteException(res.body); + throw AppwriteException(res.body, res.statusCode, '', res.body); } } dynamic data; @@ -107,15 +113,18 @@ class ClientMixin { } Future<http.Response> toResponse( - http.StreamedResponse streamedResponse) async { + http.StreamedResponse streamedResponse, + ) async { if (streamedResponse.statusCode == 204) { return http.Response( '', streamedResponse.statusCode, - headers: streamedResponse.headers.map((k, v) => - k.toLowerCase() == 'content-type' - ? MapEntry(k, 'text/plain') - : MapEntry(k, v)), + headers: streamedResponse.headers.map( + (k, v) => + k.toLowerCase() == 'content-type' + ? MapEntry(k, 'text/plain') + : MapEntry(k, v), + ), request: streamedResponse.request, isRedirect: streamedResponse.isRedirect, persistentConnection: streamedResponse.persistentConnection, diff --git a/lib/src/client_stub.dart b/lib/src/client_stub.dart index 40423b4..71d51aa 100644 --- a/lib/src/client_stub.dart +++ b/lib/src/client_stub.dart @@ -3,4 +3,5 @@ import 'client_base.dart'; /// Implemented in `client_browser.dart` and `client_io.dart`. ClientBase createClient({required String endPoint, required bool selfSigned}) => throw UnsupportedError( - 'Cannot create a client without dart:html or dart:io.'); + 'Cannot create a client without dart:html or dart:io.', + ); diff --git a/lib/src/cookie_manager.dart b/lib/src/cookie_manager.dart index 6b1e67c..0fbc0dd 100644 --- a/lib/src/cookie_manager.dart +++ b/lib/src/cookie_manager.dart @@ -11,20 +11,19 @@ class CookieManager extends Interceptor { CookieManager(this.cookieJar); @override - FutureOr<http.BaseRequest> onRequest( - http.BaseRequest request, - ) async { + FutureOr<http.BaseRequest> onRequest(http.BaseRequest request) async { await cookieJar .loadForRequest(Uri(scheme: request.url.scheme, host: request.url.host)) .then((cookies) { - var cookie = getCookies(cookies); - if (cookie.isNotEmpty) { - request.headers.addAll({HttpHeaders.cookieHeader: cookie}); - } - return request; - }).catchError((e, stackTrace) { - return request; - }); + var cookie = getCookies(cookies); + if (cookie.isNotEmpty) { + request.headers.addAll({HttpHeaders.cookieHeader: cookie}); + } + return request; + }) + .catchError((e, stackTrace) { + return request; + }); return request; } @@ -43,8 +42,9 @@ class CookieManager extends Interceptor { var cookies = cookie.split(exp); await cookieJar.saveFromResponse( Uri( - scheme: response.request!.url.scheme, - host: response.request!.url.host), + scheme: response.request!.url.scheme, + host: response.request!.url.host, + ), cookies.map((str) => Cookie.fromSetCookieValue(str)).toList(), ); } diff --git a/lib/src/enums.dart b/lib/src/enums.dart index 6566f2e..08fd606 100644 --- a/lib/src/enums.dart +++ b/lib/src/enums.dart @@ -17,5 +17,5 @@ enum ResponseType { plain, /// Get original bytes, the type of response will be List<int> - bytes + bytes, } diff --git a/lib/src/exception.dart b/lib/src/exception.dart index 3d60820..c697457 100644 --- a/lib/src/exception.dart +++ b/lib/src/exception.dart @@ -9,7 +9,7 @@ class AppwriteException implements Exception { /// for more information. final String? type; final int? code; - final dynamic response; + final String? response; /// Initializes an Appwrite Exception. AppwriteException([this.message = "", this.code, this.type, this.response]); diff --git a/lib/src/models/algo_bcrypt.dart b/lib/src/models/algo_bcrypt.dart index 2ba0c39..4e90147 100644 --- a/lib/src/models/algo_bcrypt.dart +++ b/lib/src/models/algo_bcrypt.dart @@ -5,19 +5,13 @@ class AlgoBcrypt implements Model { /// Algo type. final String type; - AlgoBcrypt({ - required this.type, - }); + AlgoBcrypt({required this.type}); factory AlgoBcrypt.fromMap(Map<String, dynamic> map) { - return AlgoBcrypt( - type: map['type'].toString(), - ); + return AlgoBcrypt(type: map['type'].toString()); } Map<String, dynamic> toMap() { - return { - "type": type, - }; + return {"type": type}; } } diff --git a/lib/src/models/algo_md5.dart b/lib/src/models/algo_md5.dart index 8bdfca6..35c7b76 100644 --- a/lib/src/models/algo_md5.dart +++ b/lib/src/models/algo_md5.dart @@ -5,19 +5,13 @@ class AlgoMd5 implements Model { /// Algo type. final String type; - AlgoMd5({ - required this.type, - }); + AlgoMd5({required this.type}); factory AlgoMd5.fromMap(Map<String, dynamic> map) { - return AlgoMd5( - type: map['type'].toString(), - ); + return AlgoMd5(type: map['type'].toString()); } Map<String, dynamic> toMap() { - return { - "type": type, - }; + return {"type": type}; } } diff --git a/lib/src/models/algo_phpass.dart b/lib/src/models/algo_phpass.dart index 4f5f917..7d27adb 100644 --- a/lib/src/models/algo_phpass.dart +++ b/lib/src/models/algo_phpass.dart @@ -5,19 +5,13 @@ class AlgoPhpass implements Model { /// Algo type. final String type; - AlgoPhpass({ - required this.type, - }); + AlgoPhpass({required this.type}); factory AlgoPhpass.fromMap(Map<String, dynamic> map) { - return AlgoPhpass( - type: map['type'].toString(), - ); + return AlgoPhpass(type: map['type'].toString()); } Map<String, dynamic> toMap() { - return { - "type": type, - }; + return {"type": type}; } } diff --git a/lib/src/models/algo_sha.dart b/lib/src/models/algo_sha.dart index 47068be..bae6618 100644 --- a/lib/src/models/algo_sha.dart +++ b/lib/src/models/algo_sha.dart @@ -5,19 +5,13 @@ class AlgoSha implements Model { /// Algo type. final String type; - AlgoSha({ - required this.type, - }); + AlgoSha({required this.type}); factory AlgoSha.fromMap(Map<String, dynamic> map) { - return AlgoSha( - type: map['type'].toString(), - ); + return AlgoSha(type: map['type'].toString()); } Map<String, dynamic> toMap() { - return { - "type": type, - }; + return {"type": type}; } } diff --git a/lib/src/models/continent.dart b/lib/src/models/continent.dart index 990b106..7318b7a 100644 --- a/lib/src/models/continent.dart +++ b/lib/src/models/continent.dart @@ -8,10 +8,7 @@ class Continent implements Model { /// Continent two letter code. final String code; - Continent({ - required this.name, - required this.code, - }); + Continent({required this.name, required this.code}); factory Continent.fromMap(Map<String, dynamic> map) { return Continent( @@ -21,9 +18,6 @@ class Continent implements Model { } Map<String, dynamic> toMap() { - return { - "name": name, - "code": code, - }; + return {"name": name, "code": code}; } } diff --git a/lib/src/models/continent_list.dart b/lib/src/models/continent_list.dart index fb4ee6f..2c605d3 100644 --- a/lib/src/models/continent_list.dart +++ b/lib/src/models/continent_list.dart @@ -8,16 +8,14 @@ class ContinentList implements Model { /// List of continents. final List<Continent> continents; - ContinentList({ - required this.total, - required this.continents, - }); + ContinentList({required this.total, required this.continents}); factory ContinentList.fromMap(Map<String, dynamic> map) { return ContinentList( total: map['total'], continents: List<Continent>.from( - map['continents'].map((p) => Continent.fromMap(p))), + map['continents'].map((p) => Continent.fromMap(p)), + ), ); } diff --git a/lib/src/models/country.dart b/lib/src/models/country.dart index d11c55d..c52b50f 100644 --- a/lib/src/models/country.dart +++ b/lib/src/models/country.dart @@ -8,22 +8,13 @@ class Country implements Model { /// Country two-character ISO 3166-1 alpha code. final String code; - Country({ - required this.name, - required this.code, - }); + Country({required this.name, required this.code}); factory Country.fromMap(Map<String, dynamic> map) { - return Country( - name: map['name'].toString(), - code: map['code'].toString(), - ); + return Country(name: map['name'].toString(), code: map['code'].toString()); } Map<String, dynamic> toMap() { - return { - "name": name, - "code": code, - }; + return {"name": name, "code": code}; } } diff --git a/lib/src/models/country_list.dart b/lib/src/models/country_list.dart index a62f926..6ef8ec4 100644 --- a/lib/src/models/country_list.dart +++ b/lib/src/models/country_list.dart @@ -8,16 +8,14 @@ class CountryList implements Model { /// List of countries. final List<Country> countries; - CountryList({ - required this.total, - required this.countries, - }); + CountryList({required this.total, required this.countries}); factory CountryList.fromMap(Map<String, dynamic> map) { return CountryList( total: map['total'], - countries: - List<Country>.from(map['countries'].map((p) => Country.fromMap(p))), + countries: List<Country>.from( + map['countries'].map((p) => Country.fromMap(p)), + ), ); } diff --git a/lib/src/models/currency_list.dart b/lib/src/models/currency_list.dart index e912ca0..acb515e 100644 --- a/lib/src/models/currency_list.dart +++ b/lib/src/models/currency_list.dart @@ -8,16 +8,14 @@ class CurrencyList implements Model { /// List of currencies. final List<Currency> currencies; - CurrencyList({ - required this.total, - required this.currencies, - }); + CurrencyList({required this.total, required this.currencies}); factory CurrencyList.fromMap(Map<String, dynamic> map) { return CurrencyList( total: map['total'], currencies: List<Currency>.from( - map['currencies'].map((p) => Currency.fromMap(p))), + map['currencies'].map((p) => Currency.fromMap(p)), + ), ); } diff --git a/lib/src/models/document.dart b/lib/src/models/document.dart index 339bd13..37fb2b7 100644 --- a/lib/src/models/document.dart +++ b/lib/src/models/document.dart @@ -19,6 +19,7 @@ class Document implements Model { /// Document permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). final List<String> $permissions; + final Map<String, dynamic> data; Document({ @@ -38,8 +39,7 @@ class Document implements Model { $databaseId: map['\$databaseId'].toString(), $createdAt: map['\$createdAt'].toString(), $updatedAt: map['\$updatedAt'].toString(), - $permissions: List<String>.from( - map['\$permissions']?.map((x) => x.toString()) ?? []), + $permissions: List.from(map['\$permissions'] ?? []), data: map, ); } diff --git a/lib/src/models/document_list.dart b/lib/src/models/document_list.dart index b4fd20e..126ad80 100644 --- a/lib/src/models/document_list.dart +++ b/lib/src/models/document_list.dart @@ -8,16 +8,14 @@ class DocumentList implements Model { /// List of documents. final List<Document> documents; - DocumentList({ - required this.total, - required this.documents, - }); + DocumentList({required this.total, required this.documents}); factory DocumentList.fromMap(Map<String, dynamic> map) { return DocumentList( total: map['total'], - documents: - List<Document>.from(map['documents'].map((p) => Document.fromMap(p))), + documents: List<Document>.from( + map['documents'].map((p) => Document.fromMap(p)), + ), ); } diff --git a/lib/src/models/execution.dart b/lib/src/models/execution.dart index 4ddca35..3a7a353 100644 --- a/lib/src/models/execution.dart +++ b/lib/src/models/execution.dart @@ -78,19 +78,20 @@ class Execution implements Model { $id: map['\$id'].toString(), $createdAt: map['\$createdAt'].toString(), $updatedAt: map['\$updatedAt'].toString(), - $permissions: List<String>.from( - map['\$permissions']?.map((x) => x.toString()) ?? []), + $permissions: List.from(map['\$permissions'] ?? []), functionId: map['functionId'].toString(), trigger: map['trigger'].toString(), status: map['status'].toString(), requestMethod: map['requestMethod'].toString(), requestPath: map['requestPath'].toString(), requestHeaders: List<Headers>.from( - map['requestHeaders'].map((p) => Headers.fromMap(p))), + map['requestHeaders'].map((p) => Headers.fromMap(p)), + ), responseStatusCode: map['responseStatusCode'], responseBody: map['responseBody'].toString(), responseHeaders: List<Headers>.from( - map['responseHeaders'].map((p) => Headers.fromMap(p))), + map['responseHeaders'].map((p) => Headers.fromMap(p)), + ), logs: map['logs'].toString(), errors: map['errors'].toString(), duration: map['duration'].toDouble(), diff --git a/lib/src/models/execution_list.dart b/lib/src/models/execution_list.dart index 32e4053..2a2ef05 100644 --- a/lib/src/models/execution_list.dart +++ b/lib/src/models/execution_list.dart @@ -8,16 +8,14 @@ class ExecutionList implements Model { /// List of executions. final List<Execution> executions; - ExecutionList({ - required this.total, - required this.executions, - }); + ExecutionList({required this.total, required this.executions}); factory ExecutionList.fromMap(Map<String, dynamic> map) { return ExecutionList( total: map['total'], executions: List<Execution>.from( - map['executions'].map((p) => Execution.fromMap(p))), + map['executions'].map((p) => Execution.fromMap(p)), + ), ); } diff --git a/lib/src/models/file.dart b/lib/src/models/file.dart index 84d5a1a..a6a9fa4 100644 --- a/lib/src/models/file.dart +++ b/lib/src/models/file.dart @@ -55,8 +55,7 @@ class File implements Model { bucketId: map['bucketId'].toString(), $createdAt: map['\$createdAt'].toString(), $updatedAt: map['\$updatedAt'].toString(), - $permissions: List<String>.from( - map['\$permissions']?.map((x) => x.toString()) ?? []), + $permissions: List.from(map['\$permissions'] ?? []), name: map['name'].toString(), signature: map['signature'].toString(), mimeType: map['mimeType'].toString(), diff --git a/lib/src/models/file_list.dart b/lib/src/models/file_list.dart index 3b695c9..9f01530 100644 --- a/lib/src/models/file_list.dart +++ b/lib/src/models/file_list.dart @@ -8,10 +8,7 @@ class FileList implements Model { /// List of files. final List<File> files; - FileList({ - required this.total, - required this.files, - }); + FileList({required this.total, required this.files}); factory FileList.fromMap(Map<String, dynamic> map) { return FileList( @@ -21,9 +18,6 @@ class FileList implements Model { } Map<String, dynamic> toMap() { - return { - "total": total, - "files": files.map((p) => p.toMap()).toList(), - }; + return {"total": total, "files": files.map((p) => p.toMap()).toList()}; } } diff --git a/lib/src/models/headers.dart b/lib/src/models/headers.dart index 2249499..463cf69 100644 --- a/lib/src/models/headers.dart +++ b/lib/src/models/headers.dart @@ -8,10 +8,7 @@ class Headers implements Model { /// Header value. final String value; - Headers({ - required this.name, - required this.value, - }); + Headers({required this.name, required this.value}); factory Headers.fromMap(Map<String, dynamic> map) { return Headers( @@ -21,9 +18,6 @@ class Headers implements Model { } Map<String, dynamic> toMap() { - return { - "name": name, - "value": value, - }; + return {"name": name, "value": value}; } } diff --git a/lib/src/models/identity_list.dart b/lib/src/models/identity_list.dart index eab513d..f38eaf6 100644 --- a/lib/src/models/identity_list.dart +++ b/lib/src/models/identity_list.dart @@ -8,16 +8,14 @@ class IdentityList implements Model { /// List of identities. final List<Identity> identities; - IdentityList({ - required this.total, - required this.identities, - }); + IdentityList({required this.total, required this.identities}); factory IdentityList.fromMap(Map<String, dynamic> map) { return IdentityList( total: map['total'], identities: List<Identity>.from( - map['identities'].map((p) => Identity.fromMap(p))), + map['identities'].map((p) => Identity.fromMap(p)), + ), ); } diff --git a/lib/src/models/jwt.dart b/lib/src/models/jwt.dart index e2e31bd..490a182 100644 --- a/lib/src/models/jwt.dart +++ b/lib/src/models/jwt.dart @@ -5,19 +5,13 @@ class Jwt implements Model { /// JWT encoded string. final String jwt; - Jwt({ - required this.jwt, - }); + Jwt({required this.jwt}); factory Jwt.fromMap(Map<String, dynamic> map) { - return Jwt( - jwt: map['jwt'].toString(), - ); + return Jwt(jwt: map['jwt'].toString()); } Map<String, dynamic> toMap() { - return { - "jwt": jwt, - }; + return {"jwt": jwt}; } } diff --git a/lib/src/models/language.dart b/lib/src/models/language.dart index b6ec612..9c45adb 100644 --- a/lib/src/models/language.dart +++ b/lib/src/models/language.dart @@ -11,11 +11,7 @@ class Language implements Model { /// Language native name. final String nativeName; - Language({ - required this.name, - required this.code, - required this.nativeName, - }); + Language({required this.name, required this.code, required this.nativeName}); factory Language.fromMap(Map<String, dynamic> map) { return Language( @@ -26,10 +22,6 @@ class Language implements Model { } Map<String, dynamic> toMap() { - return { - "name": name, - "code": code, - "nativeName": nativeName, - }; + return {"name": name, "code": code, "nativeName": nativeName}; } } diff --git a/lib/src/models/language_list.dart b/lib/src/models/language_list.dart index 29f4948..046b879 100644 --- a/lib/src/models/language_list.dart +++ b/lib/src/models/language_list.dart @@ -8,16 +8,14 @@ class LanguageList implements Model { /// List of languages. final List<Language> languages; - LanguageList({ - required this.total, - required this.languages, - }); + LanguageList({required this.total, required this.languages}); factory LanguageList.fromMap(Map<String, dynamic> map) { return LanguageList( total: map['total'], - languages: - List<Language>.from(map['languages'].map((p) => Language.fromMap(p))), + languages: List<Language>.from( + map['languages'].map((p) => Language.fromMap(p)), + ), ); } diff --git a/lib/src/models/locale_code.dart b/lib/src/models/locale_code.dart index 678e40c..cd5a115 100644 --- a/lib/src/models/locale_code.dart +++ b/lib/src/models/locale_code.dart @@ -8,10 +8,7 @@ class LocaleCode implements Model { /// Locale name final String name; - LocaleCode({ - required this.code, - required this.name, - }); + LocaleCode({required this.code, required this.name}); factory LocaleCode.fromMap(Map<String, dynamic> map) { return LocaleCode( @@ -21,9 +18,6 @@ class LocaleCode implements Model { } Map<String, dynamic> toMap() { - return { - "code": code, - "name": name, - }; + return {"code": code, "name": name}; } } diff --git a/lib/src/models/locale_code_list.dart b/lib/src/models/locale_code_list.dart index c3f4e4b..662fee4 100644 --- a/lib/src/models/locale_code_list.dart +++ b/lib/src/models/locale_code_list.dart @@ -8,16 +8,14 @@ class LocaleCodeList implements Model { /// List of localeCodes. final List<LocaleCode> localeCodes; - LocaleCodeList({ - required this.total, - required this.localeCodes, - }); + LocaleCodeList({required this.total, required this.localeCodes}); factory LocaleCodeList.fromMap(Map<String, dynamic> map) { return LocaleCodeList( total: map['total'], localeCodes: List<LocaleCode>.from( - map['localeCodes'].map((p) => LocaleCode.fromMap(p))), + map['localeCodes'].map((p) => LocaleCode.fromMap(p)), + ), ); } diff --git a/lib/src/models/log_list.dart b/lib/src/models/log_list.dart index a686897..628237f 100644 --- a/lib/src/models/log_list.dart +++ b/lib/src/models/log_list.dart @@ -8,10 +8,7 @@ class LogList implements Model { /// List of logs. final List<Log> logs; - LogList({ - required this.total, - required this.logs, - }); + LogList({required this.total, required this.logs}); factory LogList.fromMap(Map<String, dynamic> map) { return LogList( @@ -21,9 +18,6 @@ class LogList implements Model { } Map<String, dynamic> toMap() { - return { - "total": total, - "logs": logs.map((p) => p.toMap()).toList(), - }; + return {"total": total, "logs": logs.map((p) => p.toMap()).toList()}; } } diff --git a/lib/src/models/membership.dart b/lib/src/models/membership.dart index d06a079..8ee142a 100644 --- a/lib/src/models/membership.dart +++ b/lib/src/models/membership.dart @@ -71,7 +71,7 @@ class Membership implements Model { joined: map['joined'].toString(), confirm: map['confirm'], mfa: map['mfa'], - roles: List<String>.from(map['roles']?.map((x) => x.toString()) ?? []), + roles: List.from(map['roles'] ?? []), ); } diff --git a/lib/src/models/membership_list.dart b/lib/src/models/membership_list.dart index ee65133..46468a3 100644 --- a/lib/src/models/membership_list.dart +++ b/lib/src/models/membership_list.dart @@ -8,16 +8,14 @@ class MembershipList implements Model { /// List of memberships. final List<Membership> memberships; - MembershipList({ - required this.total, - required this.memberships, - }); + MembershipList({required this.total, required this.memberships}); factory MembershipList.fromMap(Map<String, dynamic> map) { return MembershipList( total: map['total'], memberships: List<Membership>.from( - map['memberships'].map((p) => Membership.fromMap(p))), + map['memberships'].map((p) => Membership.fromMap(p)), + ), ); } diff --git a/lib/src/models/mfa_recovery_codes.dart b/lib/src/models/mfa_recovery_codes.dart index 376acbc..6341198 100644 --- a/lib/src/models/mfa_recovery_codes.dart +++ b/lib/src/models/mfa_recovery_codes.dart @@ -5,20 +5,15 @@ class MfaRecoveryCodes implements Model { /// Recovery codes. final List<String> recoveryCodes; - MfaRecoveryCodes({ - required this.recoveryCodes, - }); + MfaRecoveryCodes({required this.recoveryCodes}); factory MfaRecoveryCodes.fromMap(Map<String, dynamic> map) { return MfaRecoveryCodes( - recoveryCodes: List<String>.from( - map['recoveryCodes']?.map((x) => x.toString()) ?? []), + recoveryCodes: List.from(map['recoveryCodes'] ?? []), ); } Map<String, dynamic> toMap() { - return { - "recoveryCodes": recoveryCodes, - }; + return {"recoveryCodes": recoveryCodes}; } } diff --git a/lib/src/models/mfa_type.dart b/lib/src/models/mfa_type.dart index 0573166..fa57cb8 100644 --- a/lib/src/models/mfa_type.dart +++ b/lib/src/models/mfa_type.dart @@ -8,10 +8,7 @@ class MfaType implements Model { /// URI for authenticator apps. final String uri; - MfaType({ - required this.secret, - required this.uri, - }); + MfaType({required this.secret, required this.uri}); factory MfaType.fromMap(Map<String, dynamic> map) { return MfaType( @@ -21,9 +18,6 @@ class MfaType implements Model { } Map<String, dynamic> toMap() { - return { - "secret": secret, - "uri": uri, - }; + return {"secret": secret, "uri": uri}; } } diff --git a/lib/src/models/phone_list.dart b/lib/src/models/phone_list.dart index 1ae5a35..18d2803 100644 --- a/lib/src/models/phone_list.dart +++ b/lib/src/models/phone_list.dart @@ -8,10 +8,7 @@ class PhoneList implements Model { /// List of phones. final List<Phone> phones; - PhoneList({ - required this.total, - required this.phones, - }); + PhoneList({required this.total, required this.phones}); factory PhoneList.fromMap(Map<String, dynamic> map) { return PhoneList( @@ -21,9 +18,6 @@ class PhoneList implements Model { } Map<String, dynamic> toMap() { - return { - "total": total, - "phones": phones.map((p) => p.toMap()).toList(), - }; + return {"total": total, "phones": phones.map((p) => p.toMap()).toList()}; } } diff --git a/lib/src/models/preferences.dart b/lib/src/models/preferences.dart index 3549cff..48163df 100644 --- a/lib/src/models/preferences.dart +++ b/lib/src/models/preferences.dart @@ -4,20 +4,14 @@ part of '../../models.dart'; class Preferences implements Model { final Map<String, dynamic> data; - Preferences({ - required this.data, - }); + Preferences({required this.data}); factory Preferences.fromMap(Map<String, dynamic> map) { - return Preferences( - data: map, - ); + return Preferences(data: map); } Map<String, dynamic> toMap() { - return { - "data": data, - }; + return {"data": data}; } T convertTo<T>(T Function(Map) fromJson) => fromJson(data); diff --git a/lib/src/models/session.dart b/lib/src/models/session.dart index 7d28944..d2fe4f6 100644 --- a/lib/src/models/session.dart +++ b/lib/src/models/session.dart @@ -149,8 +149,7 @@ class Session implements Model { countryCode: map['countryCode'].toString(), countryName: map['countryName'].toString(), current: map['current'], - factors: - List<String>.from(map['factors']?.map((x) => x.toString()) ?? []), + factors: List.from(map['factors'] ?? []), secret: map['secret'].toString(), mfaUpdatedAt: map['mfaUpdatedAt'].toString(), ); diff --git a/lib/src/models/session_list.dart b/lib/src/models/session_list.dart index e4739c9..479272b 100644 --- a/lib/src/models/session_list.dart +++ b/lib/src/models/session_list.dart @@ -8,16 +8,14 @@ class SessionList implements Model { /// List of sessions. final List<Session> sessions; - SessionList({ - required this.total, - required this.sessions, - }); + SessionList({required this.total, required this.sessions}); factory SessionList.fromMap(Map<String, dynamic> map) { return SessionList( total: map['total'], - sessions: - List<Session>.from(map['sessions'].map((p) => Session.fromMap(p))), + sessions: List<Session>.from( + map['sessions'].map((p) => Session.fromMap(p)), + ), ); } diff --git a/lib/src/models/team_list.dart b/lib/src/models/team_list.dart index 817e944..e604f19 100644 --- a/lib/src/models/team_list.dart +++ b/lib/src/models/team_list.dart @@ -8,10 +8,7 @@ class TeamList implements Model { /// List of teams. final List<Team> teams; - TeamList({ - required this.total, - required this.teams, - }); + TeamList({required this.total, required this.teams}); factory TeamList.fromMap(Map<String, dynamic> map) { return TeamList( @@ -21,9 +18,6 @@ class TeamList implements Model { } Map<String, dynamic> toMap() { - return { - "total": total, - "teams": teams.map((p) => p.toMap()).toList(), - }; + return {"total": total, "teams": teams.map((p) => p.toMap()).toList()}; } } diff --git a/lib/src/models/user.dart b/lib/src/models/user.dart index b9f3d8c..50bfb3c 100644 --- a/lib/src/models/user.dart +++ b/lib/src/models/user.dart @@ -92,7 +92,7 @@ class User implements Model { hashOptions: map['hashOptions'], registration: map['registration'].toString(), status: map['status'], - labels: List<String>.from(map['labels']?.map((x) => x.toString()) ?? []), + labels: List.from(map['labels'] ?? []), passwordUpdate: map['passwordUpdate'].toString(), email: map['email'].toString(), phone: map['phone'].toString(), diff --git a/lib/src/realtime_io.dart b/lib/src/realtime_io.dart index 60dc68c..bafa4f1 100644 --- a/lib/src/realtime_io.dart +++ b/lib/src/realtime_io.dart @@ -32,9 +32,11 @@ class RealtimeIO extends RealtimeBase with RealtimeMixin { final cookies = await (client as ClientIO).cookieJar.loadForRequest(uri); headers = {HttpHeaders.cookieHeader: CookieManager.getCookies(cookies)}; - final _websok = IOWebSocketChannel((client as ClientIO).selfSigned - ? await _connectForSelfSignedCert(uri, headers) - : await WebSocket.connect(uri.toString(), headers: headers)); + final _websok = IOWebSocketChannel( + (client as ClientIO).selfSigned + ? await _connectForSelfSignedCert(uri, headers) + : await WebSocket.connect(uri.toString(), headers: headers), + ); return _websok; } @@ -50,13 +52,18 @@ class RealtimeIO extends RealtimeBase with RealtimeMixin { // https://github.com/jonataslaw/getsocket/blob/f25b3a264d8cc6f82458c949b86d286cd0343792/lib/src/io.dart#L104 // and from official dart sdk websocket_impl.dart connect method Future<WebSocket> _connectForSelfSignedCert( - Uri uri, Map<String, dynamic> headers) async { + Uri uri, + Map<String, dynamic> headers, + ) async { try { var r = Random(); var key = base64.encode(List<int>.generate(16, (_) => r.nextInt(255))); var client = HttpClient(context: SecurityContext()); - client.badCertificateCallback = - (X509Certificate cert, String host, int port) { + client.badCertificateCallback = ( + X509Certificate cert, + String host, + int port, + ) { debugPrint('AppwriteRealtime: Allow self-signed certificate'); return true; }; diff --git a/lib/src/realtime_mixin.dart b/lib/src/realtime_mixin.dart index 60ec749..e3516ba 100644 --- a/lib/src/realtime_mixin.dart +++ b/lib/src/realtime_mixin.dart @@ -73,53 +73,57 @@ mixin RealtimeMixin { } debugPrint('subscription: $_lastUrl'); _retries = 0; - _websocketSubscription = _websok?.stream.listen((response) { - final data = RealtimeResponse.fromJson(response); - switch (data.type) { - case 'error': - handleError(data); - break; - case 'connected': - // channels, user? - final message = RealtimeResponseConnected.fromMap(data.data); - if (message.user.isEmpty) { - // send fallback cookie if exists - final cookie = getFallbackCookie?.call(); - if (cookie != null) { - _websok?.sink.add(jsonEncode({ - "type": "authentication", - "data": { - "session": cookie, - }, - })); + _websocketSubscription = _websok?.stream.listen( + (response) { + final data = RealtimeResponse.fromJson(response); + switch (data.type) { + case 'error': + handleError(data); + break; + case 'connected': + // channels, user? + final message = RealtimeResponseConnected.fromMap(data.data); + if (message.user.isEmpty) { + // send fallback cookie if exists + final cookie = getFallbackCookie?.call(); + if (cookie != null) { + _websok?.sink.add( + jsonEncode({ + "type": "authentication", + "data": {"session": cookie}, + }), + ); + } } - } - _startHeartbeat(); // Start heartbeat after successful connection - break; - case 'pong': - debugPrint('Received heartbeat response from realtime server'); - break; - case 'event': - final message = RealtimeMessage.fromMap(data.data); - for (var subscription in _subscriptions.values) { - for (var channel in message.channels) { - if (subscription.channels.contains(channel)) { - subscription.controller.add(message); + _startHeartbeat(); // Start heartbeat after successful connection + break; + case 'pong': + debugPrint('Received heartbeat response from realtime server'); + break; + case 'event': + final message = RealtimeMessage.fromMap(data.data); + for (var subscription in _subscriptions.values) { + for (var channel in message.channels) { + if (subscription.channels.contains(channel)) { + subscription.controller.add(message); + } } } - } - break; - } - }, onDone: () { - _stopHeartbeat(); - _retry(); - }, onError: (err, stack) { - _stopHeartbeat(); - for (var subscription in _subscriptions.values) { - subscription.controller.addError(err, stack); - } - _retry(); - }); + break; + } + }, + onDone: () { + _stopHeartbeat(); + _retry(); + }, + onError: (err, stack) { + _stopHeartbeat(); + for (var subscription in _subscriptions.values) { + subscription.controller.addError(err, stack); + } + _retry(); + }, + ); } catch (e) { if (e is AppwriteException) { rethrow; @@ -145,16 +149,17 @@ mixin RealtimeMixin { return _retries < 5 ? 1 : _retries < 15 - ? 5 - : _retries < 100 - ? 10 - : 60; + ? 5 + : _retries < 100 + ? 10 + : 60; } Uri _prepareUri() { if (client.endPointRealtime == null) { throw AppwriteException( - "Please set endPointRealtime to connect to realtime server"); + "Please set endPointRealtime to connect to realtime server", + ); } var uri = Uri.parse(client.endPointRealtime!); return Uri( @@ -175,27 +180,29 @@ mixin RealtimeMixin { Future.delayed(Duration.zero, () => _createSocket()); int id = DateTime.now().microsecondsSinceEpoch; RealtimeSubscription subscription = RealtimeSubscription( - controller: controller, - channels: channels, - close: () async { - _subscriptions.remove(id); - controller.close(); - _cleanup(channels); + controller: controller, + channels: channels, + close: () async { + _subscriptions.remove(id); + controller.close(); + _cleanup(channels); - if (_channels.isNotEmpty) { - await Future.delayed(Duration.zero, () => _createSocket()); - } else { - await _closeConnection(); - } - }); + if (_channels.isNotEmpty) { + await Future.delayed(Duration.zero, () => _createSocket()); + } else { + await _closeConnection(); + } + }, + ); _subscriptions[id] = subscription; return subscription; } void _cleanup(List<String> channels) { for (var channel in channels) { - bool found = _subscriptions.values - .any((subscription) => subscription.channels.contains(channel)); + bool found = _subscriptions.values.any( + (subscription) => subscription.channels.contains(channel), + ); if (!found) { _channels.remove(channel); } diff --git a/lib/src/realtime_response.dart b/lib/src/realtime_response.dart index b035611..e444cd0 100644 --- a/lib/src/realtime_response.dart +++ b/lib/src/realtime_response.dart @@ -4,26 +4,14 @@ import 'package:flutter/foundation.dart'; class RealtimeResponse { final String type; // error, event, connected, response final Map<String, dynamic> data; - RealtimeResponse({ - required this.type, - required this.data, - }); - - RealtimeResponse copyWith({ - String? type, - Map<String, dynamic>? data, - }) { - return RealtimeResponse( - type: type ?? this.type, - data: data ?? this.data, - ); + RealtimeResponse({required this.type, required this.data}); + + RealtimeResponse copyWith({String? type, Map<String, dynamic>? data}) { + return RealtimeResponse(type: type ?? this.type, data: data ?? this.data); } Map<String, dynamic> toMap() { - return { - 'type': type, - 'data': data, - }; + return {'type': type, 'data': data}; } factory RealtimeResponse.fromMap(Map<String, dynamic> map) { diff --git a/lib/src/realtime_response_connected.dart b/lib/src/realtime_response_connected.dart index dce0840..9994958 100644 --- a/lib/src/realtime_response_connected.dart +++ b/lib/src/realtime_response_connected.dart @@ -4,10 +4,7 @@ import 'package:flutter/foundation.dart'; class RealtimeResponseConnected { final List<String> channels; final Map<String, dynamic> user; - RealtimeResponseConnected({ - required this.channels, - this.user = const {}, - }); + RealtimeResponseConnected({required this.channels, this.user = const {}}); RealtimeResponseConnected copyWith({ List<String>? channels, @@ -20,10 +17,7 @@ class RealtimeResponseConnected { } Map<String, dynamic> toMap() { - return { - 'channels': channels, - 'user': user, - }; + return {'channels': channels, 'user': user}; } factory RealtimeResponseConnected.fromMap(Map<String, dynamic> map) { diff --git a/lib/src/realtime_stub.dart b/lib/src/realtime_stub.dart index e60cf4a..631afe3 100644 --- a/lib/src/realtime_stub.dart +++ b/lib/src/realtime_stub.dart @@ -2,5 +2,7 @@ import 'realtime_base.dart'; import 'client.dart'; /// Implemented in `realtime_browser.dart` and `realtime_io.dart`. -RealtimeBase createRealtime(Client client) => throw UnsupportedError( - 'Cannot create a client without dart:html or dart:io.'); +RealtimeBase createRealtime(Client client) => + throw UnsupportedError( + 'Cannot create a client without dart:html or dart:io.', + ); diff --git a/lib/src/realtime_subscription.dart b/lib/src/realtime_subscription.dart index 1707691..aaecd79 100644 --- a/lib/src/realtime_subscription.dart +++ b/lib/src/realtime_subscription.dart @@ -16,7 +16,9 @@ class RealtimeSubscription { final Future<void> Function() close; /// Initializes a [RealtimeSubscription] - RealtimeSubscription( - {required this.close, required this.channels, required this.controller}) - : stream = controller.stream; + RealtimeSubscription({ + required this.close, + required this.channels, + required this.controller, + }) : stream = controller.stream; } diff --git a/lib/src/upload_progress.dart b/lib/src/upload_progress.dart index 44cde38..5a19b0f 100644 --- a/lib/src/upload_progress.dart +++ b/lib/src/upload_progress.dart @@ -44,7 +44,7 @@ class UploadProgress { "progress": progress, "sizeUploaded": sizeUploaded, "chunksTotal": chunksTotal, - "chunksUploaded": chunksUploaded + "chunksUploaded": chunksUploaded, }; } diff --git a/pubspec.yaml b/pubspec.yaml index 79300b8..2d8f32b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: appwrite -version: 14.0.0 +version: 15.0.0 description: Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API homepage: https://appwrite.io repository: https://github.com/appwrite/sdk-for-flutter