Last updated:
0 purchases
fast sync client
Fast Sync
FastSync is a powerful and streamlined package designed to simplify data synchronization from server side to client application, by consolidating multiple APIs into a single, cohesive interface.
Inspired by Git's approach to version control, FastSync offers a set of functions to provide a robust solution for efficient data synchronization:
pull()
push()
sync()
hardReset()
FastSync goes beyond traditional synchronization tools by intelligently handling conflicts that may arise due to simultaneous changes on remote ends. Our sophisticated conflict detection mechanism identifies conflicts at the object level, empowering users to provide custom resolution functions.
FastSync supports three distinct conflict resolution strategies to accommodate various use cases:
LastWriterWins
TimestampOrdering
PredefinedRules
Note: when you specify it as predefined rules, you need to provide a custom function to resolve conflicts whenever they are detected.
TypeScript server pacakge
Dart client package
Fast Sync Core #
Server installation
Server setup
Server syncable object
Server syncable object data source
Server syncalbe repository
Server Push And Pull
Server installation #
"dependencies": {
...
"fast-sync-core": "*.*.*",
"fast-sync-mongoose-dao": "*.*.*",
...
}
copied to clipboard
Server setup #
In your the entry point of your server, initialize your FastSync package.
Configure your dao (Data Access Object), When you initialize FastSync package in this exemple we are using mongoose dao.
Configure the object type to be syncked using setSyncalbeObject method.
Configure the conflict handler for the configured object type.
async function configureFastSync() {
let fastSync: FastSync = FastSync.getInstance(
new MongooseSyncConfiguration()
);
let conflictsHandler: IConflictsHandler = new ConflictsHandler(
ConflictsResolutionStrategyEnum.PredefinedRules,
conflictsResolutionFunction
);
let repo = new ItemRepository();
await fastSync.setSyncalbeObject(Item.name, repo, conflictsHandler);
}
copied to clipboard
Call configureFastSync() in your main func after running the App.
app.listen(port, async () => {
try {
await configureFastSync();
console.log("Configuration completed successfully");
} catch (error) {
console.error("Error configuring Fast Sync:", error);
}
});
copied to clipboard
Server Syncable Object #
Requires fast-sync-mongoose-dao package
you need to extend SyncableObject from fast-sync-core and plug the type metadata schema using plugMetadataSchema
import { SyncableObject } from "fast-sync-core";
import { SyncableSchemaItemBuilder } from "fast-sync-mongoose-dao";
import * as mongoose from "mongoose";
export class Item extends SyncableObject {
public name: string;
public description: string;
public id: string;
constructor() {
super();
}
}
export const ItemSchema = SyncableSchemaItemBuilder.plugMetadataSchema(
new mongoose.Schema({
name: {
type: mongoose.Schema.Types.String,
},
description: {
type: mongoose.Schema.Types.String,
},
})
);
copied to clipboard
Server Syncable Object Data Source #
Now for each SyncableObject you should have a DataSource don't worry every think is setted for you, just create the class.
Note: if you need further method, can just create it there and use it.
import { SyncalbeObjectDataSource } from "fast-sync-mongoose-dao";
import { Item, ItemSchema } from "./item";
export class ItemDataSource extends SyncalbeObjectDataSource<Item> {
constructor() {
super(ItemSchema, Item.name);
}
}
copied to clipboard
Server Syncalbe Repository #
To interact with the objects, you should only use the repository,
you can use the datasource, but like that you break the package.
Note: note that you don't need to create new method in the repository, because every think is there use the defined method.
In some rare extreme case we can create some new methods.
import { SyncalbeRepository } from "fast-sync-core";
import { Item } from "./item";
import { ItemDataSource } from "./item_datasource";
export class ItemRepository extends SyncalbeRepository<Item> {
constructor() {
super(new ItemDataSource(), Item.name);
}
}
copied to clipboard
Server Push And Pull #
all what you need is to define your 2 apis, one for the /push, the other is the /pull
we decided to give you aibilty to control your api, and we are taking care of the logic behind.
@Post("/push")
async pushUserObjects(
@Req() req,
@Res() res,
@Body() input: SyncPayload
) {
try{
let syncManager = FastSync.getInstance().getSyncManager()
await this.syncManager.processPush(input)
return this.success(res, {"result":"push was done with success"});
}
catch(err){
return this.error(res,err);
}
}
copied to clipboard
@Post("/pull")
async pullUserObjects(
@Req() req,
@Res() res,
@Body() metadata: SyncOperationMetadata
) {
try{
let result = await this.syncManager.processPull(metadata)
return this.success(res, result);
}
catch(err){
return this.error(res,err);
}
}
copied to clipboard
SyncOperationMetadata and SyncPayload and 2 object handled internally in the package, don't worry they will be created from the client part. you don't need to do any thing here.
you can add some middleware for the api if you would like.
Full sync server exemple for mongoose dao
Fast Sync Client
Dart client installation
Client Setup
Client Syncable Object
Run the Code Generator
Client Syncable Object Data Source
Client Syncalbe Repository
Http Manager
Sync Manager
Dart client Installation #
dependencies:
# add fast_sync_client to your dependencies
fast_sync_client:
# add fast_sync_hive_dao to your dependencies
fast_sync_hive_dao:
dev_dependencies:
# add the generator to your dev_dependencies
build_runner:
copied to clipboard
Client Setup #
In your main function of your application, initialize your FastSync package.
Configure your dao (Data Access Object), When you initialize FastSync package in this exemple we are using Hive dao.
Configure the object type to be syncked using setSyncalbeObject method, and set the syncZone string for that type specific type.
initialize the type datasource and repository for that
Configure the conflict handler for the configured object type.
Configure the httpManger, using it you will be able to interact with your server, there you will need to implement the push and pull functions.
Note: you can set the syncZone string later, but before the you use the pull and push functions, SyncZone string is unique id, to only sync object that belong to that id.
Exemple: when you specify the user.Id as syncZone, all the object for that type, for that user will be syncked for him.
And when you specify the company.id as syncZone all the object for that type will be syncked for all the users that belong to that company.
you need specify SyncZone, so that the package can know to whom the object will be syncked, if is user.id only the user can see and change these objects.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initHive();
FastSync.setSyncConfiguration<HiveSyncConfiguration>(HiveSyncConfiguration());
FastSync.setTypeSyncZone<Item>(SyncZoneRestrictionEnum.restricted,
syncZone: "userId");
FastSync.setHttpManager(HttpManager());
ItemRepository repository = ItemRepository(dataSource: ItemDataSource());
FastSync.setSyncableObject<Item>(
fromJson: Item.fromJson, toJson: Item.intoJson, repository: repository);
runApp(MyApp());
}
Future<void> initHive() async {
var dir = await getApplicationDocumentsDirectory();
Hive.init(dir.path);
Hive.registerAdapter(ItemAdapter());
}
copied to clipboard
Client Syncable Object #
Requires fast_sync_hive_dao package
you need to extend SyncableItemModel from fast_sync_hive_dao and plug the type metadata.
import 'package:fast_sync_hive_dao/fast_sync_hive_dao.dart';
import 'package:hive/hive.dart';
import 'package:json_annotation/json_annotation.dart';
part 'item.g.dart';
@HiveType(typeId: 1, adapterName: "ItemAdapter")
@JsonSerializable(explicitToJson: true)
class Item extends SyncableItemModel {
@HiveField(1)
String name;
@HiveField(2)
String description;
Item({required this.name, required this.description});
@override
factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
@override
Map<String, dynamic> toJson() => _$ItemToJson(this);
static Function get intoJson => _$ItemToJson;
}
copied to clipboard
Run the Code Generator #
Run the generator with flutter packages pub run build_runner build.
To automatically run it, whenever a file changes, use flutter packages pub run build_runner watch.
Client Syncable Object Data Source #
Now for each SyncableObject you should have a DataSource don't worry every think is setted for you, just create the class.
Note: if you need further method, can just create it there and use it.
import 'package:example/item/item.dart';
import 'package:fast_sync_hive_dao/fast_sync_hive_dao.dart';
class ItemDataSource extends SyncalbeObjectDataSource<Item> {
ItemDataSource();
}
copied to clipboard
Client Syncalbe Repository #
To interact with the objects, you should only use the repository,
you can use the datasource, but like that you break the package.
Note: note that you don't need to create new method in the repository, because every think is there use the defined method.
In some rare extreme case we can create some new methods.
import 'package:example/item/item.dart';
import 'package:fast_sync_client/fast_sync_client.dart';
class ItemRepository extends SyncalbeRepository<Item> {
ItemRepository({required super.dataSource});
}
copied to clipboard
Http Manager #
HttpManger is abstract class, you need just implement the 2 methods: pull and puss
Just you need only to make to http calls to your server, don't worry how you create the body of your calls, they will made to you.
import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:fast_sync_client/fast_sync_client.dart';
class HttpManager implements IhttpManager {
final dio = Dio();
HttpManager();
@override
Future<SyncPayload> pull(SyncOperationMetadata metadata) async {
Response response = await dio.post(
'https://www.server.com/pull',
data: json.encode(metadata.toJson()));
if (response.data["success"] == true) {
return SyncPayload.fromJson(response.data["data"]);
}
return throw Exception('pull failed');
}
@override
Future<bool> push(SyncPayload payload) async {
Response response = await dio.post(
'https://www.server.com/push',
data: json.encode(payload.toJson()));
if (response.data["success"] == true) {
return true;
}
return throw Exception('push failed');
}
}
copied to clipboard
SyncOperationMetadata and SyncPayload and 2 object handled internally in the package, don't worry they will be created from the client part. you don't need to do any thing here.
Sync Manager #
To Push, Pull, sync, hardReset, Just get syncManager instance using getSyncManager(), and then have fun playing with your data.
import 'package:example/item/item.dart';
import 'package:fast_sync_client/fast_sync_client.dart';
import 'package:flutter/material.dart';
class ItemProvider with ChangeNotifier {
List<Item> items = [];
ISyncableRepository<Item> repository = FastSync.getObjectRepository<Item>();
ISyncManager syncManager = FastSync.getSyncManager();
Future<List<Item>> loadLocalItems() async {
List<Item> localItems = await repository.getAll();
return localItems;
}
Future<void> pull() async {
await syncManager.pull();
}
Future<void> sync() async {
await syncManager.sync();
}
Future<void> push() async {
await syncManager.push();
}
Future<void> hardReset() async {
await syncManager.hardReset();
}
Future<void> resetItemRepo() async {
await repository.hardDelete();
}
Future<Item> saveElement(Item item) async {
item = await repository.add(item);
return item;
}
Future<Item> updateElement(Item item) async {
item = await repository.update(item);
return item;
}
Future<int> getCount() async {
int count = await repository.count();
return count;
}
}
copied to clipboard
Full sync client exemple for Hive dao
You can support the library by staring it on Github && liking it on pub or report any bugs you encounter.
also, if you have a suggestion or think something can be implemented in a better way, open an issue and let's talk about it.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.