data_management 2.0.7+1 data_management: ^2.0.7+1 copied to clipboard
Collection of service with advanced style and controlling system.
data_management #
Collection of service with advanced style and controlling system.
Use cases
// Example: Check data by ID
final checkResponse = userRepository.checkById('userId123');
// Output: DataResponse<User> ...
// Example: Clear data
final clearResponse = userRepository.clear();
// Output: DataResponse<User> ...
// Example: Create data
final newUser = User(name: 'John', age: 25);
final createResponse = userRepository.create(newUser);
// Output: DataResponse<User> ...
// Example: Create multiple data entries
final newUserList = [User(name: 'John', age: 25), User(name: 'Alice', age: 30)];
final createsResponse = userRepository.creates(newUserList);
// Output: DataResponse<User> ...
// Example: Delete data by ID
final deleteResponse = userRepository.deleteById('userId123');
// Output: DataResponse<User> ...
// Example: Delete data by multiple IDs
final deleteIdsResponse = userRepository.deleteByIds(['userId1', 'userId2']);
// Output: DataResponse<User> ...
// Example: Get all data
final getResponse = userRepository.get();
// Output: DataResponse<User> ...
// Example: Get data by ID
final getByIdResponse = userRepository.getById('userId123');
// Output: DataResponse<User> ...
// Example: Get data by multiple IDs
final getByIdsResponse = userRepository.getByIds(['userId1', 'userId2']);
// Output: DataResponse<User> ...
// Example: Get data by query
final query = Query.field('name', 'John');
final getByQueryResponse = userRepository.getByQuery(queries: [query]);
// Output: DataResponse<User> ...
// Example: Listen for data changes
final listenResponse = userRepository.listen();
// Output: Stream<DataResponse<User>> ...
// Example: Listen for data changes by ID
final listenByIdResponse = userRepository.listenById('userId123');
// Output: Stream<DataResponse<User>> ...
// Example: Listen for data changes by multiple IDs
final listenByIdsResponse = userRepository.listenByIds(['userId1', 'userId2']);
// Output: Stream<DataResponse<User>> ...
// Example: Listen for data changes by query
final listenByQueryResponse = userRepository.listenByQuery(queries: [query]);
// Output: Stream<DataResponse<User>> ...
// Example: Check data by query
final checker = Checker(field: 'status', value: 'active');
final searchResponse = userRepository.search(checker);
// Output: DataResponse<User> ...
// Example: Update data by ID
final updateData = {'status': 'inactive'};
final updateByIdResponse = userRepository.updateById('userId123', updateData);
// Output: DataResponse<User> ...
// Example: Update data by multiple IDs
final updates = [
UpdatingInfo('userId1', {'status': 'inactive'}),
UpdatingInfo('userId2', {'status': 'active'}),
];
final updateByIdsResponse = userRepository.updateByIds(updates);
// Output: DataResponse<User> ...
Api data example:
import 'package:data_management/core.dart';
import 'package:flutter/material.dart';
class ApiDataTest extends StatefulWidget {
const ApiDataTest({Key? key}) : super(key: key);
@override
State<ApiDataTest> createState() => _ApiDataTestState();
}
class _ApiDataTestState extends State<ApiDataTest> {
late DataController<Post> controller = DataController.of(context);
@override
Widget build(BuildContext context) {
var p1 = Post(
id: "1",
title: "This is a title 1",
body: "This is a body 1",
);
var p2 = Post(
id: "2000",
userId: 1,
title: "This is a title 2",
body: "This is a body 2",
);
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Wrap(
runSpacing: 12,
spacing: 12,
runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
child: const Text("Availability"),
onPressed: () => controller.checkById("1"),
),
ElevatedButton(
child: const Text("Insert"),
onPressed: () => controller.create(p2),
),
ElevatedButton(
child: const Text("Inserts"),
onPressed: () => controller.creates([p1, p2]),
),
ElevatedButton(
child: const Text("Update"),
onPressed: () {
controller.updateById(
id: "1",
data: p1
.copyWith(
title: "Title updated!",
body: "Body updated!",
)
.source,
);
},
),
ElevatedButton(
onPressed: () => controller.deleteById("1"),
child: const Text("Delete"),
),
ElevatedButton(
onPressed: () => controller.clear(),
child: const Text("Clear"),
),
ElevatedButton(
onPressed: () => controller.getById("1"),
child: const Text("Get"),
),
ElevatedButton(
onPressed: () => controller.get(),
child: const Text("Gets"),
),
],
),
DataBuilder<Post>(
builder: (context, response) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: Text(
response.toString(),
textAlign: TextAlign.center,
),
);
},
),
],
),
),
);
}
}
/// Step - 2
/// When you use remote database (ex. Firebase Firestore, Firebase Realtime, Api, Encrypted Api data)
/// Use for remote data => insert, update, delete, get, gets, live, lives, clear
class RemotePostDataSource extends ApiDataSource<Post> {
RemotePostDataSource({
super.path = "posts",
//super.encryptor = const Encryptor(),
super.api = const Api(
baseUrl: "https://jsonplaceholder.typicode.com",
status: ApiStatus(ok: 200),
timer: ApiTimer(streamReloadTime: 500),
autoGenerateId: true,
),
});
@override
Post build(source) {
return Post.from(source);
}
}
/// Step - 2
/// When you use local database (ex. SharedPreference)
/// Use for local data => insert, update, delete, get, gets, live, lives, clear
class LocalPostDataSource extends LocalDataSourceImpl<Post> {
LocalPostDataSource({
super.database,
super.path = "products",
});
@override
Post build(source) {
return Post.from(source);
}
}
/// Step - 1
/// Use for local or remote data model
class Post extends Data {
final int? userId;
final String? title;
final String? body;
Post({
super.id,
super.timeMills,
this.userId,
this.title,
this.body,
});
factory Post.from(Object? source) {
return Post(
id: Data.autoId(source),
timeMills: Data.autoTimeMills(source),
userId: Data.value<int>("userId", source),
title: Data.value<String>("title", source),
body: Data.value<String>("body", source),
);
}
Post copyWith({
String? id,
int? userId,
String? title,
String? body,
}) {
return Post(
id: id ?? this.id,
userId: userId ?? this.userId,
title: title ?? this.title,
body: body ?? this.body,
);
}
@override
Map<String, dynamic> get source {
return super.source
..addAll({
"id": idInt,
"userId": idInt,
"title": title ?? "Title",
"body": body,
});
}
}
Firebase firestore example
import 'package:data_management/core.dart';
import 'package:flutter/material.dart';
class FirebaseFireStoreDataTest extends StatefulWidget {
const FirebaseFireStoreDataTest({Key? key}) : super(key: key);
@override
State<FirebaseFireStoreDataTest> createState() =>
_FirebaseFireStoreDataTestState();
}
class _FirebaseFireStoreDataTestState extends State<FirebaseFireStoreDataTest> {
late DataController<Product> controller = DataController.of(context);
@override
Widget build(BuildContext context) {
var p1 = Product(
id: "1",
timeMills: Data.generateTimeMills,
name: "Oppo F17 Pro",
price: 23500,
);
var p2 = Product(
id: "2",
timeMills: Data.generateTimeMills,
name: "Oppo A5s",
price: 14000,
);
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Wrap(
runSpacing: 12,
spacing: 12,
runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
child: const Text("Availability"),
onPressed: () => controller.checkById("1"),
),
ElevatedButton(
child: const Text("Insert"),
onPressed: () => controller.create(p1),
),
ElevatedButton(
child: const Text("Inserts"),
onPressed: () => controller.creates([p1, p2]),
),
ElevatedButton(
child: const Text("Update"),
onPressed: () {
controller.updateById(
id: p1.id,
data: p1
.copyWith(
price: 20500,
name: "Oppo F17 Pro (Updated)",
)
.source,
);
},
),
ElevatedButton(
onPressed: () => controller.deleteById("1"),
child: const Text("Delete"),
),
ElevatedButton(
onPressed: () => controller.clear(),
child: const Text("Clear"),
),
ElevatedButton(
onPressed: () => controller.getById("1"),
child: const Text("Get"),
),
ElevatedButton(
onPressed: () => controller.get(),
child: const Text("Gets"),
),
],
),
DataBuilder<Product>(
builder: (context, state) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: Text(
state.toString(),
textAlign: TextAlign.center,
),
);
},
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listenById("1"),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.data.toString(),
textAlign: TextAlign.center,
);
}),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listen(),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.result.toString(),
textAlign: TextAlign.center,
);
},
),
),
],
),
),
);
}
}
/// Step - 2
/// When you use remote database (ex. Firebase Firestore, Firebase Realtime, Api, Encrypted Api data)
/// Use for remote data => insert, update, delete, get, gets, live, lives, clear
class RemoteProductDataSource extends FirestoreDataSource<Product> {
RemoteProductDataSource({
super.path = "products",
super.encryptor = const DataEncryptor(),
});
@override
Product build(source) {
return Product.from(source);
}
}
/// Step - 2
/// When you use local database (ex. SharedPreference)
/// Use for local data => insert, update, delete, get, gets, live, lives, clear
class LocalProductDataSource extends LocalDataSourceImpl<Product> {
LocalProductDataSource({
super.database,
super.path = "products",
});
@override
Product build(source) {
return Product.from(source);
}
}
/// Step - 1
/// Use for local or remote data model
class Product extends Data {
final String? name;
final double? price;
Product({
super.id,
super.timeMills,
this.name,
this.price,
});
factory Product.from(dynamic source) {
return Product(
id: Data.value<String>("id", source),
timeMills: Data.value<int>("time_mills", source),
name: Data.value<String>("name", source),
price: Data.value<double>("price", source),
);
}
Product copyWith({
String? id,
int? timeMills,
String? name,
double? price,
}) {
return Product(
id: id ?? this.id,
timeMills: timeMills ?? this.timeMills,
name: name ?? this.name,
price: price ?? this.price,
);
}
@override
Map<String, dynamic> get source {
return super.source
..addAll({
"name": name ?? "Name",
"price": price,
});
}
}
Firebase realtime example
import 'package:data_management/core.dart';
import 'package:flutter/material.dart';
class FirebaseRealtimeDataTest extends StatefulWidget {
const FirebaseRealtimeDataTest({Key? key}) : super(key: key);
@override
State<FirebaseRealtimeDataTest> createState() =>
_FirebaseRealtimeDataTestState();
}
class _FirebaseRealtimeDataTestState extends State<FirebaseRealtimeDataTest> {
late DataController<User> controller = DataController.of(context);
@override
Widget build(BuildContext context) {
var p1 = User(
id: "1",
timeMills: Data.generateTimeMills,
name: "Mr. X",
);
var p2 = User(
id: "2",
timeMills: Data.generateTimeMills,
name: "Mr. Y",
);
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Wrap(
runSpacing: 12,
spacing: 12,
runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
child: const Text("Availability"),
onPressed: () => controller.checkById("1"),
),
ElevatedButton(
child: const Text("Insert"),
onPressed: () => controller.create(p1),
),
ElevatedButton(
child: const Text("Inserts"),
onPressed: () => controller.creates([p1, p2]),
),
ElevatedButton(
child: const Text("Update"),
onPressed: () {
controller.updateById(
id: p1.id,
data: p1.copyWith(name: "Mr. X (Updated)").source,
);
},
),
ElevatedButton(
onPressed: () => controller.deleteById("1"),
child: const Text("Delete"),
),
ElevatedButton(
onPressed: () => controller.clear(),
child: const Text("Clear"),
),
ElevatedButton(
onPressed: () => controller.getById("1"),
child: const Text("Get"),
),
ElevatedButton(
onPressed: () => controller.get(),
child: const Text("Gets"),
),
],
),
DataBuilder<User>(
builder: (context, state) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: Text(
state.toString(),
textAlign: TextAlign.center,
),
);
},
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listenById("1"),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.data.toString(),
textAlign: TextAlign.center,
);
}),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listen(),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.result.toString(),
textAlign: TextAlign.center,
);
},
),
),
],
),
),
);
}
}
/// Step - 2
/// When you use remote database (ex. Firebase Firestore, Firebase Realtime, Api, Encrypted Api data)
/// Use for remote data => insert, update, delete, get, gets, live, lives, clear
class RemoteUserDataSource extends RealtimeDataSource<User> {
RemoteUserDataSource({
super.path = "users",
super.encryptor = const DataEncryptor(),
});
@override
User build(source) {
return User.from(source);
}
}
/// Step - 2
/// When you use local database (ex. SharedPreference)
/// Use for local data => insert, update, delete, get, gets, live, lives, clear
class LocalUserDataSource extends LocalDataSourceImpl<User> {
LocalUserDataSource({
super.database,
super.path = "users",
});
@override
User build(source) {
return User.from(source);
}
}
/// Step - 1
/// Use for local or remote data model
class User extends Data {
final String? name;
User({
super.id,
super.timeMills,
this.name,
});
factory User.from(dynamic source) {
return User(
id: Data.value<String>("id", source),
timeMills: Data.value<int>("time_mills", source),
name: Data.value<String>("name", source),
);
}
User copyWith({
String? id,
int? timeMills,
String? name,
}) {
return User(
id: id ?? this.id,
timeMills: timeMills ?? this.timeMills,
name: name ?? this.name,
);
}
@override
Map<String, dynamic> get source {
return super.source
..addAll({
"name": name ?? "Name",
});
}
}
Local data examples:
import 'package:data_management/core.dart';
import 'package:flutter/material.dart';
import 'firebase_firestore_data_test.dart';
class LocalDataTest extends StatefulWidget {
const LocalDataTest({Key? key}) : super(key: key);
@override
State<LocalDataTest> createState() => _LocalDataTestState();
}
class _LocalDataTestState extends State<LocalDataTest> {
late Product p1 = Product(
id: "1",
timeMills: Data.generateTimeMills,
name: "Oppo F17 Pro",
price: 23500,
);
late Product p2 = Product(
id: "2",
timeMills: Data.generateTimeMills,
name: "Oppo A5s",
price: 14000,
);
late Cart c1 = Cart(
id: "1",
timeMills: Data.generateTimeMills,
quantity: 3,
product: p1,
);
late Cart c2 = Cart(
id: "2",
timeMills: Data.generateTimeMills,
quantity: 2,
product: p2,
);
@override
Widget build(BuildContext context) {
final controller = DataController<Cart>.of(context);
return DataBuilder<Cart>(
builder: (context, state) {
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Wrap(
runSpacing: 12,
spacing: 12,
runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
child: const Text("Availability"),
onPressed: () => controller.checkById("1"),
),
ElevatedButton(
child: const Text("Insert"),
onPressed: () => controller.create(c1),
),
ElevatedButton(
child: const Text("Inserts"),
onPressed: () => controller.creates([c1, c2]),
),
ElevatedButton(
child: const Text("Update"),
onPressed: () => controller.updateById(
id: c1.id,
data: c1.copyWith(quantity: 1).source,
),
),
ElevatedButton(
onPressed: () {
controller.deleteById("1");
},
child: const Text("Delete"),
),
ElevatedButton(
onPressed: () {
controller.clear();
},
child: const Text("Clear"),
),
ElevatedButton(
onPressed: () {
controller.getById("1");
},
child: const Text("Get"),
),
ElevatedButton(
onPressed: () {
controller.get();
},
child: const Text("Gets"),
),
],
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: Text(
state.toString(),
textAlign: TextAlign.center,
),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listenById("1"),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.data.toString(),
textAlign: TextAlign.center,
);
}),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listen(),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse<Cart>();
return Text(
value.result.toString(),
textAlign: TextAlign.center,
);
},
),
),
],
),
),
);
},
);
}
}
/// Step - 2
/// When you use local database (ex. SharedPreference)
/// Use for local data => insert, update, delete, get, gets, live, lives, clear
class CartDataSource extends LocalDataSourceImpl<Cart> {
CartDataSource({
super.database,
super.path = "carts",
});
@override
Cart build(source) {
return Cart.from(source);
}
}
/// Step - 1
/// Use for local or remote data model
class Cart extends Data {
final int? quantity;
final Product? product;
Cart({
super.id,
super.timeMills,
this.quantity,
this.product,
});
factory Cart.from(dynamic source) {
return Cart(
id: Data.value<String>("id", source),
timeMills: Data.value<int>("time_mills", source),
quantity: Data.value<int>("quantity", source),
product: Data.object("product", source, (value) => Product.from(value)),
);
}
@override
Map<String, dynamic> get source {
return super.source
..addAll({
"quantity": quantity,
"product": product?.source,
});
}
Cart copyWith({
String? id,
int? timeMills,
int? quantity,
Product? product,
}) {
return Cart(
id: id ?? this.id,
timeMills: timeMills ?? this.timeMills,
quantity: quantity ?? this.quantity,
product: product ?? this.product,
);
}
}
Bloc provider example:
import 'package:data_management/core.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const Application());
}
class Application extends StatelessWidget {
const Application({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: Scaffold(
body: SafeArea(
/// Step - 3
/// Create a data management controller with bloc
child: DataControllers(
controllers: [
/// Create data controller by data source
RemoteDataController<Post>(RemoteDataRepositoryImpl(
source: PostDataSource(),
/// (Optional) if you need to backup your data when network unavailable
backup: PostBackupSource(),
)),
],
child: const ApiDataTest(),
),
),
),
);
}
}
/// Step - 5
/// Use data management logic with data management remote data controller
class ApiDataTest extends StatefulWidget {
const ApiDataTest({Key? key}) : super(key: key);
@override
State<ApiDataTest> createState() => _ApiDataTestState();
}
class _ApiDataTestState extends State<ApiDataTest> {
late DataController<Post> controller = DataController.of(context);
@override
Widget build(BuildContext context) {
var p1 = Post(
id: "1",
title: "This is a title 1",
body: "This is a body 1",
);
var p2 = Post(
id: "2000",
userId: 1,
title: "This is a title 2",
body: "This is a body 2",
);
return SizedBox(
width: double.infinity,
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Wrap(
runSpacing: 12,
spacing: 12,
runAlignment: WrapAlignment.center,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
child: const Text("Availability"),
onPressed: () => controller.checkById("1"),
),
ElevatedButton(
child: const Text("Insert"),
onPressed: () => controller.create(p2),
),
ElevatedButton(
child: const Text("Inserts"),
onPressed: () => controller.creates([p1, p2]),
),
ElevatedButton(
child: const Text("Update"),
onPressed: () {
controller.updateById(
id: "1",
data: p1
.copyWith(
title: "Title updated!",
body: "Body updated!",
)
.source,
);
},
),
ElevatedButton(
onPressed: () => controller.deleteById("1"),
child: const Text("Delete"),
),
ElevatedButton(
onPressed: () => controller.clear(),
child: const Text("Clear"),
),
ElevatedButton(
onPressed: () => controller.getById("1"),
child: const Text("Get"),
),
ElevatedButton(
onPressed: () => controller.get(),
child: const Text("Gets"),
),
],
),
DataBuilder<Post>(
builder: (context, state) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: Text(
state.toString(),
textAlign: TextAlign.center,
),
);
},
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listenById("1"),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.data.toString(),
textAlign: TextAlign.center,
);
}),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(24),
alignment: Alignment.center,
color: Colors.grey.withAlpha(50),
margin: const EdgeInsets.symmetric(vertical: 24),
child: StreamBuilder(
stream: controller.listen(),
builder: (context, snapshot) {
var value = snapshot.data ?? DataResponse();
return Text(
value.result.toString(),
textAlign: TextAlign.center,
);
},
),
),
],
),
),
);
}
}
/// Step - 3 (Optional)
/// If you need to use any custom data managing system then you can create the custom repository
/// or use directly "RemoteDataRepositoryImpl<Post>"
class PostRepository extends RemoteDataRepositoryImpl<Post> {
PostRepository({
required super.source,
});
/// OPTIONAL FUNCTION
Future<DataResponse<Post>> fetchInnerData() async {
/// Build custom path with builder function
FieldParams params = const Params({
"post_id": "1234",
});
if (isCacheMode && isLocal) {
return backup!.get(params: params);
} else {
var connected = await isConnected;
if (!connected && isLocal) {
return backup!.get(params: params);
} else {
return source.get(
isConnected: connected,
params: params,
);
}
}
}
}
/// Step - 2
/// When you use remote database (ex. Firebase Firestore, Firebase Realtime, Api, or Encrypted Api data)
/// Use for remote data => insert, update, delete, get, gets, live, lives, clear
class PostDataSource extends ApiDataSource<Post> {
PostDataSource({
super.path = "posts/{post_id}/inner_post",
super.api = const Api(
baseUrl: "https://jsonplaceholder.typicode.com",
status: ApiStatus(ok: 200),
timer: ApiTimer(streamReloadTime: 500),
autoGenerateId: true,
),
}) : super(
/// If you want to your data secure then setup encryptor mode for encryption layer
/// This is only use for encrypted api data
// encryptor: Encryptor(
// key: "APPLICATION_SECRET_KEY",
// passcode: "APPLICATION_SECRET_PASSWORD",
// iv: "APPLICATION_SECRET_IV_NUMBER",
// request: (passcode, value) {
// /// REQUEST BODY DATA CUSTOMIZATION
// return {"data": value};
// },
// response: (value) {
// /// RESPONSE DATA MODIFICATION
// return value["data"];
// },
// ),
);
@override
Post build(source) {
/// Convert response data as Model data
return Post.from(source);
}
}
/// Step - 2 (Optional)
/// When you use local database (ex. SharedPreference)
/// Use for local data => insert, update, delete, get, gets, live, lives, clear
class PostBackupSource extends LocalDataSourceImpl<Post> {
PostBackupSource({
super.database,
super.path = "products",
});
@override
Post build(source) {
return Post.from(source);
}
}
/// Step - 1
/// Use for local or remote data model
class Post extends Data {
final int? userId;
final String? title;
final String? body;
Post({
super.id,
super.timeMills,
this.userId,
this.title,
this.body,
});
factory Post.from(Object? source) {
return Post(
id: Data.autoId(source),
timeMills: Data.autoTimeMills(source),
userId: Data.value<int>("userId", source),
title: Data.value<String>("title", source),
body: Data.value<String>("body", source),
);
}
Post copyWith({
String? id,
int? userId,
String? title,
String? body,
}) {
return Post(
id: id ?? this.id,
userId: userId ?? this.userId,
title: title ?? this.title,
body: body ?? this.body,
);
}
@override
Map<String, dynamic> get source {
return super.source
..addAll({
"id": idInt,
"userId": idInt,
"title": title ?? "Title",
"body": body,
});
}
}