ncc_data_shaft 2.0.0
ncc_data_shaft: ^2.0.0 copied to clipboard
The official bridge between network_cool_client (ncc) and data_shaft. Provides standardized drivers and datasources for a clean data layer.
ncc_data_shaft ⚡️ #
Bridge between robust networking and clean data architecture. Ncc and data_shaft
ncc_data_shaft is the official glue that joins the power of Ncc (session management, auto-renewal, and network state tracking) with the architectural rigor of data_shaft (Clean Architecture, strict typing, and error handling).
This package provides a standardized RemoteDriver implementation powered by the Ncc BaseClient. It eliminates the need for manual adapters by offering pre-configured drivers and specialized data sources for both public and authenticated communication.
Key Features #
- 🛡️ Context-Strict Typing: The compiler prevents you from using a public client for an endpoint requiring a session (e.g., DatasourceSessionGet vs DatasourceHttpGet).
- 🚀 Zero Boilerplate: Includes HttpDataShaftDriver and SessionDataShaftDriver ready to use.
- 📦 All-in-One: Seamlessly bridges data_shaft repositories with ncc session logic and interceptors.
- 🔄 Transparent Auto-Renewal: Requests failing due to expired tokens are paused; ncc handles renewal, and data_shaft retries the request seamlessly.
- ✨ Clean Architecture Ready: Built on top of data_shaft principles to ensure a decoupled and testable data layer.
📖 Implementation Examples #
1. Driver Configuration #
Initialize the drivers by injecting the corresponding ncc client:
import 'package:ncc_data_shaft/ncc_data_shaft.dart';
// Driver for Public APIs (Uses NccClient)
final publicClient = NccClient(id: 'public-api');
final publicDriver = HttpDataShaftDriver(client: publicClient);
// Driver for Authenticated APIs (Uses SessionClient)
final authClient = MySessionClient(id: 'secure-api');
final sessionDriver = SessionDataShaftDriver(client: authClient);
2. Specialized DataSources #
Create data sources by extending the specific verb and context needed:
Public GET Request
Use DatasourceHttpGet to ensure this endpoint uses the session-less driver.
class GetProductsDataSource extends DatasourceHttpGet<ProductModel> {
GetProductsDataSource({required super.driver});
@override
GetParams? generateCallRequirement({required Params params}) {
return GetParams(baseUrl: 'https://api.example.com/products');
}
}
Authenticated POST Request
Use DatasourceSessionPost for protected endpoints. The compiler will demand a session driver, ensuring tokens are attached to the headers.
class CreateOrderDataSource extends DatasourceSessionPost<OrderModel> {
CreateOrderDataSource({required super.driver});
@override
PostParams generateCallRequirement({required Params params}) {
return PostParams(
baseUrl: 'https://api.example.com/secure/orders',
encodeBody: () => jsonEncode({'itemId': params.id}),
);
}
}
3. Path Variables vs Query Parameters #
The package distinguishes between modifying the URL path and adding query parameters:
- Path Variables: Use the
pathModificationmap in your DataSource class to replace placeholders like{id}in thepath. - Query Parameters: Use
urlParamsinsideGetParams,PostParams, etc., to append key-value pairs to the URL (e.g.,?search=term).
class GetUserDataSource extends DatasourceGetHttp<UserRemote> {
GetUserDataSource({required super.driver});
@override
String? get path => 'users/{id}';
@override
final Map<String, String> pathModification = {'{id}': ''};
@override
GetParams generateCallRequirement({required UserParams params}) {
// 1. Update Path Placeholder
pathModification.update('{id}', (value) => params.userId.toString());
return const GetParams(
// 2. Append Query Parameters (?active=true)
urlParams: {'active': 'true'},
);
}
}
4. Repository Usage #
Wrap your DataSource in a data_shaft repository. The repository catches network exceptions and converts them into controlled domain errors.
final repository = SafeRepositoryDatasourceCallable(
dataSource: GetProductsDataSource(driver: publicDriver),
);
final result = await repository(repositoryParams: const NoParams());
result.fold(
(error) => print('Error: ${error.message}'),
(data) => print('Success: ${data.name}'),
);
🏗️ Available Class Hierarchy #
The package includes base classes for all standard HTTP operations, strictly tied to their security context:
| Operation | Public (HttpDataShaftDriver) | Session (SessionDataShaftDriver) |
|---|---|---|
| GET | DatasourceHttpGet | DatasourceSessionGet |
| POST | DatasourceHttpPost | DatasourceSessionPost |
| PUT | DatasourceHttpPut | DatasourceSessionPut |
| PATCH | DatasourceHttpPatch | DatasourceSessionPatch |
| DELETE | DatasourceHttpDelete | DatasourceSessionDelete |
Observability & Safety #
- Error Handling: Automatically maps exceptions to data_shaft's structured error levels: Inadmissible, OnException, and UnControl.
- Logging: Full observability of network traffic and repository logic powered by dart:developer tags like DS.REMOTE.
Customize logging by implementing HttpDatasourceObserver or RepositoryObserver:
DatasourceObserverInstances.httpDatasourceObserver = MyCustomLogStrategy();
🤖 AI-Assisted Development #
This repository includes an AI assistant skill designed to help generate DataSources, Repositories, and Models following the project conventions and best practices.
🤝 Contributing #
Contributions are welcome!
- Open issues for bugs or feature requests
- Fork the repo and submit a PR
- Run
dart formatanddart testbefore submitting
Authors & Maintainers #
This project was created and is primarily maintained by:
![]() Cayetano Bañón Rubio |
![]() Eduardo Martínez Catalá | ![]() Jesus Bernabeu |
License #
MIT © 2026 Coolosos


