Overview
CloudBase Flutter SDK enables you to use CloudBase capabilities in Flutter applications, including authentication, document database, data models, MySQL database, cloud functions, cloud hosting, APIs, and more. For usage, please refer to CloudBase Flutter SDK, or check the sample code.
CloudBase Flutter SDK is fully aligned with HTTP API
SDK is categorized by functionality:
- Authentication: API methods for user registration and login, supporting multiple login methods.
- Session Management: API methods for managing user session state and tokens.
- User Management: API methods for retrieving, updating, and managing user information.
- Identity Source Management: API methods for managing third-party identity source binding and unbinding.
- Password Management: API methods for password reset and change.
- Verification Management: API methods for verification code sending, verification, resending, CAPTCHA creation, verification, and management.
- Document Database: Operations for NoSQL document database including collections, documents, queries, updates, deletions, aggregation, transactions, and more.
- Data Model: Data model CRUD operations.
- Data Source Query: Query data source aggregation list, details, Schema, and table names.
- MySQL Database: MySQL RESTful database operations.
- Cloud Functions: Call cloud functions and function-type cloud hosting.
- Cloud Hosting: Call cloud hosting container services.
- APIs: Call APIs interfaces.
- Cloud Storage: File upload, download, delete, copy, move, and other operations.
Basic Usage Example
- Initialization
- Login Status Check
- User Registration Flow
- Password Login
- Logout
- Listen for State Changes
- Call Cloud Function
accessKey can be generated in CloudBase Platform/API Key Configuration
import 'package:cloudbase_flutter/cloudbase_flutter.dart';
// Initialize (async)
final app = await CloudBase.init(
env: 'your-env-id', // Replace with your environment ID
region: 'ap-shanghai', // Region, default is Shanghai
accessKey: 'your-key', // Fill in the generated Publishable Key
authConfig: AuthConfig(
detectSessionInUrl: true, // Optional: automatically detect OAuth parameters in URL
),
);
final auth = app.auth;
// Check login status
Future<bool> checkAuthStatus() async {
final result = await auth.getSession();
if (result.error != null) {
print('Failed to check login status: ${result.error!.message}');
return false;
}
if (result.data?.session != null) {
print('User is logged in: ${result.data!.user?.id}');
return true;
} else {
print('User is not logged in');
return false;
}
}
// User registration example (two-step verification flow)
Future<void> registerUser(String email, String password) async {
// Step 1: Send verification code
final signUpResult = await auth.signUp(SignUpReq(
email: email,
password: password,
));
if (signUpResult.error != null) {
print('Failed to send verification code: ${signUpResult.error!.message}');
return;
}
print('Verification code sent, waiting for user input...');
// Step 2: Verify verification code and complete registration
final verifyResult = await signUpResult.data!.verifyOtp!(
VerifyOtpParams(token: 'User input verification code'),
);
if (verifyResult.error != null) {
print('Registration failed: ${verifyResult.error!.message}');
} else {
print('Registration successful: ${verifyResult.data?.user?.id}');
}
}
// Password login example
Future<void> loginWithPassword(String email, String password) async {
final result = await auth.signInWithPassword(
SignInWithPasswordReq(email: email, password: password),
);
if (result.error != null) {
print('Login failed: ${result.error!.message}');
} else {
print('Login successful: ${result.data?.user?.id}');
print('Access Token: ${result.data?.session?.accessToken}');
}
}
// Logout example
Future<void> logout() async {
await auth.signOut();
print('Logged out');
}
// Listen for authentication state changes
final result = auth.onAuthStateChange((event, session, info) {
switch (event) {
case AuthStateChangeEvent.signedIn:
print('User signed in');
break;
case AuthStateChangeEvent.signedOut:
print('User signed out');
break;
case AuthStateChangeEvent.tokenRefreshed:
print('Token refreshed');
break;
case AuthStateChangeEvent.userUpdated:
print('User info updated');
break;
default:
break;
}
});
// Unsubscribe
result.data?.subscription.unsubscribe();
// Call cloud function example
final result = await app.callFunction(
name: 'myFunction',
data: {'key': 'value'},
);
if (result.isSuccess) {
print('Execution result: ${result.result}');
} else {
print('Execution failed: ${result.message}');
}
Authentication
signUp
Future<SignUpRes> auth.signUp(SignUpReq params)
Register a new user account using smart registration and login flow.
- Creates a new user account
- Uses smart registration and login flow: send verification code → wait for user input → smart judgment of user existence → auto login or register and login
- If user already exists, directly login; if user does not exist, register new user and auto login
Parameters
Response
Example
- Email Registration
- Phone Registration
- Error Handling
final result = await auth.signUp(SignUpReq(
email: 'user@example.com',
password: 'securePassword123',
nickname: 'New User',
));
if (result.error != null) {
print('Registration failed: ${result.error!.message}');
return;
}
// Verify verification code
final verifyResult = await result.data!.verifyOtp!(
VerifyOtpParams(token: '123456'),
);
if (verifyResult.isSuccess) {
print('Registration successful: ${verifyResult.data?.user?.id}');
}
final result = await auth.signUp(SignUpReq(
phone: '13800138000',
password: 'securePassword123',
));
if (result.error != null) {
print('Failed to send verification code: ${result.error!.message}');
return;
}
final verifyResult = await result.data!.verifyOtp!(
VerifyOtpParams(token: '123456'),
);
if (verifyResult.isSuccess) {
print('Registration successful: ${verifyResult.data?.user?.phone}');
}
final result = await auth.signUp(SignUpReq(
email: 'user@example.com',
password: 'password123',
));
if (result.error != null) {
final code = result.error!.code;
switch (code) {
case 'already_exists':
print('Email already registered');
break;
case 'password_too_weak':
print('Password too weak');
break;
case 'invalid_email':
print('Invalid email format');
break;
default:
print('Registration failed: ${result.error!.message}');
}
}
signInAnonymously
Future<SignInRes> auth.signInAnonymously({String? providerToken})
Anonymous login, creates a temporary anonymous user account.
- Creates a temporary anonymous user account
- No identity verification info needed
- Suitable for scenarios requiring temporary access
Parameters
Third-party platform token, used to associate third-party platform identity
Response
Example
- Anonymous Login
- Anonymous User Upgrade Flow
final result = await auth.signInAnonymously();
if (result.isSuccess) {
print('Anonymous login successful');
print('User ID: ${result.data?.user?.id}');
print('Is anonymous: ${result.data?.user?.isAnonymous}');
} else {
print('Anonymous login failed: ${result.error!.message}');
}
// Step 1: Anonymous login
final anonymousResult = await auth.signInAnonymously();
if (anonymousResult.error != null) {
print('Anonymous login failed: ${anonymousResult.error!.message}');
return;
}
print('Anonymous login successful, preparing to upgrade to official user');
// Step 2: Bind email (pass anonymousToken during registration)
final upgradeResult = await auth.signUp(SignUpReq(
email: 'user@example.com',
password: 'securePassword123',
anonymousToken: anonymousResult.data?.session?.accessToken,
));
if (upgradeResult.error != null) {
print('Upgrade failed: ${upgradeResult.error!.message}');
return;
}
// Step 3: Verify verification code
final verifyResult = await upgradeResult.data!.verifyOtp!(
VerifyOtpParams(token: '123456'),
);
if (verifyResult.isSuccess) {
print('Anonymous user upgrade successful');
}
signInWithPassword
Future<SignInRes> auth.signInWithPassword(SignInWithPasswordReq params)
Login with password. Supports login via username, email, or phone number.
Parameters
Response
Example
- Email Password Login
- Error Handling
final result = await auth.signInWithPassword(
SignInWithPasswordReq(
email: 'user@example.com',
password: 'securePassword123',
),
);
if (result.isSuccess) {
print('Login successful: ${result.data?.user?.id}');
} else {
print('Login failed: ${result.error!.message}');
}
final result = await auth.signInWithPassword(
SignInWithPasswordReq(
email: 'user@example.com',
password: 'wrongPassword',
),
);
if (result.error != null) {
switch (result.error!.code) {
case 'invalid_credentials':
print('Incorrect username or password');
break;
case 'user_not_found':
print('User does not exist');
break;
default:
print('Login failed: ${result.error!.message}');
}
}
signInWithOtp
Future<SignInWithOtpRes> auth.signInWithOtp(SignInWithOtpReq params)
Login with OTP (one-time verification code). After calling, a verification code will be sent. You need to complete verification through the returned verifyOtp callback.
- If the user does not exist, a user will be created by default. You can control whether to automatically create a user with the
shouldCreateUserparameter (default is true)
Parameters
Response
Example
- Example
final result = await auth.signInWithOtp(
SignInWithOtpReq(email: 'user@example.com'),
);
if (result.error != null) {
print('Failed to send verification code: ${result.error!.message}');
return;
}
// Call after user inputs verification code
final loginResult = await result.data!.verifyOtp!(
VerifyOtpParams(token: '123456'),
);
if (loginResult.isSuccess) {
print('OTP login successful: ${loginResult.data?.user?.id}');
}
signInWithOAuth
Future<SignInOAuthRes> auth.signInWithOAuth(SignInWithOAuthReq params)
Login with OAuth third-party platform. Returns authorization URL, you need to guide the user to redirect to this URL to complete authorization.
Parameters
Response
Example
- Example
final result = await auth.signInWithOAuth(
SignInWithOAuthReq(provider: 'wechat'),
);
if (result.isSuccess) {
final authUrl = result.data!.url!;
print('Please redirect to authorization page: $authUrl');
// Guide user to open authUrl for authorization
}
signInWithIdToken
Future<SignInRes> auth.signInWithIdToken(SignInWithIdTokenReq params)
Login with IdToken. Suitable for scenarios where third-party platform tokens have been obtained.
Parameters
Response
Example
- Example
final result = await auth.signInWithIdToken(
SignInWithIdTokenReq(
token: 'provider-id-token',
provider: 'wechat',
),
);
if (result.isSuccess) {
print('IdToken login successful: ${result.data?.user?.id}');
} else {
print('Login failed: ${result.error!.message}');
}
signInWithCustomTicket
Future<SignInRes> auth.signInWithCustomTicket(Future<String> Function() getTicketFn)
Login with custom ticket. By passing an async function to get the ticket, the server generates the ticket and completes the login.
Parameters
Async function to get custom login ticket
Response
Example
- Basic Usage
final result = await auth.signInWithCustomTicket(() async {
// Get custom ticket from your server
final ticket = await fetchTicketFromServer();
return ticket;
});
if (result.isSuccess) {
print('Custom ticket login successful: ${result.data?.user?.id}');
} else {
print('Login failed: ${result.error!.message}');
}
Session Management
getSession
Future<SignInRes> auth.getSession();
Get current session. If token has expired, it will be automatically refreshed.
Parameters
No parameters
Response
Example
- Example
final result = await auth.getSession();
if (result.isSuccess) {
final session = result.data?.session;
print('Access Token: ${session?.accessToken}');
print('User: ${result.data?.user?.id}');
} else {
print('Failed to get session: ${result.error!.message}');
}
refreshSession
Future<SignInRes> auth.refreshSession([String? refreshToken])
Refresh session. Use Refresh Token to get a new Access Token.
Parameters
Refresh token (optional, defaults to current session's refreshToken)
Response
Example
- Example
final result = await auth.refreshSession();
if (result.isSuccess) {
print('Session refreshed');
print('New Access Token: ${result.data?.session?.accessToken}');
} else {
print('Refresh failed: ${result.error!.message}');
}
setSession
Future<SignInRes> auth.setSession(SetSessionReq params)
Set session. Restore session state with Refresh Token.
Parameters
Response
Example
- Example
final result = await auth.setSession(
SetSessionReq(refreshToken: 'your-refresh-token'),
);
if (result.isSuccess) {
print('Session set successfully: ${result.data?.user?.id}');
}
signOut
Future<SignOutRes> auth.signOut([SignOutReq? params])
Logout. Clear local session and notify server to revoke token.
Parameters
Logout configuration options (optional)
Response
Example
- Example
await auth.signOut();
print("Logged out");
onAuthStateChange
OnAuthStateChangeResult auth.onAuthStateChange(OnAuthStateChangeCallback callback)
Listen for authentication state changes. Supports listening for login, logout, token refresh, and user update events.
Parameters
State change callback function
Response
Example
- Example
final result = auth.onAuthStateChange((event, session, info) {
print('Auth state changed: ${event.value}');
if (session != null) {
print('User: ${session.user?.id}');
}
});
// Stop listening
result.data?.subscription.unsubscribe();
getClaims
Future<GetClaimsRes> auth.getClaims();
Get JWT Claims of current Access Token (token claims).
Parameters
No parameters
Response
Example
- Example
final result = await auth.getClaims();
if (result.isSuccess) {
final claims = result.data?.claims;
print('User ID: ${claims?.sub}');
print('Email: ${claims?.email}');
print('User groups: ${claims?.groups}');
print('Expiration: ${claims?.exp}');
}
User Management
getUser
Future<GetUserRes> auth.getUser();
Get current logged-in user info.
Parameters
No parameters
Response
Example
- Example
final result = await auth.getUser();
if (result.isSuccess) {
final user = result.data?.user;
print('User ID: ${user?.id}');
print('Email: ${user?.email}');
print('Nickname: ${user?.userMetadata?.nickName}');
} else {
print('Failed to get user info: ${result.error!.message}');
}
refreshUser
Future<SignInRes> auth.refreshUser();
Refresh user info. Re-fetch the latest user data from server and update local session.
Parameters
No parameters
Response
Example
- Example
final result = await auth.refreshUser();
if (result.isSuccess) {
print('User info refreshed: ${result.data?.user?.id}');
}
updateUser
Future<UpdateUserRes> auth.updateUser(UpdateUserReq params)
Update user info. If updating email or phone number, verification code verification is required.
Parameters
Response
Example
- Update Basic Info
- Update Email (Requires Verification)
final result = await auth.updateUser(
UpdateUserReq(nickname: 'New Nickname', avatarUrl: 'https://example.com/avatar.png'),
);
if (result.isSuccess) {
print('User info updated: ${result.data?.user?.userMetadata?.nickName}');
}
final result = await auth.updateUser(
UpdateUserReq(email: 'new@example.com'),
);
if (result.isSuccess && result.data?.verifyOtp != null) {
final verifyResult = await result.data!.verifyOtp!(
UpdateUserVerifyParams(token: '123456'),
);
if (verifyResult.isSuccess) {
print('Email updated successfully: ${verifyResult.data?.user?.id}');
}
}
deleteUser
Future<CloudBaseResponse<void>> auth.deleteUser(DeleteUserReq params)
Delete current user. Password is required for security verification.
Parameters
Response
Example
- Example
final result = await auth.deleteUser(
DeleteUserReq(password: 'currentPassword'),
);
if (result.isSuccess) {
print('User deleted');
} else {
print('Deletion failed: ${result.error!.message}');
}
Identity Source Management
getUserIdentities
Future<GetUserIdentitiesRes> auth.getUserIdentities();
Get the list of identity sources bound to the current user.
Parameters
No parameters
Response
Example
- Example
final result = await auth.getUserIdentities();
if (result.isSuccess) {
for (final identity in result.data?.identities ?? []) {
print('Identity: ${identity.name} (${identity.provider})');
}
}
linkIdentity
Future<LinkIdentityRes> auth.linkIdentity(LinkIdentityReq params)
Bind third-party identity source. Will redirect to third-party authorization page to complete binding.
Parameters
Response
Example
- Example
final result = await auth.linkIdentity(
LinkIdentityReq(provider: 'wechat'),
);
if (result.isSuccess) {
print('Identity source bound successfully: ${result.data?.provider}');
}
unlinkIdentity
Future<CloudBaseResponse<void>> auth.unlinkIdentity(UnlinkIdentityReq params)
Unbind third-party identity source.
Parameters
Response
Example
- Example
final result = await auth.unlinkIdentity(
UnlinkIdentityReq(provider: 'wechat'),
);
if (result.isSuccess) {
print('Identity source unbound');
}
Password Management
resetPasswordForEmail
Future<ResetPasswordForEmailRes> auth.resetPasswordForEmail(String emailOrPhone, {String? redirectTo})
Reset password via email or phone number. After calling, a verification code will be sent. You need to complete password reset through the returned updateUser callback.
Parameters
Email or phone number
Redirect URL
Response
Example
- Example
final result = await auth.resetPasswordForEmail('user@example.com');
if (result.error != null) {
print('Failed to send verification code: ${result.error!.message}');
return;
}
// After user receives verification code
final resetResult = await result.data!.updateUser!(
UpdateUserAttributes(nonce: '123456', password: 'newPassword123'),
);
if (resetResult.isSuccess) {
print('Password reset successfully, auto-logged in');
}
resetPasswordForOld
Future<SignInRes> auth.resetPasswordForOld(ResetPasswordForOldReq params)
Reset password with old password.
Parameters
Response
Example
- Example
final result = await auth.resetPasswordForOld(
ResetPasswordForOldReq(
oldPassword: 'oldPassword123',
newPassword: 'newPassword456',
),
);
if (result.isSuccess) {
print('Password changed successfully');
} else {
print('Password change failed: ${result.error!.message}');
}
reauthenticate
Future<ReauthenticateRes> auth.reauthenticate();
Re-authenticate. Send verification code to user's email or phone number. After verification, sensitive operations can be performed (such as setting a new password).
Parameters
No parameters
Response
Example
- Example
final result = await auth.reauthenticate();
if (result.error != null) {
print('Failed to send verification code: ${result.error!.message}');
return;
}
final authResult = await result.data!.updateUser!(
UpdateUserAttributes(nonce: '123456', password: 'newSecurePassword'),
);
if (authResult.isSuccess) {
print('Re-authentication successful');
}
Verification Management
getVerification
Future<GetVerificationRes> auth.getVerification(GetVerificationReq params)
Send verification code. Supports sending to email or phone number.
Parameters
Response
Example
- Example
final result = await auth.getVerification(
GetVerificationReq(email: 'user@example.com'),
);
if (result.isSuccess) {
print('Verification code sent');
} else {
print('Failed to send: ${result.error!.message}');
}
verify
Future<VerifyRes> auth.verify(VerifyReq params)
Verify verification code (for email/phone verification).
Parameters
Response
Example
- Example
final result = await auth.verify(
VerifyReq(
email: 'user@example.com',
token: '123456',
),
);
if (result.isSuccess) {
print('Verification successful');
} else {
print('Verification failed: ${result.error!.message}');
}
verifyOAuth
Future<SignInRes> auth.verifyOAuth(VerifyOAuthReq params)
Verify OAuth callback. Handle the callback after user authorization on third-party platform.
Parameters
Response
Example
- Example
// Handle OAuth callback (typically in web platform)
final result = await auth.verifyOAuth(
VerifyOAuthReq(
code: 'auth-code-from-callback',
state: 'state-from-callback',
),
);
if (result.isSuccess) {
print('OAuth verification successful: ${result.data?.user?.id}');
}
verifyOtp
Future<SignInRes> auth.verifyOtp(VerifyOtpParams params)
Verify OTP (one-time password). Used to verify the verification code sent by signInWithOtp or signUp.
Parameters
Response
Example
- Example
final result = await auth.verifyOtp(
VerifyOtpParams(token: '123456'),
);
if (result.isSuccess) {
print('OTP verification successful: ${result.data?.user?.id}');
} else {
print('Verification failed: ${result.error!.message}');
}
resend
Future<ResendRes> auth.resend(ResendReq params)
Resend verification code.
Parameters
Response
Example
- Example
final result = await auth.resend(
ResendReq(email: 'user@example.com'),
);
if (result.isSuccess) {
print('Verification code resent');
} else {
print('Resend failed: ${result.error!.message}');
}
getCaptchaToken
Future<GetCaptchaTokenRes> auth.getCaptchaToken()
Get CAPTCHA token. Used to get CAPTCHA verification token before sending verification code.
Parameters
No parameters
Response
Example
- Example
final result = await auth.getCaptchaToken();
if (result.isSuccess) {
final captchaToken = result.data?.captchaToken;
print('CAPTCHA token: $captchaToken');
}
createCaptchaData
Future<CreateCaptchaDataRes> auth.createCaptchaData(CreateCaptchaDataReq params)
Create CAPTCHA verification data. Used to initialize CAPTCHA challenge.
Parameters
Response
Example
- Example
final result = await auth.createCaptchaData(
CreateCaptchaDataReq(captchaToken: 'captcha-token'),
);
if (result.isSuccess) {
print('CAPTCHA data created');
}
verifyCaptchaData
Future<VerifyCaptchaDataRes> auth.verifyCaptchaData(VerifyCaptchaDataReq params)
Verify CAPTCHA. Validate user's CAPTCHA response.
Parameters
Response
Example
- Example
final result = await auth.verifyCaptchaData(
VerifyCaptchaDataReq(
captchaToken: 'captcha-token',
captchaAnswer: 'user-answer',
),
);
if (result.isSuccess) {
print('CAPTCHA verified successfully');
} else {
print('CAPTCHA verification failed');
}
clearCaptchaToken
Future<ClearCaptchaTokenRes> auth.clearCaptchaToken()
Clear CAPTCHA token. Clean up CAPTCHA state after verification.
Parameters
No parameters
Response
Example
- Example
final result = await auth.clearCaptchaToken();
if (result.isSuccess) {
print('CAPTCHA token cleared');
}
Document Database
The document database (NoSQL) provides JS SDK-style chained calls, and you get an instance via app.database(). It supports create, read, update, and delete operations on collections and documents, complex conditional queries, aggregation, transactions, and more, and is fully aligned with the HTTP API.
- Initialize & Add
- Conditional Query
- Update & Delete
- Transaction
final app = await CloudBase.init(env: 'your-env-id');
final db = app.database();
// Add a single record
final addRes = await db.collection('todos').add({
'title': 'Learn CloudBase',
'completed': false,
'createdAt': DateTime.now(),
});
print('New document ID: ${addRes.id}');
final db = app.database();
final _ = db.command;
final res = await db
.collection('todos')
.where({'completed': false, 'priority': _.inList(['high', 'medium'])})
.orderBy('createdAt', OrderDirection.desc)
.limit(10)
.get();
print('Query results: ${res.data}');
final db = app.database();
final _ = db.command;
// Update a single document, increment a field
await db.collection('todos').doc('doc-id').update({'count': _.inc(1)});
// Delete a single document
await db.collection('todos').doc('doc-id').remove();
final db = app.database();
final _ = db.command;
final transaction = await db.startTransaction();
try {
await transaction.collection('accounts').doc('a').update({'balance': _.inc(-100)});
await transaction.collection('accounts').doc('b').update({'balance': _.inc(100)});
await transaction.commit();
} catch (e) {
await transaction.rollback();
}
database
CloudBaseDatabase app.database({String? instance, String? database})
Gets a document database instance. The optional parameters instance (instance ID) and database (database name) specify the database to access. Both can be omitted, in which case (default) is used (the default database of the default instance). You only need to pass them explicitly when accessing a non-default instance or database.
Parameters
Instance ID, defaults to (default)
Database name, defaults to (default)
Response
Database instance, providing capabilities such as collection, command, Geo, and startTransaction
Example
- Basic Initialization
- Specify Database Configuration
final db = app.database();
final db = app.database(instance: 'my-instance', database: 'my-db');
createCollection
Future<DbCreateCollectionResult> db.createCollection(String collName)
Creates a collection.
Parameters
Collection name
Response
Example
- Create Collection
final result = await db.createCollection('todos');
if (result.isSuccess) {
print('Collection created successfully');
}
collection
CollectionReference db.collection(String collName)
Gets a collection reference, on which you can chain query methods such as where, orderBy, limit, skip, and field, or call doc, add, get, count, and aggregate.
Parameters
Collection name
Response
Collection reference
Example
- Get Collection Reference
- Chained Calls
final collection = db.collection('todos');
final res = await db
.collection('todos')
.where({'completed': false})
.orderBy('createdAt', OrderDirection.desc)
.limit(10)
.get();
add
Future<DbAddResult> collection.add(dynamic data)
Adds records to a collection, supporting single (Map) and batch (List) additions.
Parameters
Document data. Pass a Map for a single addition, or a List for batch addition
Response
Example
- Single Addition
- Batch Addition
final res = await db.collection('todos').add({
'title': 'Learn CloudBase',
'completed': false,
'createdAt': DateTime.now(),
});
print('New document ID: ${res.id}');
final res = await db.collection('todos').add([
{'title': 'Task 1', 'completed': false},
{'title': 'Task 2', 'completed': true},
]);
print('New document ID list: ${res.ids}');
doc
DocumentReference collection.doc(dynamic docId)
Gets a document reference, on which you can call get, update, set, remove, and field.
Parameters
Document ID
Response
Document reference
Example
- Get Document Reference
final docRef = db.collection('todos').doc('doc-id');
final res = await docRef.get();
print(res.data);
where
Query collection.where(Map<String, dynamic> condition)
Sets query conditions, supporting equality matching and complex condition filtering via db.command operators.
Parameters
Query condition object, supporting equality matching, operator matching, nested field matching, and more
Response
Query object, on which you can chain methods such as orderBy, limit, skip, field, get, count, update, and remove
Example
- Basic Query
- Complex Conditional Query
final res = await db
.collection('todos')
.where({'completed': false, 'priority': 'high'})
.get();
print('Query results: ${res.data}');
final _ = db.command;
final res = await db
.collection('todos')
.where({
'age': _.gt(18),
'tags': _.inList(['tech', 'study']),
'createdAt': _.gte(DateTime.now().subtract(const Duration(days: 7))),
})
.orderBy('createdAt', OrderDirection.desc)
.limit(10)
.get();
print('Query results: ${res.data}');
orderBy
Query collection.orderBy(String field, OrderDirection direction)
Sets the sort rule. direction can be OrderDirection.asc or OrderDirection.desc. You can call it multiple times to combine multi-field sorting.
Parameters
Sort field
Sort direction: OrderDirection.asc (ascending) or OrderDirection.desc (descending)
Response
Query object, on which you can continue chaining
Example
- Example
final res = await db
.collection('todos')
.orderBy('createdAt', OrderDirection.desc)
.get();
limit
Query collection.limit(int max)
Sets the maximum number of records to return.
Parameters
Maximum number of records to return
Response
Query object, on which you can continue chaining
Example
- Example
final res = await db.collection('todos').limit(10).get();
skip
Query collection.skip(int offset)
Sets the number of records to skip, commonly used for pagination.
Parameters
Number of records to skip (offset)
Response
Query object, on which you can continue chaining
Example
- Pagination Query
const pageSize = 10;
const pageNum = 2;
final res = await db
.collection('todos')
.orderBy('createdAt', OrderDirection.desc)
.skip((pageNum - 1) * pageSize)
.limit(pageSize)
.get();
print('Page $pageNum data: ${res.data}');
print('Offset: ${res.offset}, page size: ${res.limit}');
field
Query collection.field(Map<String, dynamic> projection)
Specifies the fields to return in the query. true means return, and false means do not return. The document reference doc also supports the field method.
Parameters
Field projection, e.g. {'title': true, 'content': false}
Response
Query object, on which you can continue chaining
Example
- Example
final res = await db
.collection('todos')
.where({'completed': false})
.field({'title': true, 'completed': true, 'content': false})
.get();
get
Future<DbGetResult> collection.get()
Future<DbGetResult> query.get()
Future<DbGetResult> doc.get()
Gets query results. Called on a collection reference, it performs an unconditional query; called on a Query, it returns the list of matching documents; called on a document reference, it returns a single document (data is an empty list when the document does not exist).
Parameters
No parameters
Response
Example
- Query Collection
- Query Single Document
final res = await db.collection('todos').get();
print('${res.data.length} records in total');
final res = await db.collection('todos').doc('doc-id').get();
if (res.data.isNotEmpty) {
print('Document content: ${res.data.first}');
}
count
Future<DbCountResult> collection.count()
Future<DbCountResult> query.count()
Counts the number of documents matching the conditions.
Parameters
No parameters
Response
Example
- Example
final res = await db
.collection('todos')
.where({'completed': false})
.count();
print('Number of incomplete tasks: ${res.total}');
update
Future<DbUpdateResult> query.update(Map<String, dynamic> data)
Future<DbUpdateResult> doc.update(Map<String, dynamic> data, {bool returnDoc = false})
Updates documents. Called on a Query, it batch-updates documents matching the conditions; called on a document reference, it performs a merge update on a single document, and returns the updated document when returnDoc is true.
Parameters
Update data. You can use db.command update operators (such as _.inc, _.set, _.push, etc.)
Supported only by document reference update. When true, returns the updated document. Defaults to false
Response
Example
- Update Single Document
- Batch Update
final _ = db.command;
final res = await db
.collection('todos')
.doc('doc-id')
.update({'count': _.inc(1), 'completed': true}, returnDoc: true);
print('Updated document: ${res.doc}');
final res = await db
.collection('todos')
.where({'completed': false})
.update({'archived': true});
print('${res.updated} records updated');
set
Future<DbUpdateResult> doc.set(Map<String, dynamic> data)
Sets document data (full replacement; creates the document if it does not exist).
Parameters
Full document data, which will completely replace the original document
Response
Example
- Example
final res = await db.collection('todos').doc('doc-id').set({
'title': 'Reset task',
'completed': false,
});
remove
Future<DbRemoveResult> query.remove()
Future<DbRemoveResult> doc.remove()
Deletes documents. Called on a Query, it batch-deletes documents matching the conditions; called on a document reference, it deletes a single document.
Parameters
No parameters
Response
Example
- Delete Single Document
- Batch Delete
final res = await db.collection('todos').doc('doc-id').remove();
print('${res.deleted} records deleted');
final res = await db
.collection('todos')
.where({'completed': true})
.remove();
print('${res.deleted} records deleted');
command
DbCommand get db.command
Gets the query/update command (corresponding to the JS SDK's db.command, commonly abbreviated as _). It supports comparison, logical, field/array, update, geolocation, and other operators.
Parameters
No parameters
Response
Command object, used to build query conditions and update operations
Example
- Comparison & Logical Operators
- Field & Array Operators
- Update Operators
final _ = db.command;
// eq / neq / gt / gte / lt / lte / inList / nin
await db.collection('todos').where({'age': _.gte(18)}).get();
// and / or / not / nor
await db.collection('todos').where({
'priority': _.or([_.eq('high'), _.eq('medium')]),
}).get();
final _ = db.command;
// exists / mod / all / elemMatch / size
await db.collection('todos').where({
'tags': _.all(['tech', 'study']),
'assignee': _.exists(true),
}).get();
final _ = db.command;
// set / remove / inc / mul / min / max / rename / bit
await db.collection('todos').doc('doc-id').update({
'count': _.inc(1),
'weight': _.mul(2),
'deprecatedField': _.remove(),
});
// Array updates: push / pop / shift / unshift / pull / pullAll / addToSet
await db.collection('todos').doc('doc-id').update({
'tags': _.push('new tag'),
'members': _.addToSet('user-1'),
});
aggregate
Aggregate collection.aggregate()
Gets an aggregation operation object. Chain aggregation stages and then call end() to execute. Supports match, group, sort, project, limit, skip, unwind, lookup, addFields, count, sample, bucket, bucketAuto, geoNear, replaceRoot, sortByCount, and custom stage.
Parameters
No parameters
Response
Aggregation operation object. Chain stages and then call end() to execute
Example
- Grouped Statistics
final res = await db
.collection('todos')
.aggregate()
.match({'completed': true})
.group({
'_id': '\$priority',
'total': {'\$sum': 1},
})
.sort({'total': -1})
.end();
print('Aggregation results: ${res.data}');
startTransaction
Future<Transaction> db.startTransaction()
Starts a transaction and returns a transaction object. Use the transaction object's collection to get a collection reference within the transaction to operate on, and finally call commit to commit or rollback to roll back.
Parameters
No parameters
Response
Example
- Transfer Transaction
final _ = db.command;
final transaction = await db.startTransaction();
try {
await transaction.collection('accounts').doc('a').update({'balance': _.inc(-100)});
await transaction.collection('accounts').doc('b').update({'balance': _.inc(100)});
await transaction.commit();
} catch (e) {
await transaction.rollback();
}
runCommands
Future<DbRunCommandsResult> db.runCommands({required List<Map<String, dynamic>> commands, String? transactionId})
Executes MongoDB-style database commands (in batch). Callable by administrators only.
Parameters
Array of command objects
Transaction ID (optional, executes all commands within the transaction)
Response
Example
- Example
final res = await db.runCommands(commands: [
{'find': 'todos', 'filter': {'completed': true}},
]);
print('Execution results: ${res.list}');
Geo
GeoNamespace get db.Geo
DbRegExp db.RegExp({required String regexp, String? options})
DbServerDate db.serverDate({int offset = 0})
Database helper types: the geolocation namespace Geo, the regular expression RegExp, and the server-side time serverDate.
Geosupportspoint,lineString,polygon,multiPoint,multiLineString, andmultiPolygon, used together with the operatorsgeoNear,geoWithin, andgeoIntersects.RegExpis used for fuzzy queries;optionssuch asimeans case-insensitive.serverDategenerates server-side time, whereoffsetis the offset in milliseconds.
Parameters
No parameters
Response
Geolocation namespace
Example
- Geolocation Query
- Regex Fuzzy Query
- Server-side Time
final _ = db.command;
// Query records within 5000 meters of the specified coordinates
final res = await db.collection('places').where({
'location': _.geoNear(
geometry: db.Geo.point(116.397, 39.908),
maxDistance: 5000,
),
}).get();
final res = await db.collection('todos').where({
'title': db.RegExp(regexp: 'study', options: 'i'),
}).get();
// Write the current server-side time
await db.collection('todos').add({
'title': 'Task',
'createdAt': db.serverDate(),
});
Data Model
getById
Future<GetByIdRes> app.data.model(collectionName).getById(String id)
Get a single record by ID.
Parameters
Record ID
Response
Example
- Example
final result = await app.data.model('users').getById('record-id-123');
if (result.isSuccess) {
final record = result.data?.record;
print('Record: ${record?.toJson()}');
} else {
print('Failed to get record: ${result.error!.message}');
}
get
Future<GetRes> app.data.model(collectionName).get([GetReq? params])
Query records with filters. Supports WHERE conditions, sorting, pagination, etc.
Parameters
Query parameters (optional)
Response
Example
- Basic Query
- Complex Query
final result = await app.data.model('users').get(
GetReq(
filter: 'age > 18',
sort: ['-createdAt'],
limit: 10,
),
);
if (result.isSuccess) {
for (final record in result.data?.records ?? []) {
print('User: ${record.toJson()}');
}
}
final result = await app.data.model('orders').get(
GetReq(
filter: 'status == "paid" && total > 100',
sort: ['-createdAt'],
limit: 20,
offset: 0,
),
);
list
Future<ModelFindManyResponse> app.models.list({
required String modelName,
Map<String, dynamic>? filter,
Map<String, dynamic>? select,
int? pageSize,
int? pageNumber,
bool? getCount,
List<Map<String, String>>? orderBy,
})
Query multiple records. Supports filter conditions, field selection, pagination, and sorting.
Parameters
Data model identifier
Filter condition, format: {'where': {'field': {'\$eq': 'value'}}}
Field selection, format: {'\$master': true} or {'field': true}
Page size, default 10
Page number, default 1
Whether to return total count
Sorting, up to 3 fields, format: [{'field': 'desc'}]
Response
Example
- Example
final result = await app.models.list(
modelName: 'user',
pageSize: 10,
pageNumber: 1,
getCount: true,
orderBy: [{'createdAt': 'desc'}],
filter: {'where': {'age': {'\$gt': 18}}},
);
if (result.isSuccess) {
print('Total: ${result.total}');
for (final record in result.records) {
print('Record: $record');
}
}
listSimple
Future<ModelFindManyResponse> app.models.listSimple({required String modelName, int? pageSize, int? pageNumber, bool? getCount})
Simple query for multiple records (GET request, only supports pagination parameters).
Parameters
Data model identifier
Page size
Page number, default 1
Whether to return total count, default false
Response
Example
- Example
final result = await app.models.listSimple(
modelName: 'user',
pageSize: 10,
pageNumber: 1,
getCount: true,
);
if (result.isSuccess) {
print('Total: ${result.total}');
for (final record in result.records) {
print('Record: $record');
}
}
create
Future<ModelCreateResponse> app.models.create({required String modelName, required Map<String, dynamic> data})
Create a single record.
Parameters
Data model identifier
Record data
Response
Example
- Example
final result = await app.models.create(
modelName: 'user',
data: {'name': 'Zhang San', 'age': 25, 'email': 'test@example.com'},
);
if (result.isSuccess) {
print('Created successfully, ID: ${result.id}');
} else {
print('Creation failed: ${result.message}');
}
createMany
Future<ModelCreateManyResponse> app.models.createMany({required String modelName, required List<Map<String, dynamic>> data})
Batch create records.
Parameters
Data model identifier
List of records to create
Response
Example
- Example
final result = await app.models.createMany(
modelName: 'user',
data: [
{'name': 'Zhang San', 'age': 25},
{'name': 'Li Si', 'age': 30},
],
);
if (result.isSuccess) {
print('Batch creation successful, ID list: ${result.idList}');
}
update
Future<ModelUpdateDeleteResponse> app.models.update({required String modelName, required Map<String, dynamic> filter, required Map<String, dynamic> data})
Update a single record.
Parameters
Data model identifier
Filter condition
Data to update
Response
Example
- Example
final result = await app.models.update(
modelName: 'user',
filter: {'where': {'_id': {'\$eq': '123'}}},
data: {'age': 26},
);
if (result.isSuccess) {
print('Update successful, ${result.count} record(s) updated');
}
updateMany
Future<ModelUpdateDeleteManyResponse> app.models.updateMany({required String modelName, required Map<String, dynamic> filter, required Map<String, dynamic> data})
Batch update records.
Parameters
Data model identifier
Filter condition
Data to update
Response
Example
- Example
final result = await app.models.updateMany(
modelName: 'user',
filter: {'where': {'age': {'\$lt': 18}}},
data: {'status': 'minor'},
);
if (result.isSuccess) {
print('Batch update successful, ${result.count} record(s) updated');
}
upsert
Future<ModelUpsertResponse> app.models.upsert({required String modelName, required Map<String, dynamic> filter, Map<String, dynamic>? create, Map<String, dynamic>? update})
Create or update a single record (Upsert). If a matching record is found, it will be updated; otherwise, a new record will be created.
Parameters
Data model identifier
Filter condition
Data to create when record does not exist
Data to update when record already exists
Response
Example
- Example
final result = await app.models.upsert(
modelName: 'user',
filter: {'where': {'email': {'\$eq': 'test@example.com'}}},
create: {'name': 'Zhang San', 'email': 'test@example.com', 'age': 25},
update: {'age': 26},
);
if (result.isSuccess) {
print('Upsert successful, ${result.count} record(s) changed');
if (result.id != null) {
print('New record ID: ${result.id}');
}
}
deleteById
Future<ModelUpdateDeleteResponse> app.models.deleteById({required String modelName, required String recordId})
Delete a single record by ID.
Parameters
Data model identifier
Record ID
Response
Example
- Example
final result = await app.models.deleteById(
modelName: 'user',
recordId: '123',
);
if (result.isSuccess) {
print('Deletion successful, ${result.count} record(s) changed');
}
deleteRecord
Future<ModelUpdateDeleteResponse> app.models.deleteRecord({required String modelName, required Map<String, dynamic> filter})
Delete a single record by condition.
Parameters
Data model identifier
Filter condition
Response
Example
- Example
final result = await app.models.deleteRecord(
modelName: 'user',
filter: {'where': {'_id': {'\$eq': '123'}}},
);
if (result.isSuccess) {
print('Deletion successful, ${result.count} record(s) changed');
}
deleteMany
Future<ModelUpdateDeleteManyResponse> app.models.deleteMany({required String modelName, required Map<String, dynamic> filter})
Batch delete records.
Parameters
Data model identifier
Filter condition
Response
Example
- Example
final result = await app.models.deleteMany(
modelName: 'user',
filter: {'where': {'status': {'\$eq': 'inactive'}}},
);
if (result.isSuccess) {
print('Batch deletion successful, ${result.count} record(s) changed');
}
mysqlCommand
Future<ModelMysqlCommandResponse> app.models.mysqlCommand({required String sqlTemplate, List<ModelMysqlParameter>? parameter, ModelMysqlConfig? config})
Execute MySQL commands. Supports parameterized queries.
Parameters
SQL statement, supports parameter placeholders {{ var }}
SQL parameter list
Execution config (timeout, preparedStatements, dbLinkName)
Response
Example
- Example
final result = await app.models.mysqlCommand(
sqlTemplate: 'select * from `users` where _id = {{ _id }}',
parameter: [
ModelMysqlParameter(key: '_id', type: 'STRING', value: '123'),
],
);
if (result.isSuccess) {
print('Execution result: ${result.executeResultList}');
}
Data Source Queries
getAggregateDataSourceList
Future<AggregateDataSourceListResponse> app.models.getAggregateDataSourceList({
List<String>? idList,
List<String>? nameList,
int? pageSize,
int? pageNumber,
bool? getCount,
List<Map<String, String>>? orderBy,
})
Query aggregate data source list (GET request, supports pagination and sorting).
Parameters
Data source ID list
Data source name list
Page size, default 10
Page number, default 1
Whether to return total count
Sorting, format: [{'field': 'desc'}]
Response
Example
- Example
final result = await app.models.getAggregateDataSourceList(
pageSize: 10,
pageNumber: 1,
getCount: true,
);
if (result.isSuccess) {
print('Total: ${result.count}');
for (final ds in result.rows) {
print('${ds.name}: ${ds.title} (type: ${ds.type})');
}
}
getDataSourceAggregateDetail
Future<DataSourceAggregateDetailResponse> app.models.getDataSourceAggregateDetail({
String? datasourceId,
String? dataSourceName,
String? viewId,
int? queryPublish,
bool? queryModelRelation,
String? dbInstanceType,
String? databaseTableName,
})
Query aggregate data source detail by conditions. datasourceId and dataSourceName cannot both be empty.
Parameters
Data source ID (cannot both be empty with dataSourceName)
Data source name (cannot both be empty with datasourceId)
View ID
Query published data source (0: preview, 1: published)
Whether to query relation
DB instance type
Database table name
Response
Example
- Example
final result = await app.models.getDataSourceAggregateDetail(
dataSourceName: 'user',
);
if (result.isSuccess) {
print('Schema: ${result.dataSource?.schema}');
print('Name: ${result.dataSource?.title}');
}
getDataSourceByTableName
Future<DataSourceByTableNameResponse> app.models.getDataSourceByTableName({required List<String> tableNames})
Query data source schema definition by database table name.
Parameters
Database table name list
Response
Example
- Example
final result = await app.models.getDataSourceByTableName(
tableNames: ['user_table', 'order_table'],
);
if (result.isSuccess) {
for (final info in result.dataSourceTableInfos) {
print('Table: ${info.tableName}, Data source: ${info.name}');
}
}
getBasicDataSourceList
Future<BasicDataSourceListResponse> app.models.getBasicDataSourceList({
List<String>? idList,
List<String>? nameList,
int? pageNum,
int? pageSize,
bool? queryAll,
List<DataSourceQueryFilter>? queryFilterList,
bool? onlyFlexDb,
})
Query basic data source list by conditions (POST request, supports filter conditions).
Parameters
Data source ID list
Data source name list
Page number, default 1
Page size, default 10
Whether to query all
Query filter list
Whether to query only flexdb type
Response
Example
- Example
final result = await app.models.getBasicDataSourceList(
pageSize: 10,
pageNum: 1,
queryFilterList: [
DataSourceQueryFilter(name: 'Type', values: ['database']),
],
);
if (result.isSuccess) {
print('Total: ${result.total}');
for (final ds in result.dataSourceList) {
print('${ds.name}: ${ds.title}');
}
}
getBasicDataSource
Future<BasicDataSourceResponse> app.models.getBasicDataSource({
String? datasourceId,
String? dataSourceName,
String? viewId,
int? queryPublish,
bool? queryModelRelation,
String? dbInstanceType,
String? databaseTableName,
})
Query basic data source info by conditions. datasourceId and dataSourceName cannot both be empty.
Parameters
Data source ID (cannot both be empty with dataSourceName)
Data source name (cannot both be empty with datasourceId)
View ID
Query published data source (0: preview, 1: published)
Whether to query relation
DB instance type
Database table name
Response
Example
- Example
final result = await app.models.getBasicDataSource(
dataSourceName: 'user',
);
if (result.isSuccess) {
print('Data source: ${result.dataSource?.name}');
print('Type: ${result.dataSource?.type}');
}
getSchemaList
Future<DataSourceSchemaListResponse> app.models.getSchemaList({List<String>? dataSourceNameList})
Query all data source schemas in the environment. If no parameters are provided, all schemas are returned.
Parameters
Data source name list (optional, query all if not provided)
Response
Example
- Example
final result = await app.models.getSchemaList(
dataSourceNameList: ['user', 'order'],
);
if (result.isSuccess) {
for (final rel in result.dataSourceRelationInfoList) {
print('${rel.name}: ${rel.title}');
}
}
getTableName
Future<DataSourceTableNameResponse> app.models.getTableName({String? dataSourceName})
Query the corresponding database table name by data source name.
Parameters
Data source name
Response
Example
- Example
final result = await app.models.getTableName(
dataSourceName: 'user',
);
if (result.isSuccess) {
print('Table name: ${result.tableName}');
print('Database type: ${result.dbType}');
}
MySQL Database
query
Future<MySqlResponse> app.mysql.query({required String table, String? schema, String? instance, MySqlQueryOptions? options})
Query MySQL data. Supports field selection, pagination, sorting, and filter conditions.
Supported filter operators: eq (equal), neq (not equal), gt (greater than), gte (greater than or equal), lt (less than), lte (less than or equal), like (fuzzy match), in (in list), is (null check)
Parameters
Table name
Database name
Database instance identifier (requires schema)
Query options
Response
Example
- Basic Query
- Filter Query
final result = await app.mysql.query(
table: 'users',
options: MySqlQueryOptions(
select: '*',
limit: 10,
offset: 0,
order: 'id.asc',
withCount: true,
),
);
if (result.isSuccess) {
print('Total: ${result.total}');
for (final row in result.data) {
print('Record: $row');
}
}
final result = await app.mysql.query(
table: 'users',
options: MySqlQueryOptions(
select: 'id,name,age',
filters: {'age': 'gt.18', 'name': 'like.%Zhang%'},
limit: 20,
),
);
if (result.isSuccess) {
print('Found ${result.data.length} records');
}
insert
Future<MySqlWriteResponse> app.mysql.insert({required String table, required dynamic data, String? schema, String? instance, bool? upsert, String? onConflict})
Insert data. Supports single and batch insert, as well as Upsert mode.
Parameters
Table name
Insert data, single Map or batch List<Map>
Database name
Database instance identifier
Whether to enable Upsert mode (default false)
Upsert conflict field
Response
Example
- Single Insert
- Batch Insert
final result = await app.mysql.insert(
table: 'users',
data: {'name': 'Zhang San', 'age': 25},
);
if (result.isSuccess) {
print('Insert successful');
}
final result = await app.mysql.insert(
table: 'users',
data: [
{'name': 'Zhang San', 'age': 25},
{'name': 'Li Si', 'age': 30},
],
);
if (result.isSuccess) {
print('Batch insert successful');
}
update (MySQL)
Future<MySqlWriteResponse> app.mysql.update({required String table, required Map<String, dynamic> data, required Map<String, String> filters, String? schema, String? instance})
Update MySQL data. WHERE condition is required.
Parameters
Table name
Data to update
WHERE condition (cannot be empty)
Database name
Database instance identifier
Response
Example
- Example
final result = await app.mysql.update(
table: 'users',
data: {'age': 26},
filters: {'name': 'eq.Zhang San'},
);
if (result.isSuccess) {
print('Update successful');
} else {
print('Update failed: ${result.message}');
}
delete (MySQL)
Future<MySqlWriteResponse> app.mysql.delete({required String table, required Map<String, String> filters, String? schema, String? instance})
Delete MySQL data. WHERE condition is required.
Parameters
Table name
WHERE condition (cannot be empty)
Database name
Database instance identifier
Response
Example
- Example
final result = await app.mysql.delete(
table: 'users',
filters: {'name': 'eq.Zhang San'},
);
if (result.isSuccess) {
print('Delete successful');
}
count
Future<MySqlCountResponse> app.mysql.count({required String table, Map<String, String>? filters, String? schema, String? instance})
Count MySQL data records.
Parameters
Table name
Filter conditions
Database name
Database instance identifier
Response
Example
- Example
final result = await app.mysql.count(
table: 'users',
filters: {'age': 'gt.18'},
);
if (result.isSuccess) {
print('Matching records: ${result.count}');
} else {
print('Count failed: ${result.message}');
}
Cloud Functions
callFunction
Future<FunctionResponse> app.callFunction({
required String name,
FunctionType? type,
Map<String, dynamic>? data,
HttpMethod? method,
String? path,
Map<String, String>? header,
bool? parse,
})
Call cloud function. Supports both basic cloud functions and function-type cloud run.
Parameters
Function/service name
Call type: FunctionType.function (default) / FunctionType.cloudrun
Request data
HTTP method (only valid for cloudrun type, default POST)
HTTP path (only valid for cloudrun type, default /)
HTTP headers (only valid for cloudrun type)
Whether to parse return object (only valid for function type, default true)
Response
Example
- Call Basic Cloud Function
- Call Function-type Cloud Run
final result = await app.callFunction(
name: 'myFunction',
data: {'action': 'getUserList', 'pageSize': 10},
);
if (result.isSuccess) {
print('Execution result: ${result.result}');
} else {
print('Execution failed: ${result.message}');
}
final result = await app.callFunction(
name: 'myService',
type: FunctionType.cloudrun,
method: HttpMethod.post,
path: '/api/users',
data: {'name': 'Zhang San'},
header: {'X-Custom-Header': 'value'},
);
if (result.isSuccess) {
print('Execution result: ${result.result}');
}
Cloud Run
callContainer
Future<CloudRunResponse> app.callContainer({
required String name,
HttpMethod? method,
String? path,
Map<String, String>? header,
Map<String, dynamic>? data,
})
Call cloud run container service. Supports custom HTTP method, path, and headers.
Parameters
Cloud run service name
HTTP request method (default GET)
HTTP request path (default /)
HTTP request headers
HTTP request body
Response
Example
- Example
final result = await app.callContainer(
name: 'my-service',
method: HttpMethod.post,
path: '/api/data',
data: {'key': 'value'},
header: {'X-Custom': 'header'},
);
if (result.isSuccess) {
print('Response data: ${result.result}');
} else {
print('Request failed: ${result.message}');
}
APIs
apis[name]
ApiMethodProxy app.apis[String apiName]
Call API gateway interface. Supports accessing API proxy objects via subscript operator for chained calls. Supports GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH methods.
Parameters
API name
Response
API method proxy object, supports chained calls
API response
Example
- Chained Call
- Direct Call callApi
// POST request
final result = await app.apis['myApi'].post(
path: '/users',
body: {'name': 'Zhang San', 'age': 25},
);
if (result.isSuccess) {
print('Response data: ${result.data}');
}
// GET request
final getResult = await app.apis['myApi'].get(path: '/users/123');
// PUT request
final putResult = await app.apis['myApi'].put(
path: '/users/123',
body: {'name': 'Li Si'},
);
// DELETE request
final deleteResult = await app.apis['myApi'].delete(path: '/users/123');
final result = await app.apis.callApi(CallApiOptions(
name: 'myApi',
method: 'POST',
path: '/users',
body: {'name': 'test'},
headers: {'X-Custom': 'value'},
));
if (result.isSuccess) {
print('Response: ${result.data}');
}
Cloud Storage
Cloud Storage module provides file upload, download, delete, copy, move and other operations.
Initialization
final app = await CloudBase.init(
env: 'your-env-id',
accessKey: 'your-access-key',
);
final storage = app.storage.from();
upload
Future<StorageResponse<StorageUploadResult>> storage.upload(
String path,
List<int> fileData, {
StorageUploadOptions? options,
})
Upload file to cloud storage. This method will first get upload info, then upload file to COS, and finally return fileID.
Parameters
Cloud storage relative path, e.g. `images/photo.jpg`.
File byte data.
Upload options.
Response
Return data
Error message.
Example
- Upload File
- Upload Options
import 'package:cloudbase_flutter/cloudbase_flutter.dart';
import 'package:image_picker/image_picker.dart';
final app = await CloudBase.init(
env: 'your-env-id',
accessKey: 'your-access-key',
);
final storage = app.storage.from();
// Pick image and upload
Future<void> uploadImage() async {
final picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
if (image == null) return;
final fileBytes = await image.readAsBytes();
final result = await storage.upload(
'images/${image.name}',
fileBytes,
StorageUploadOptions(
contentType: 'image/jpeg',
cacheControl: 'max-age=3600',
),
);
if (result.isSuccess) {
print('Upload successful: ${result.data?.id}');
print('File path: ${result.data?.path}');
} else {
print('Upload failed: ${result.error?.message}');
}
}
// Do not overwrite existing file
final result = await storage.upload(
'images/photo.jpg',
fileBytes,
StorageUploadOptions(upsert: false),
);
// Custom metadata
final result = await storage.upload(
'images/photo.jpg',
fileBytes,
StorageUploadOptions(
metadata: {'userId': '123', 'category': 'avatar'},
),
);
getUploadInfo
Future<StorageResponse<List<StorageUploadInfo>>> storage.getUploadInfo(
List<String> paths,
)
Get file upload info. Returns upload URL and other info for client to directly upload files to COS.
Parameters
File path list (cloud storage relative path).
Response
Upload info list.
Error message.
Example
- Get Upload Info
final result = await storage.getUploadInfo([
'images/photo.jpg',
'documents/report.pdf',
]);
if (result.isSuccess) {
for (final info in result.data!) {
print('Path: ${info.path}');
print('Upload URL: ${info.uploadUrl}');
print('File ID: ${info.fileId}');
}
}
getDownloadUrls
Future<StorageResponse<List<StorageDownloadInfo>>> storage.getDownloadUrls(
List<String> fileIds, {
int? expiresIn,
})
Get file download URLs.
Parameters
File ID list (full cloudObjectId, e.g. `cloud://envId.xxx/path/file.jpg`).
Reserved parameter, current API does not support custom expiration time.
Response
Download info list.
Error message.
Example
- Get Download URLs
final result = await storage.getDownloadUrls([
'cloud://envId.xxx/images/photo.jpg',
'cloud://envId.xxx/documents/report.pdf',
]);
if (result.isSuccess) {
for (final info in result.data!) {
if (info.isSuccess) {
print('Download URL: ${info.downloadUrl}');
} else {
print('Failed to get: ${info.message}');
}
}
}
createSignedUrl
Future<StorageResponse<String>> storage.createSignedUrl(
String fileId,
int expiresIn,
)
Create signed URL (temporary access link).
Parameters
Full fileID.
Expiration time (seconds).
Response
Signed URL.
Error message.
Example
- Create Signed URL
final result = await storage.createSignedUrl(
'cloud://envId.xxx/images/photo.jpg',
3600, // 1 hour expiration
);
if (result.isSuccess) {
print('Signed URL: ${result.data}');
}
createSignedUrls
Future<StorageResponse<List<StorageDownloadInfo>>> storage.createSignedUrls(
List<String> fileIds,
int expiresIn,
)
Batch create signed URLs.
Parameters
Full fileID list.
Expiration time (seconds).
Response
Download info list.
Error message.
Example
- Batch Create Signed URLs
final result = await storage.createSignedUrls(
[
'cloud://envId.xxx/images/photo1.jpg',
'cloud://envId.xxx/images/photo2.jpg',
],
3600,
);
if (result.isSuccess) {
for (final info in result.data!) {
print('${info.fileId}: ${info.downloadUrl}');
}
}
remove
Future<StorageResponse<List<StorageDeleteResult>>> storage.remove(
List<String> fileIds,
)
Delete files.
Parameters
File ID list to delete (full fileID).
Response
Delete result list.
Error message.
Example
- Delete Files
final result = await storage.remove([
'cloud://envId.xxx/images/photo.jpg',
'cloud://envId.xxx/documents/report.pdf',
]);
if (result.isSuccess) {
for (final item in result.data!) {
if (item.isSuccess) {
print('Delete successful: ${item.fileId}');
} else {
print('Delete failed: ${item.fileId} - ${item.message}');
}
}
}
copy
Future<StorageResponse<StorageCopyResult>> storage.copy(
String fromPath,
String toPath, {
bool overwrite = true,
})
Copy file.
Parameters
Source file path (relative path).
Target file path (relative path).
Whether to overwrite if target exists, default `true`.
Response
Copy result.
Error message.
Example
- Copy File
final result = await storage.copy(
'images/photo.jpg',
'images/backup/photo.jpg',
);
if (result.isSuccess) {
print('Copy successful: ${result.data?.cloudObjectId}');
} else {
print('Copy failed: ${result.error?.message}');
}
copyBatch
Future<StorageResponse<List<StorageCopyResult>>> storage.copyBatch(
List<Map<String, dynamic>> items,
)
Batch copy files.
Parameters
Copy item list, each item contains `srcPath` and `dstPath`.
Response
Copy result list.
Error message.
Example
- Batch Copy Files
final result = await storage.copyBatch([
{'srcPath': 'images/photo1.jpg', 'dstPath': 'backup/photo1.jpg'},
{'srcPath': 'images/photo2.jpg', 'dstPath': 'backup/photo2.jpg'},
]);
if (result.isSuccess) {
for (final item in result.data!) {
if (item.isSuccess) {
print('Copy successful: ${item.cloudObjectId}');
}
}
}
move
Future<StorageResponse<StorageCopyResult>> storage.move(
String fromPath,
String toPath, {
bool overwrite = true,
})
Move file (implemented by copy + removeOriginal).
Parameters
Source file path (relative path).
Target file path (relative path).
Whether to overwrite if target exists, default `true`.
Response
Move result.
Error message.
Example
- Move File
final result = await storage.move(
'images/old.jpg',
'images/new.jpg',
);
if (result.isSuccess) {
print('Move successful: ${result.data?.cloudObjectId}');
} else {
print('Move failed: ${result.error?.message}');
}
Storage Related Types
StorageUploadOptions
Upload options:
| Parameter | Type | Description |
|---|---|---|
cacheControl | String? | Cache control, e.g. max-age=3600 |
contentType | String? | File MIME type, e.g. image/jpeg |
metadata | Map<String, dynamic>? | Custom metadata |
upsert | bool | Whether to overwrite existing file, default true |
StorageUploadResult
Upload result:
| Parameter | Type | Description |
|---|---|---|
id | String? | CloudBase fileID |
path | String? | Upload path |
fullPath | String? | File full path |
StorageUploadInfo
Upload info:
| Parameter | Type | Description |
|---|---|---|
path | String? | File path |
uploadUrl | String? | Upload URL |
token | String? | Upload token |
authorization | String? | Upload authorization |
fileId | String? | File ID |
cosFileId | String? | COS file ID |
code | String? | Error code |
message | String? | Error message |
StorageDownloadInfo
Download info:
| Parameter | Type | Description |
|---|---|---|
fileId | String? | File ID |
downloadUrl | String? | Download URL |
code | String? | Error code (on partial failure) |
message | String? | Error message (on partial failure) |
StorageDeleteResult
Delete result:
| Parameter | Type | Description |
|---|---|---|
fileId | String? | File ID |
code | String? | Error code (on partial failure) |
message | String? | Error message (on partial failure) |
StorageCopyResult
Copy result:
| Parameter | Type | Description |
|---|---|---|
cloudObjectId | String? | Cloud file ID of copied object |
code | String? | Error code (on partial failure) |
message | String? | Error message (on partial failure) |
StorageResponse<T>
Storage response:
| Parameter | Type | Description |
|---|---|---|
data | T? | Response data |
error | StorageError? | Error message |
StorageError
Storage error:
| Parameter | Type | Description |
|---|---|---|
code | String? | Error code |
message | String? | Error message |
requestId | String? | Request ID |
Changelog
1.2.0 (2026-07-24)
- Add NoSQL Database module (
CloudBaseDatabase) with JS-SDK-style chainable APIdb.collection().doc()document references- Chainable query:
where/orderBy/limit/skip/field - CRUD:
add(single & batch),get,count,update,set,remove - Query/update commands via
db.command: comparison (eq/gt/gte/lt/lte/neq/in/nin), logic (and/or/not/nor), update operators (set/inc/mul/remove/push/pull/pop/shift/unshift/addToSet/rename/max/min) - Aggregation pipeline via
collection().aggregate()...end() - Transactions via
db.startTransaction()withcommit/rollback - Geo types (
GeoPoint/GeoLineString/GeoPolygon/GeoMultiPoint/GeoMultiLineString/GeoMultiPolygon) and geo queries RegExp,serverDatehelpers and automatic EJSON encode/decode (e.g.DateTime)- MongoDB-style commands via
runCommands
1.1.0 (2026-07-01)
- Add Cloud Storage module (
CloudBaseStorage)- Upload files to cloud storage with upload info and direct COS upload
- Get signed download URLs (single and batch)
- Delete files (batch)
- Copy files (single and batch)
- Move/rename files
- Get upload info for client-side direct upload
1.0.9 (2026-06-30)
- Add
X-SDK-Versionheader (@cloudbase/flutter-sdk/<version>) to all HTTP requests for platform identification - Add version management tooling (
tool/update_version.dart) to auto-sync version frompubspec.yaml - Add
CONTRIBUTING.mdwith release workflow documentation - Improve HTTP client to support List request body (for storage APIs)
1.0.8 (2026-05-06)
- Fix
UserProfile.toUser()incorrectly falling back tousername(phone number) whenemailis null, which caused reauthentication to send an invalid email format to the server - Fix
reauthenticate()to properly distinguish between empty string and valid email, ensuring phone-only users use phone number for verification instead of invalid email
1.0.7 (2026-03-11)
- Add
shouldCreateUseroption tosignInWithOtpfor auto-registration when user does not exist - Refactor internal signup logic into reusable
_signUpAndSaveSessionmethod
1.0.6 (2026-03-05)
- Add MySQL module (
CloudBaseMySQL)- Direct SQL query execution
- Transaction support (begin, commit, rollback)
- Database/table management operations
- Add example code for MySQL modules
- Add unit tests for MySQL modules
1.0.5 (2026-03-05)
- Add Data Model module (
CloudBaseDataModel)- CRUD operations with filter, select, orderBy, expand support
- Batch create/update/delete operations
- Upsert support
- Raw MySQL command execution
- DataSource query APIs (aggregate list, detail, schema, table name)
- Refactor HTTP client with token auto-refresh and improved documentation
- Add example code for Data Model
- Add unit tests for Data Model
1.0.4 (2026-01-16)
- Add example code
1.0.3 (2026-01-16)
- Update README documentation
1.0.2 (2026-01-15)
- Fix HTTP client not handling empty token string correctly
1.0.1 (2026-01-15)
- Improve README documentation with complete authentication API usage
1.0.0 (2026-01-15)
- Initial release
- Authentication module (
CloudBaseAuth)- Email/phone registration and sign-in
- Password sign-in
- OTP verification sign-in
- OAuth third-party sign-in
- IdToken sign-in
- Custom ticket sign-in
- Anonymous sign-in
- Session management (get, refresh, set)
- User information management
- Identity provider binding/unbinding
- Password reset
- Cloud Functions module (
CloudBaseFunctions)- Basic cloud function invocation
- Function-based cloud run invocation
- Cloud Run module (
CloudBaseCloudRun)- HTTP methods support (GET/POST/PUT/DELETE)
- Custom request headers
- API Gateway module (
CloudBaseApis)- Chained calls
- Multiple HTTP methods support
- Captcha module (
CloudBaseCaptcha)- Image captcha
- Custom captcha handler
- Built-in captcha dialog