
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@describble/ddnet
Advanced tools
DDNet is a decentralized network for real-time collaborative applications.
Decentralized Document Network (DDNet) is a cutting-edge, decentralized network designed for secure storage and access of documents. It aims to address the inherent challenges of centralized document storage systems, namely access control and single points of failure, by providing a robust, decentralized alternative powered by cryptographic techniques.
# Using npm
$ npm install @describble/ddnet
# Using pnpm
$ pnpm install @describble/ddnet
# Using yarn
$ yarn add @describble/ddnet
We have divided the usage examples into smaller chunks, each demonstrating a specific aspect of DDNet.
The KeyManager class handles the generation and storage of cryptographic keys for users. You pass the store-name to it as a string. This is the name of the IndexedDB store where keys are saved.
import { KeyManager } from '@describble/ddnet';
const keyManager = new KeyManager('store-name');
SessionManager is responsible for managing user's sessions.
It takes an instance of KeyManager as a parameter to manage cryptographic keys. You can also optionally pass an instance of ServiceWorkerCache to cache sessions in the browser.
import { SessionManager, KeyManager, ServiceWorkerCache } from '@describble/ddnet';
const sessionManager = new SessionManager(
new KeyManager('store-name'),
new ServiceWorkerCache(myServiceWorkerInstance) // optional session caching
);
DDnet requires a NetworkAdapter to communicate with the signaling server.
You can use the WebSocketNetworkAdapter class for this.
Pass the URL of the signaling server to it.
import { WebSocketNetworkAdapter } from '@describble/ddnet';
const networkAdapter = new WebSocketNetworkAdapter('wss://ddnet-server.com');
You need a StorageProvider instance for storing documents in the browser.
IDBStorageProvider is an implementation using IndexedDB.
import { IDBStorageProvider } from '@describble/ddnet';
const storageProvider = new IDBStorageProvider();
DocumentSharingClient is the main class that you use to create and manage documents.
It requires instances of SessionManager, NetworkAdapter, and StorageProvider.
import { DocumentSharingClient } from '@describble/ddnet';
const docClient = new DocumentSharingClient({
sessionManager,
network: networkAdapter,
storageProvider: storageProvider,
});
Once you have an instance of DocumentSharingClient, you can start creating, fetching, and updating documents.
You can create a new document using the createDocument method.
It will return a Document instance that you can use to perform operations on the document.
const doc = docClient.createDocument();
This fetches a document from the browser's local storage or in memory cache.
const doc = await docClient.findDocument('document-id');
This fetches a document from the network and caches it in the browser's local storage. If the document is already cached, it will be returned from the cache, but the network will be queried for any updates.
const doc = await docClient.requestDocument('document-id');
This returns a list of all document IDs that are stored in the browser's local storage.
const docs = await docClient.listDocumentIds();
This removes a document from the browser's local storage.
const docs = await docClient.removeDocument('document-id');
Now that you have a Document instance, you can perform operations on it.
We are using Automerge internally to manage document content.
You can use the change method to update the document content.
doc.change((data) => {
data.text = 'Hello World!';
});
You can get the document data using the data property.
const data = doc.data;
Each document has a header that contains metadata about the document.
For example, to edit who can access the document, you can do the following:
All keys can be base58 encoded or Uint8Array instances.
Header is immutable, so you need to create a new header and update the document with it.
// Private key of the owner of the document
const privateKey = "G8gw9d54D3NDt4SogSBxzyBzfkyTL9Dge1EeMQgmZSAk"
const allowedClients = [
'24YDGmC5swrdiph4pfBweYW8P8L1A4kv5K6o9BR3jHafi',
'qBWVsxpXJHfNShbiKtgWkD6M2KNp35JaPS4Efck39t43'
];
const header = document.header.update({ allowedClients }, privateKey);
document.updateHeader(header);
You can listen to events on the document using the on method.
This event is fired when the document content changes.
doc.on('change', ({document, data}) => {
console.log(`Document ${document.id} changed`, data);
});
This event is useful to know what changes were made to the document.
doc.on('patch', ({document, patches, before, after}) => {
console.log(`Document ${document.id} patched`, patches, before, after);
});
This event is fired when the document header changes.
doc.on('header-updated', ({document, header}) => {
console.log(`Document ${document.id} header changed`, header);
});
DDNet requires a signaling server to establish connections between clients. The server handles the signaling process and forwards messages between clients to establish a WebRTC connection for document exchange.
import {SignalingServer, WebSocketNetwork} from '@describble/ddnet/node';
const server = new SignalingServer({
network: new WebSocketNetwork({
host: '0.0.0.0',
port: 8080,
}),
});
server.listen();
DDnet have a system called Presence
that allows you to send arbitrary data to other connected clients for a specific document scope.
This is useful for implementing features like cursors, chat, and other collaborative features.
The data is sent to all connected clients for a specific document, and the data is not persisted.
You can get an instance of Presence using the getPresence method on the DocumentSharingClient instance.
const presence = docClient.getPresence('document-id');
You can send presence data using the sendPresenceMessage method.
presence.sendPresenceMessage({
type: 'cursor',
position: {
x: 10,
y: 20,
},
});
You can listen to presence data using the on method.
presence.on('update', (presenceMap) => {
presenceMap.forEach(({
peerId, // ID of the WebRTC connection
client, // Client data
presence, // Presence data
}) => {
console.log(`Received presence data from ${peerId}`, presence);
});
});
We can get the current presence map using the getPresence method.
const presenceMap = presence.getPresence();
You can stop listening to presence data using the stop method.
presence.stop();
Vite is a modern front-end build tool that significantly improves the front-end development experience. It provides features like hot module replacement and efficient lazy loading out of the box.
If you're using DDNet with Vite, you'll need to use a specific configuration since this package uses WebAssembly (wasm).
First, you need to install the required Vite plugins. These plugins enable support for WebAssembly and top-level await, respectively. You can install them using npm, yarn, or pnpm. Here's an example using npm:
# Using npm
$ npm install vite-plugin-wasm vite-plugin-top-level-await
# Using pnpm
$ pnpm install vite-plugin-wasm vite-plugin-top-level-await
# Using yarn
$ yarn add vite-plugin-wasm vite-plugin-top-level-await
Create or modify your vite.config.js file and include the vite-plugin-wasm and vite-plugin-top-level-await as plugins in your configuration:
import { defineConfig } from 'vite';
import wasm from 'vite-plugin-wasm';
import topLevelAwait from 'vite-plugin-top-level-await';
export default defineConfig({
plugins: [wasm(), topLevelAwait()],
});
This configuration ensures that Vite properly handles the WebAssembly files included in the DDNet package and supports top-level await syntax, which is commonly used with async WebAssembly functions.
With this setup, you should be able to integrate DDNet into your Vite project successfully. If you still encounter issues, please consult the respective plugin documentation or reach out for support.
To understand how DDNet works, please read the technical overview.
FAQs
DDNet is a decentralized network for real-time collaborative applications.
We found that @describble/ddnet demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.