A Flutter SDK for interacting with the Vendure e-commerce framework's GraphQL API. This SDK simplifies the process of connecting to Vendure and performing common operations like authentication, adding items to the cart, and more.
Thanks to ZikZak AI for sponsoring this project!
ZikZak AI is an AI-Powered Price Comparison app that you scan barcodes, and discover amazing savings instantly. Your personal shopping assistant that never sleeps.
- Authenticate users
- Add items to the cart
- Manage orders
- Manage customers
- Access catalog and system information
- Extendable to support custom GraphQL operations
- Global enum conversion toggles:
VendureUtils.convertQueryEnumsandVendureUtils.convertMutationEnums(both default totrue). UseVendureUtils.setConvertEnums({bool? queryEnums, bool? mutationEnums})to change them globally. - Convenience re-export: The utilities are available via a short import (
package:vendure/vendure_utils.dart) and are also exported frompackage:vendure/vendure.dartfor easy access toVendureUtils.
Add the following to your pubspec.yaml:
dependencies:
vendure: ^2.8.0Note: Starting with v2.8.0 the SDK exposes global flags to control enum conversion:
- Toggle query/response enum normalization with
VendureUtils.setConvertEnums(queryEnums: true|false). - Toggle mutation input enum normalization with
VendureUtils.setConvertEnums(mutationEnums: true|false).
You can import the helper utilities using the short path:
import 'package:vendure/vendure_utils.dart';
// or import the main library:
import 'package:vendure/vendure.dart';First, create an instance of the Vendure class:
import 'package:vendure/vendure.dart';
void main() async {
// Initialize with Native Auth
Vendure vendure = await Vendure.initializeWithNativeAuth(
endpoint: 'http://localhost:3000/shop-api',
username: 'your-username',
password: 'your-password',
sessionDuration: const Duration(days: 1),
customFieldsConfig: {
'User': ['os'],
'Order': ['giftMessage']
},
);
// Initialize with Firebase Auth
vendure = await Vendure.initializeWithFirebaseAuth(
endpoint: 'http://localhost:3000/shop-api',
uid: '8o6CuL3vvceCwjnSxtCTp08vEMr2',
jwt: 'your-jwt-token',
sessionDuration: const Duration(hours: 1),
customFieldsConfig: {
'User': ['os'],
'Order': ['giftMessage']
},
languageCode: 'TR',
channelToken: 'your-channel-token'
);
// Initialize with Token
vendure = await Vendure.initialize(
endpoint: 'http://localhost:3000/shop-api',
token: '9a3d1222ed018701fdd8a7484a7299977507787f5bb22bec898e67939ee453169f8',
);
// Initialize with Custom Auth
vendure = await Vendure.initializeWithCustomAuth(
endpoint: 'http://localhost:3000/shop-api',
fetchToken: (params) async {
// Implement your custom token fetching logic here
return 'custom-token';
},
tokenParams: {
'customParam1': 'value1',
'customParam2': 'value2',
},
sessionDuration: const Duration(days: 1),
customFieldsConfig: {
'User': ['os'],
'Order': ['giftMessage']
},
);
// Initialize with API Key (machine-to-machine auth)
vendure = await Vendure.initializeWithApiKey(
endpoint: 'http://localhost:3000/shop-api',
apiKey: 'your-api-key',
apiKeyHeaderKey: 'vendure-api-key', // optional, defaults to 'vendure-api-key'
);
// Initialize with a guest session (no auth, creates an anonymous order)
vendure = await Vendure.initialize(
endpoint: 'http://localhost:3000/shop-api',
useVendureGuestSession: true,
languageCode: 'en',
channelToken: 'your-channel-token',
);
// Use the vendure instance for various operations
Vendure vendure = Vendure.instance;
// Update the authentication token at runtime (e.g., after refresh)
Vendure.setAuthToken('your-new-token');
// Update runtime configuration
Vendure.setLanguageCode('tr');
Vendure.setChannelToken('your-channel-token');
Vendure.setApiKey('your-api-key');
// Clean up when done (releases the singleton and HTTP client)
Vendure.destroy();
}Firebase updates tokens every hour. You should listen and update Vendure client with new token:
Future<void> initializaRepository() async {
FirebaseAuth.instance.idTokenChanges().listen((event) async {
if (event == null) return;
String? idToken = await event.getIdToken();
if (idToken == null) {
throw Exception('idToken is null');
}
// Instead of reinitializing, just update the token:
Vendure.setAuthToken(idToken);
});
}Future<void> addItem() async {
try {
var result = await vendure.order.addItemToOrder(
productVariantId: 79,
quantity: 1,
);
print('Item added: ${result.toJson()}');
} catch (e) {
print('Error adding item to cart: $e');
}
}Future<void> setShippingAddress() async {
try {
var result = await vendure.order.setOrderShippingAddress(
input: CreateAddressInput(
fullName: 'Abraham Lincoln',
streetLine1: '1600 Pennsylvania Avenue NW',
city: 'Washington',
postalCode: '20500',
countryCode: 'US',
),
);
print('Shipping address set: ${result.toJson()}');
} catch (e) {
print('Error setting shipping address: $e');
}
}Future<void> setBillingAddress() async {
try {
var result = await vendure.order.setOrderBillingAddress(
input: CreateAddressInput(
fullName: 'Abraham Lincoln',
streetLine1: '1600 Pennsylvania Avenue NW',
city: 'Washington',
postalCode: '20500',
countryCode: 'US',
),
);
print('Billing address set: ${result.toJson()}');
} catch (e) {
print('Error setting billing address: $e');
}
}Future<void> getActiveOrder() async {
try {
var result = await vendure.order.getActiveOrder();
print('Active order: ${result.toJson()}');
} catch (e) {
print('Error getting active order: $e');
}
}Future<void> addPayment() async {
try {
var result = await vendure.order.addPaymentToOrder(
input: PaymentInput(
method: 'stripe-payment',
metadata: {'stripeCheckoutSessionId': 'xyz'},
),
);
print('Payment added: ${result.toJson()}');
} catch (e) {
print('Error adding payment to order: $e');
}
}Future<void> getOrderByCode(String code) async {
try {
var result = await vendure.order.getOrderByCode(code: code);
print('Order by code: ${result.toJson()}');
} catch (e) {
print('Error getting order by code: $e');
}
}Future<void> getPaymentMethods() async {
try {
var result = await vendure.order.getPaymentMethods();
print('Payment methods: ${result.map((e) => e.toJson()).toList()}');
} catch (e) {
print('Error getting payment methods: $e');
}
}Future<void> getShippingMethods() async {
try {
var result = await vendure.order.getShippingMethods();
print('Shipping methods: ${result.map((e) => e.toJson()).toList()}');
} catch (e) {
print('Error getting shipping methods: $e');
}
}Future<void> setCustomerForOrder() async {
try {
var result = await vendure.order.setCustomerForOrder(
input: CreateCustomerInput(
emailAddress: 'customer@example.com',
firstName: 'John',
lastName: 'Doe',
),
);
print('Customer set for order: ${result.toJson()}');
} catch (e) {
print('Error setting customer for order: $e');
}
}Future<void> setOrderShippingMethod({
required String shippingMethodId,
List<String>? additionalMethodIds }) async {
try {
var result = await vendure.order.setOrderShippingMethod(
shippingMethodId: shippingMethodId, additionalMethodIds: additionalMethodIds);;
print('Customer set for order: ${result.toJson()}');
} catch (e) {
print('Error setting customer for order: $e');
}
}Future<void> adjustOrderLine(String orderLineId, int quantity) async {
try {
var result = await vendure.order.adjustOrderLine(
orderLineId: orderLineId,
quantity: quantity,
);
print('Order line adjusted: ${result.toJson()}');
} catch (e) {
print('Error adjusting order line: $e');
}
}Future<void> removeOrderLine(String orderLineId) async {
try {
var result = await vendure.order.removeOrderLine(orderLineId: orderLineId);
print('Order line removed: ${result.toJson()}');
} catch (e) {
print('Error removing order line: $e');
}
}Future<void> applyCouponCode(String couponCode) async {
try {
var result = await vendure.order.applyCouponCode(couponCode: couponCode);
print('Coupon code applied: ${result.toJson()}');
} catch (e) {
print('Error applying coupon code: $e');
}
}Future<void> removeCouponCode(String couponCode) async {
try {
var result = await vendure.order.removeCouponCode(couponCode: couponCode);
print('Coupon code removed: ${result.toJson()}');
} catch (e) {
print('Error removing coupon code: $e');
}
}Future<void> transitionOrderToState(String state) async {
try {
var result = await vendure.order.transitionOrderToState(state: state);
print('Order transitioned to state: ${result.toJson()}');
} catch (e) {
print('Error transitioning order to state: $e');
}
}Future<void> setOrderCustomFields(Map<String, dynamic> customFields) async {
try {
var result = await vendure.order.setOrderCustomFields(
input: UpdateOrderInput(customFields: customFields),
);
print('Order custom fields set: ${result.toJson()}');
} catch (e) {
print('Error setting order custom fields: $e');
}
}Future<void> getCollections() async {
try {
var result = await vendure.catalog.getCollections(
options: CollectionListOptions(topLevelOnly: true),
);
print('Collections: ${result.toJson()}');
} catch (e) {
print('Error getting collections: $e');
}
}Future<void> getCollectionById(int id) async {
try {
var result = await vendure.catalog.getCollectionById(id: id);
print('Collection: ${result.toJson()}');
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getCollectionBySlug(String slug) async {
try {
var result = await vendure.catalog.getCollectionBySlug(slug: slug);
print('Collection: ${result.toJson()}');
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getCollectionsWithParentChildren() async {
try {
CollectionListOptions options = CollectionListOptions(
topLevelOnly: false,
filter: CollectionFilterParameter(
parentId: IdOperators(eq: '2'),
),
);
var result = await vendure.catalog
.getCollectionListWithParentChildren(options: options);
for (var collection in result.items) {
print('Collection: ${result.toJson()}');
if (collection.children.isNotEmpty) {
print(collection.children.first.slug);
}
}
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getCollectionWithParentChildren(String id) async {
try {
var result = await vendure.catalog
.getCollectionWithParentChildren(id:id);
for (var collection in result.items) {
print('Collection: ${result.toJson()}');
if (collection.children.isNotEmpty) {
print(collection.children.first.slug);
}
}
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getCollectionWithParent(String id) async {
try {
var result = await vendure.catalog
.getCollectionWithParent(id:id);
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getCollectionWithChildren(String id) async {
try {
var result = await vendure.catalog
.getCollectionWithChildren(id:id);
} catch (e) {
print('Error getting collection: $e');
}
}Future<void> getProducts() async {
try {
var result = await vendure.catalog.getProducts(
options: ProductListOptions(take: 1),
);
print('Products: ${result.toJson()}');
} catch (e) {
print('Error getting products: $e');
}
}Future<void> getProductById(int id) async {
try {
var result = await vendure.catalog.getProductById(id: id);
print('Product: ${result.toJson()}');
} catch (e) {
print('Error getting product: $e');
}
}Future<void> getProductBySlug(String slug) async {
try {
var result = await vendure.catalog.getProductBySlug(slug: slug);
print('Product: ${result.toJson()}');
} catch (e) {
print('Error getting product: $e');
}
}Future<void> searchCatalog(String term) async {
try {
var result = await vendure.catalog.searchCatalog(
input: SearchInput(term: term),
);
print('Search results: ${result.toJson()}');
} catch (e) {
print('Error searching catalog: $e');
}
}Future<void> getActiveCustomer() async {
try {
var result = await vendure.customer.getActiveCustomer();
print('Active customer: ${result.toJson()}');
} catch (e) {
print('Error getting active customer: $e');
}
}Future<void> getCurrentUser() async {
try {
var result = await vendure.customer.getCurrentUser();
print('Current user: ${result.toJson()}');
} catch (e) {
print('Error getting current user: $e');
}
}Future<void> getActiveChannel() async {
try {
var result = await vendure.customer.getActiveChannel();
print('Active channel: ${result.toJson()}');
} catch (e) {
print('Error getting active channel: $e');
}
}Future<void> updateCustomer(String firstName, String lastName) async {
try {
var result = await vendure.customer.updateCustomer(
input: UpdateCustomerInput(
firstName: firstName,
lastName: lastName,
),
);
print('Customer updated: ${result.toJson()}');
} catch (e) {
print('Error updating customer: $e');
}
}Future<void> createCustomerAddress() async {
try {
var result = await vendure.customer.createCustomerAddress(
input: CreateAddressInput(
fullName: 'John Doe',
streetLine1: '123 Main St',
city: 'Springfield',
postalCode: '12345',
countryCode: 'US',
),
);
print('Customer address created: ${result.toJson()}');
} catch (e) {
print('Error creating customer address: $e');
}
}Future<void> updateCustomerAddress(String addressId) async {
try {
var result = await vendure.customer.updateCustomerAddress(
input: UpdateAddressInput(
id: addressId,
fullName: 'John Doe Updated',
streetLine1: '456 Main St',
city: 'Springfield',
postalCode: '12345',
countryCode: 'US',
),
);
print('Customer address updated: ${result.toJson()}');
} catch (e) {
print('Error updating customer address: $e');
}
}Future<void> deleteCustomerAddress(String addressId) async {
try {
var result = await vendure.customer.deleteCustomerAddress(id: addressId);
print('Customer address deleted: ${result.toJson()}');
} catch (e) {
print('Error deleting customer address: $e');
}
}Future<void> getAvailableCountries() async {
try {
var result = await vendure.system.getAvailableCountries();
print('Available countries: ${result.toJson()}');
} catch (e) {
print('Error getting available countries: $e');
}
}Future<void> getFacets() async {
try {
var result = await vendure.system.getFacets(
options: FacetListOptions(take: 1),
);
print('Facets: ${result.toJson()}');
} catch (e) {
print('Error getting facets: $e');
}
}Future<void> getFacet(int id) async {
try {
var result = await vendure.system.getFacet(id: id);
print('Facet: ${result.toJson()}');
} catch (e) {
print('Error getting facet: $e');
}
}Future<void> authenticate(String username, String password) async {
try {
var result = await vendure.auth.authenticate(
username: username,
password: password,
);
print('Authentication result: ${result.toJson()}');
} catch (e) {
print('Error authenticating: $e');
}
}Future<void> authenticateFirebase(String uid, String jwt) async {
try {
var result = await vendure.auth.authenticateFirebase(
uid: uid,
jwt: jwt,
);
print('Firebase Authentication result: ${result.toJson()}');
} catch (e) {
print('Error authenticating with Firebase: $e');
}
}Future<void> getToken(String username, String password) async {
try {
var token = await vendure.auth.getToken(
username: username,
password: password,
);
print('Token: $token');
} catch (e) {
print('Error getting token: $e');
}
}Future<void> getTokenFirebase(String uid, String jwt) async {
try {
var token = await vendure.auth.getTokenFirebase(
uid: uid,
jwt: jwt,
);
print('Firebase Token: $token');
} catch (e) {
print('Error getting Firebase token: $e');
}
}Future<void> login(String username, String password) async {
try {
var result = await vendure.auth.login(
username: username,
password: password,
rememberMe: true,
);
print('Login result: ${result.toJson()}');
} catch (e) {
print('Error logging in: $e');
}
}Future<void> logout() async {
try {
var result = await vendure.auth.logout();
print('Logout result: ${result.toJson()}');
} catch (e) {
print('Error logging out: $e');
}
}Future<void> registerCustomerAccount() async {
try {
var result = await vendure.auth.registerCustomerAccount(
input: RegisterCustomerInput(
emailAddress: 'test@example.com',
firstName: 'John',
lastName: 'Doe',
),
);
print('Register customer account result: ${result.toJson()}');
} catch (e) {
print('Error registering customer account: $e');
}
}Future<void> verifyCustomerAccount(String token, String? password) async {
try {
var result = await vendure.auth.verifyCustomerAccount(
token: token,
password: password,
);
print('Verify customer account result: ${result.toJson()}');
} catch (e) {
print('Error verifying customer account: $e');
}
}Future<void> updateCustomerPassword(String currentPassword, String newPassword) async {
try {
var result = await vendure.auth.updateCustomerPassword(
currentPassword: currentPassword,
newPassword: newPassword,
);
print('Update customer password result: ${result.toJson()}');
} catch (e) {
print('Error updating customer password: $e');
}
}Future<void> requestUpdateCustomerEmailAddress(String password, String newEmailAddress) async {
try {
var result = await vendure.auth.requestUpdateCustomerEmailAddress(
password: password,
newEmailAddress: newEmailAddress,
);
print('Request update customer email address result: ${result.toJson()}');
} catch (e) {
print('Error requesting update customer email address: $e');
}
}Future<void> updateCustomerEmailAddress(String token) async {
try {
var result = await vendure.auth.updateCustomerEmailAddress(
token: token,
);
print('Update customer email address result: ${result.toJson()}');
} catch (e) {
print('Error updating customer email address: $e');
}
}Future<void> requestPasswordReset(String emailAddress) async {
try {
var result = await vendure.auth.requestPasswordReset(
emailAddress: emailAddress,
);
print('Request password reset result: ${result.toJson()}');
} catch (e) {
print('Error requesting password reset: $e');
}
}Future<void> resetPassword(String token, String password) async {
try {
var result = await vendure.auth.resetPassword(
token: token,
password: password,
);
print('Reset password result: ${result.toJson()}');
} catch (e) {
print('Error resetting password: $e');
}
}You can also perform custom operations using the custom method.
Future<void> customMutation() async {
try {
const String myCustomMutation = r'''
type CustomMutationInput{
customField: String!
}
mutation CustomMutation($input:CustomMutationInput) {
customMethod(input:$input){
__typename
{
customField
}
}
}
''';
var variables = {"customField": 'your-custom-value'};
final result = await vendure.custom.mutate(
myCustomMutation,
variables,
CustomMutationResult.fromJson,
expectedDataType: 'custom',
);
print('Custom result: ${result.customField}');
} catch (e) {
print('Error custom mutation: $e');
}
}Future<void> customQuery() async {
try {
const String myCustomQuery = r'''
type CustomQueryInput{
customField: String!
}
query CustomQuery($input:CustomQueryInput) {
customMethod(input:$input){
__typename
{
customField
}
}
}
''';
var variables = {"customField": 'your-custom-value'};
final result = await vendure.custom.query(
myCustomQuery,
variables,
CustomQueryResult.fromJson,
expectedDataType: 'custom',
);
print('Custom result: ${result.customField}');
} catch (e) {
print('Error custom query: $e');
}
}Future<void> customQueryList() async {
try {
const String myCustomQueryList = r'''
query CustomQueryList {
customListMethod{
__typename
{
customListItem
}
}
}
''';
final result = await vendure.custom.queryList(
myCustomQueryList,
{},
CustomQueryResult.fromJson,
expectedDataType: 'customListItems',
);
for (var item in result) {
print('Custom list item: ${item.customListItem}');
}
} catch (e) {
print('Error custom query list: $e');
}
} Future<List<ZikZakResponse>> postZikZaks(
{required List<ZikZak> zikZaks, required String userId}) async {
final input = zikZaks
.map((zikZak) => ZikZakToMutationMapper.toMutationInput(zikZak, userId))
.toList();
print(input.map((i) => i.toJson()).toList());
return _vendure.custom.mutateList<ZikZakResponse>(
postZikZaksMutation,
{'input': input.map((i) => i.toJson()).toList()},
ZikZakResponse.fromJson,
expectedDataType: 'postZikZaks',
);
}Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the GitHub repository.


