@ironroggers/sync-engine
v1.0.1
Published
Bidirectional real-time data sync between clients and MongoDB
Downloads
30
Maintainers
Readme
mongo-sync-lite
Bidirectional real-time data sync between clients and MongoDB. A lightweight, schema-agnostic alternative to Firebase/Realm Sync — MongoDB-native and fully customizable.
Features
- Bidirectional sync (client ↔ MongoDB)
- Real-time updates via WebSocket
- Offline support with automatic queue flush on reconnect
- Delta sync (only changed documents)
- Conflict resolution (Last Write Wins or version-based, pluggable)
- Subscription model with optional query filters
- Token-based auth middleware hook
- Soft deletes
- Full TypeScript with strict mode
Install
npm install
npm run buildQuick Start
Server
import { createSyncServer } from "mongo-sync-lite";
const server = createSyncServer({
mongoUri: "mongodb://localhost:27017",
dbName: "my-db",
port: 4000,
authMiddleware: async (token) => token === "my-secret",
});
await server.start();Client
import { createSyncClient } from "mongo-sync-lite";
const client = createSyncClient({
url: "ws://localhost:4000",
token: "my-secret",
});
await client.connect();
// Subscribe to a collection (with optional filter)
client.subscribe("tasks", { status: "open" }, (op, doc) => {
console.log(op, doc);
});
// CRUD
const task = await client.create("tasks", { title: "Hello", status: "open" });
await client.update("tasks", task._id, { status: "done" });
await client.delete("tasks", task._id);
// Read local cache
const tasks = client.getLocal("tasks");Conflict Resolution
import { createSyncServer, versionBased } from "mongo-sync-lite";
const server = createSyncServer({
mongoUri: "...",
dbName: "...",
conflictResolver: versionBased, // or lastWriteWins (default)
});Custom resolver:
const myResolver = (local, remote) => {
// your logic — return { winner, loser }
return local.priority > remote.priority
? { winner: local, loser: remote }
: { winner: remote, loser: local };
};Hooks
const server = createSyncServer({
mongoUri: "...",
dbName: "...",
hooks: {
beforeSync: async (change) => { /* validate, log, etc. */ },
afterSync: async (change) => { /* notify, audit, etc. */ },
},
});Run the Example
Start MongoDB, then in three terminals:
# Terminal 1 — server
ts-node examples/basic/server.ts
# Terminal 2 — client B (listener)
ts-node examples/basic/client-b.ts
# Terminal 3 — client A (creates + updates tasks)
ts-node examples/basic/client-a.tsDocument Shape
Every document automatically gets these metadata fields:
| Field | Type | Description |
|-------------|---------|------------------------------------|
| _id | string | UUID |
| updatedAt | number | Unix ms timestamp |
| version | number | Incremented on every write |
| isDeleted | boolean | Soft delete flag |
Scripts
| Command | Description |
|-----------------|------------------------------|
| npm run build | Compile TypeScript |
| npm test | Run unit tests (Vitest) |
| npm run dev | Run server with ts-node-dev |
| npm run example | Run basic example server |
Architecture
src/
core/ # Types, logger, conflict resolvers
adapters/ # MongoDB adapter
sync/ # SyncEngine (apply changes, delta fetch)
server/ # SyncServer + WebSocketManager
client/ # SyncClient, LocalCache, OfflineQueue
examples/
basic/ # Two-client live sync demo
tests/ # Vitest unit tests