boltcart_sdk 0.1.0
boltcart_sdk: ^0.1.0 copied to clipboard
Type-safe Dart and Flutter SDK for the Boltcart backend.
Boltcart SDK #
Type-safe Dart and Flutter SDK for the Boltcart ecommerce backend.
The package is generated from the backend OpenAPI documents and exposes a small handwritten runtime plus generated models and repositories. It is a pure Dart package, so it works in Flutter mobile, desktop, web, and server-side Dart code.
Features #
- Typed repositories grouped by backend resource, such as
catalogProducts,cart,orders,customersMe,adminOrders, andauth. - Typed request bodies, query objects, path parameter objects, response models, and shared
ProblemDetails. - Eden-style results with
Future<ApiResult<T>>, so callers handle success and failure explicitly. - Auth helpers for bearer tokens, cookies, and custom async headers.
- Dio transport with cancellation and per-request headers.
- JSON requests and responses.
- Multipart uploads for file endpoints.
- PDF downloads as
Uint8List. - Notification streams as
Stream<ServerSentEvent>.
Installation #
For a local monorepo Flutter or Dart app, depend on the package by path:
dependencies:
boltcart_sdk:
path: ../packages/boltcart_sdk
Then fetch dependencies:
dart pub get
For Flutter apps, use:
flutter pub get
Quick Start #
import 'package:boltcart_sdk/boltcart_sdk.dart';
Future<void> main() async {
final sdk = BoltcartSdk(
baseUrl: Uri.parse('https://api.example.com'),
);
final result = await sdk.catalogProducts.getCatalogProducts();
switch (result) {
case ApiSuccess(:final data):
for (final product in data.data) {
print(product.title);
}
case ApiFailure(:final error):
print(error.message);
}
}
Authentication #
Use a bearer token:
final sdk = BoltcartSdk(
baseUrl: Uri.parse('https://api.example.com'),
auth: BoltcartAuth.bearer(accessToken),
);
Use a cookie session:
final sdk = BoltcartSdk(
baseUrl: Uri.parse('https://api.example.com'),
auth: BoltcartAuth.cookie('better-auth.session_token=...'),
);
Use custom async headers:
final sdk = BoltcartSdk(
baseUrl: Uri.parse('https://api.example.com'),
auth: BoltcartAuth.headers(() async {
final token = await secureStorage.read(key: 'access_token');
return token == null ? {} : {'authorization': 'Bearer $token'};
}),
);
Per-request headers can be passed with BoltcartRequestOptions:
final result = await sdk.orders.getOrders(
options: const BoltcartRequestOptions(
headers: {'x-boltcart-locale': 'en'},
),
);
Working With Results #
Every generated repository method returns Future<ApiResult<T>>.
final result = await sdk.cart.getCart();
final cart = result.when(
success: (success) => success.data,
failure: (failure) {
final error = failure.error;
throw StateError(error.message);
},
);
Success values include the decoded typed data, status code, and response headers:
if (result case ApiSuccess(:final data, :final statusCode, :final headers)) {
print(statusCode);
print(headers['cache-control']);
print(data);
}
Failures are typed:
if (result case ApiFailure(:final error)) {
switch (error) {
case BoltcartProblemError(:final problem):
print(problem.code);
print(problem.detail);
case BoltcartHttpError(:final statusCode, :final body):
print('Unexpected HTTP $statusCode: $body');
case BoltcartNetworkError(:final cause):
print('Network problem: $cause');
case BoltcartDecodeError(:final cause):
print('Decode problem: $cause');
}
}
Query, Params, and Body Models #
Generated methods use typed objects when an endpoint has path parameters, query parameters, or a body.
final product = await sdk.catalogProducts.getCatalogProductsByHandle(
params: const GetCatalogProductsByHandleParams(handle: 'classic-shirt'),
);
final orders = await sdk.orders.getOrders(
query: const GetOrdersQuery(page: 1, pageSize: 20),
);
final updated = await sdk.cart.patchCartItemsById(
params: const PatchCartItemsByIdParams(id: 'cart_item_id'),
body: const PatchCartItemsByIdRequest(quantity: 2),
);
Model classes include:
fromJsontoJsoncopyWith- deep equality
File Uploads #
Multipart endpoints use Dio MultipartFile.
import 'package:dio/dio.dart';
import 'package:boltcart_sdk/boltcart_sdk.dart';
final result = await sdk.adminFiles.postAdminFiles(
body: PostAdminFilesRequest(
file: await MultipartFile.fromFile(
'/path/to/image.png',
filename: 'image.png',
contentType: DioMediaType('image', 'png'),
),
),
);
PDF Downloads #
Invoice endpoints return Uint8List.
final result = await sdk.orders.getOrdersByOrderNumberInvoicePdf(
params: const GetOrdersByOrderNumberInvoicePdfParams(
orderNumber: 'BC-2026-0001',
),
);
if (result case ApiSuccess(:final data)) {
// `data` is Uint8List.
}
Notification Streams #
Server-Sent Event endpoints return a stream wrapped in ApiResult.
final result = await sdk.customersMe.getMeNotificationsStream();
if (result case ApiSuccess(:final data)) {
await for (final event in data) {
print(event.event);
print(event.data);
}
}
Using a Custom Dio Instance #
Pass a configured Dio instance when you need interceptors, custom timeouts, proxies, certificate pinning, or logging.
final dio = Dio(
BaseOptions(
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 30),
),
);
dio.interceptors.add(LogInterceptor(responseBody: false));
final sdk = BoltcartSdk(
baseUrl: Uri.parse('https://api.example.com'),
dio: dio,
);
Generated Surface #
The SDK currently contains generated coverage for:
- Public catalog: products, brands, categories, reviews.
- Buyer flows: cart, checkout, orders, returns, wishlist, customer profile, addresses, notifications.
- Admin flows: files, catalog, customers, sellers, dashboard, inventory, notifications, orders, discounts, returns, audit logs.
- Better Auth routes under
sdk.auth. - System health under
sdk.system.
Generated files live under lib/src/generated_sdk.dart, lib/src/model/generated_models.dart, and lib/src/repo/generated_repositories.dart.
Regenerating the SDK #
From the repository root:
bun run sdk:generate
Check that generated files are current:
bun run sdk:generate:check
Run SDK tests and analysis:
bun run sdk:test
bun run sdk:analyze
The generator and test tooling are repository-only files and are excluded from pub.dev packages with .pubignore.
Publishing Notes #
The pub package excludes repository-only files such as:
test/tool/openapi.generated.jsonpackage.jsonpubspec.lockanalysis_options.yaml
Those files remain in git for this private repository but are not intended to be part of the public pub.dev package.