What is VoidMerge?
Void Merge is the next-generation, developer oriented web services platform.
- Forever open-source design eliminates big-tech vendor lock-in.
- Conflict-free data replication makes clustering a breeze.
- Built from the start for state of the art real-time P2P apps and post-quantum security.
- Managed hosting for turnkey security and reliability.
The vm Utility
Install the vm command-line utility to work with VoidMerge.
vm serveruns a VoidMerge server instance.- The other commands let you administrate a running server instance.
Installing the vm Utility
Option 1: Install from crates.io
- First, Get Rust (https://rustup.rs/).
- Second, Install the
vmutility with cargo:
cargo install voidmerge --bin vm
Use this command like other local commands:
vm --help
Option 2: Use a docker image
docker pull ghcr.io/voidmerge/voidmerge-vm:latest
Use this command through docker:
docker run -it ghcr.io/voidmerge/voidmerge-vm:latest vm --help
Note: if you're running 'vm serve' in docker, you'll likely need to add additional options to the command to bind a volume and expose the port of the server.
Quick Start
Clone the Template Repository
git clone https://github.com/voidmerge/voidmerge-template.git
# then go into the directory
cd voidmerge-template
Install Dependencies
npm install
Run the VM Server (Using Docker):
npm run start-docker
Open a browser:
No Docker? Install the "vm" Cli Tool.
cargo install voidmerge
Run the VM Server (Using Native CLI):
npm start
Open a browser:
Functions
Functions represent the main request/response type of a Void Merge service.
// Import the voidmerge-code library to gain access to types.
import * as VM from "@voidmerge/voidmerge-code"
// The "VoidMergeHandler" is the main entry point to void merge logic.
VM.defineVoidMergeHandler(async (req) => {
// If this is a "Function" type request, send back a "Hello World!" response.
if (req instanceof VM.RequestFn) {
return new VM.ResponseFnOk({
// Set the http status code to 200.
status: 200,
// Send back "Hello World!" text.
body: new TextEncoder().encode("Hello World!"),
// Set the content type to "text/plain".
headers: {
"content-type": "text/plain",
},
});
}
// Output an error if the request is a type we don't handle.
throw new Error(`Unhandled Request ${JSON.stringify(req)}`);
})
Object Store
A Void Merge service has access to an object store.
Put data into the store.
const { meta } = await VM.objPut({
meta: VM.ObjMeta.fromParts({ appPath: "test-path" }),
data: new TextEncoder().encode("test-data"),
});
Get data from the store.
const { data } = await VM.objGet({
meta: VM.ObjMeta.fromParts({ appPath: "test-path" }),
});
List data from the store.
const { metaList } = await VM.objList({
appPathPrefix: "test-",
createdGt: 0,
limit: 50,
});
Object Store Validation
When data is put into the object store, either from a call in a function or cron handler, or when it is synced from a peer node in a cluster, Void Merge provides an opportunity to validate the data, and reject it if needed.
import * as VM from "@voidmerge/voidmerge-code";
VM.defineVoidMergeHandler(async (req) => {
if (req instanceof VM.RequestObjCheck) {
const data = new TextDecoder().decode(req.data);
if (data === "hello") {
return new VM.ResponseObjCheckOk();
} else {
throw new Error(`invalid data: ${data}`);
}
}
}
Cron
Void Merge web services provide a method for periodic maintenance tasks.
First, we have to tell void merge how often to run this task.
ResponseCodeConfigOk type API Docs
import * as VM from "@voidmerge/voidmerge-code";
VM.defineVoidMergeHandler(async (req) => {
const reqType = req.type;
if (req instanceof VM.RequestCodeConfig) {
// Run cron every 10 seconds.
return new VM.ResponseCodeConfigOk({ cronIntervalSecs: 10 });
}
}
Now we need to actually do something when a cron request is triggered.
import * as VM from "@voidmerge/voidmerge-code";
VM.defineVoidMergeHandler(async (req) => {
const reqType = req.type;
if (req instanceof VM.RequestCodeConfig) {
// Run cron every 10 seconds.
return new VM.ResponseCodeConfigOk({ cronIntervalSecs: 10 });
} else if (req instanceof VM.RequestCron) {
// Write a new unique entry every cron run.
await VM.objPut({
meta: VM.ObjMeta.fromParts({ appPath: Date.now().toString() }),
data: new TextEncoder().encode(Date.now().toString()),
});
return new VM.ResponseCronOk();
}
}
Messaging
A Void Merge service provides the ability to send messages to connected clients and can be set up so clients can message each other.
Create a new messaging channel for a client.
const { msgId } = await VM.msgNew();
// In the client code:
import * as VM from "@voidmerge/voidmerge-client"
const listener = await VM.MsgListener.connect({
msgId,
...
});
List open messaging channels.
const { msgIdList } = await VM.msgList();
Send a message over an open channel.
await VM.msgSend({
msg: new TextEncoder().encode("hello"),
msgId,
});