Compare commits

...
Author SHA1 Message Date
Adrien Beraud 441e26c897 docker: use ninja for DockerfileAlpine 2026-11-11 20:56:37 -05:00
Adrien Beraud 95ed2a4207 docker: add simdutf to DockerfileAlpine 2026-11-11 20:51:28 -05:00
Adrien Beraud 7f6e57afbf build: remove redundant license-file from cargo 2026-11-11 20:51:28 -05:00
Adrien BeraudandCopilot 6183600c89 docs: focus Node.js README on npm users
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-04 00:05:27 -05:00
Adrien BeraudandCopilot dff27203a4 build: prepare 4.5.0 release candidate 1
Co-authored-by: Copilot <223556219+Copilot@users.nply.github.com>
2026-11-03 22:48:09 -05:00
Adrien BeraudandCopilot 506d9f9cbb ci: install MessagePack C++ headers on Ubuntu
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-03 22:44:50 -05:00
dependabot[bot] 349f4e5fc6 build(deps): bump pypa/cibuildwheel from 4.3.4 to 4.3.5
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v4.3.4...v4.3.5)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 4.3.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 22:41:04 -05:00
dependabot[bot] 11d69d02e8 build(deps): bump actions/setup-node from 6 to 7
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 22:40:02 -05:00
13 changed files with 192 additions and 113 deletions

No files matched your search

+3 -3
View File
@@ -4,9 +4,9 @@ env:
LLHTTP_VERSION: "v9.2.1"
RESTINIO_VERSION: "0.7.10"
EXPECTED_LITE_URL: "https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp"
UBUNTU_FULL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
UBUNTU_MESON_DEPS: "ninja-build libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-dev python3-setuptools python3-pip libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
UBUNTU_MINIMAL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libfmt-dev libgnutls28-dev libcppunit-dev libmsgpack-dev libargon2-dev"
UBUNTU_FULL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-cxx-dev libargon2-dev"
UBUNTU_MESON_DEPS: "ninja-build libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-dev python3-setuptools python3-pip libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-cxx-dev libargon2-dev"
UBUNTU_MINIMAL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libfmt-dev libgnutls28-dev libcppunit-dev libmsgpack-cxx-dev libargon2-dev"
DEBIAN13_DEPS: "git libtool pkg-config wget cmake libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-cxx-dev libargon2-dev"
on: [push, pull_request]
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
sudo apt update && \
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
libfmt-dev libmsgpack-dev libargon2-dev libasio-dev \
libfmt-dev libmsgpack-cxx-dev libargon2-dev libasio-dev \
llvm llvm-dev clang clang-tools && \
sudo apt remove gcc g++
+3 -3
View File
@@ -64,7 +64,7 @@ jobs:
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg-binary-cache,readwrite
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: '22'
cache: npm
@@ -151,7 +151,7 @@ jobs:
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: '22'
- uses: actions/download-artifact@v8
@@ -194,7 +194,7 @@ jobs:
node: ['22', '24', '26']
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node }}
- uses: actions/download-artifact@v8
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
# Run locally with: pipx run cibuildwheel --platform linux python
- name: Build wheels
uses: pypa/cibuildwheel@v4.3.4
uses: pypa/cibuildwheel@v4.3.5
with:
package-dir: python
+2 -1
View File
@@ -599,6 +599,7 @@ jobs:
uses: softprops/action-gh-release@v3
with:
draft: true
prerelease: ${{ contains(github.ref_name, '-') }}
files: |
downloaded_artifacts/windows_msi/*.msi
downloaded_artifacts/static_dhtnode/**/*dhtnode.exe
@@ -616,7 +617,7 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: '24'
registry-url: https://registry.npmjs.org/
+4 -4
View File
@@ -10,10 +10,10 @@ if(POLICY CMP0167)
endif()
set (opendht_VERSION_MAJOR 4)
set (opendht_VERSION_MINOR 4.99)
set (opendht_VERSION_MINOR 5.0)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
set (PACKAGE_VERSION "${opendht_VERSION}-rc.1")
set (VERSION "${PACKAGE_VERSION}")
project (opendht
VERSION ${opendht_VERSION}
DESCRIPTION "OpenDHT: A lightweight C++17 Distributed Hash Table library."
@@ -421,7 +421,7 @@ else ()
endif ()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_NO_BOOST -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
add_definitions(-DPACKAGE_VERSION="${opendht_VERSION}")
add_definitions(-DPACKAGE_VERSION="${PACKAGE_VERSION}")
if (ASIO_INCLUDE_DIR)
include_directories (SYSTEM "${ASIO_INCLUDE_DIR}")
+4 -3
View File
@@ -8,9 +8,9 @@ RUN mkdir /install
ENV DESTDIR=/install
RUN cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
&& cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=Off \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
@@ -19,7 +19,7 @@ RUN cd opendht && mkdir build && cd build \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install
&& ninja && ninja install
FROM alpine:3.24 AS install
COPY --from=build /install /
@@ -32,6 +32,7 @@ RUN apk add --no-cache \
jsoncpp \
llhttp \
fmt \
simdutf \
readline \
ncurses
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
+1 -1
View File
@@ -10,7 +10,7 @@ ENV DESTDIR=/install
RUN cd opendht && mkdir build && cd build \
&& cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=/usr \
-DOPENDHT_DOWNLOAD_DEPS=Off \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
+7 -2
View File
@@ -5,7 +5,7 @@ project(
'cython',
license: 'MIT',
license_files: 'LICENSE',
version: '4.4.99',
version: '4.5.0-rc.1',
meson_version: '>=1.1.0',
default_options: ['cpp_std=c++20', 'warning_level=3'],
)
@@ -55,7 +55,12 @@ if host_machine.system() == 'linux' and io_uring.found()
endif
conf_data = configuration_data()
add_project_arguments('-DMSGPACK_NO_BOOST', '-DASIO_STANDALONE', language: 'cpp')
add_project_arguments(
'-DMSGPACK_NO_BOOST',
'-DASIO_STANDALONE',
'-DPACKAGE_VERSION="' + meson.project_version() + '"',
language: 'cpp',
)
if io_uring.found()
add_project_arguments('-DASIO_HAS_IO_URING', '-DASIO_DISABLE_EPOLL', language: 'cpp')
conf_data.set('iouring_lib', ', liburing')
+108
View File
@@ -0,0 +1,108 @@
# Building and Testing the Node.js Package
The `opendht` npm package bundles native binaries for supported platforms.
Applications can install it directly as shown in the [README](README.md).
This guide covers building the Node-API addon from an OpenDHT source checkout,
testing changes, and packaging binaries.
## Prerequisites
Install the native dependencies described in the
[OpenDHT build guide](../BUILD.md), plus Node.js 22.9 or later, a C++17 compiler,
and CMake 3.21 or later. Ninja is optional. The bindings use `node-addon-api` and
target Node-API version 8.
Proxy-client support defaults to enabled and requires ASIO, llhttp, RESTinio,
and expected-lite headers.
## Build and Test
From the root of an OpenDHT source checkout:
```sh
cd nodejs
npm ci
npm run build
npm test
npm run typecheck
```
CMake.js builds OpenDHT from the parent source directory in `nodejs/build/native`.
It does not change the repository's existing build directory. Tools, Python,
peer discovery, documentation, and native tests default to disabled in this build.
Native CMake options can be passed through, for example:
```sh
npm run build -- --CDOPENDHT_PEER_DISCOVERY=ON
```
For an existing build, change cached options directly with CMake from the
`nodejs` directory, then rebuild:
```sh
cmake -S . -B build -DOPENDHT_PROXY_CLIENT=ON
npm run build
```
A custom build can disable proxy support with `-DOPENDHT_PROXY_CLIENT=OFF`;
requesting a proxy then throws an explicit unsupported-build error.
The loader checks local builds, then compatible Node-API binaries under
`prebuilds/`. Set `OPENDHT_NODE_BINDING` to an absolute addon path to select an
explicit build.
## Run the Example
From the `nodejs` directory after building:
```sh
npm run dhtnode -- --port 0 --bootstrap bootstrap.jami.net
```
The interactive node supports get, put, signed put, and value subscriptions.
Run `npm run dhtnode -- --help` for networking options.
## Package and Test Binaries
From a successful Release build in the `nodejs` directory:
```sh
npm run package
npm run test:package
```
`bundle` copies the addon into `prebuilds/<platform>-<arch>/`, gathers its runtime
dependencies, rewrites native loader paths, and copies dependency license
notices. macOS needs `dylibbundler` and Apple developer tools; Linux needs
`patchelf` and Debian/Ubuntu dependency copyright files. Windows uses the vcpkg
installed tree (`VCPKG_INSTALLED_DIR`, `VCPKG_DEFAULT_TRIPLET`) and MSVC tools.
`OPENDHT_LIBRARY_PATH` adds native library search directories when bundling.
An explicit addon path may be passed to `npm run bundle -- /absolute/addon.node`.
Bundling replaces only the current platform's generated prebuild directory.
`test:package` creates an npm archive, installs it in a temporary consumer with
install scripts disabled and no dev dependencies, forces prebuild-only loading,
and runs the full runtime suite. Pass an archive file or a directory containing
one archive to test it directly, for example `npm run test:package -- dist`.
Only runtime JS, declarations, the example's TypeScript source, documentation,
and prebuilds are included in the archive. `prepack` compiles the example, so
archive creation needs the development dependencies; archive installation does not.
Review the included dependency licenses and source-distribution obligations
before redistributing binaries.
## CI
The [Node.js package workflow](../.github/workflows/nodejs-package.yml) builds:
| Target | Build baseline |
|--------|----------------|
| Linux x64 | Ubuntu 24.04 / glibc 2.39 (Noble dependency image) |
| macOS ARM64 and x64 | macOS 15 |
| Windows x64 | Windows Server 2022 / MSVC |
CI combines platform prebuilds into one npm archive and verifies that archive on
Node 22, 24, and 26 on each platform, including Ubuntu 24.04 and 26.04. Branch
pushes, pull requests, and manual runs build and test without publishing.
musl/Alpine and other architectures are not currently built. Node-API stability
does not remove OS/libc or native dependency compatibility requirements.
+57 -92
View File
@@ -1,75 +1,75 @@
# OpenDHT Node.js Bindings
# OpenDHT: a Distributed Hash Table
Initial Node-API bindings using `node-addon-api` directly over the C++ library.
Node.js 22.9 or later is required; the addon targets Node-API version 8.
OpenDHT is a Kademlia-based distributed hash table for storing and retrieving
small values over a peer-to-peer network without a central server. Common uses
include peer discovery, service announcements, and decentralized applications.
## Install
The `opendht` npm package provides Node.js bindings to
[OpenDHT](https://opendht.net), with promises, async iterators, and TypeScript
declarations. It supports value subscriptions, signed and encrypted values, and
direct or HTTP(S) proxy connections.
## Get Started
Install with Node.js 22.9 or later:
```sh
npm install opendht
```
## Build
The package uses ES modules. Packaged binaries include OpenDHT and its non-system
native dependencies; no compiler or separate OpenDHT installation is needed on
supported platforms:
Install the native dependencies described in [BUILD.md](../BUILD.md), plus Node.js,
a C++17 compiler, and CMake 3.21 or later. Ninja is optional. Proxy-client support
defaults to enabled and requires ASIO, llhttp, RESTinio, and expected-lite headers.
| Platform | Binary baseline |
|----------|-----------------|
| Linux x64 | Ubuntu 24.04 / glibc 2.39 |
| macOS ARM64 and x64 | macOS 15 |
| Windows x64 | Windows Server 2022 / MSVC |
```sh
cd nodejs
npm ci
npm run build
npm test
npm run typecheck
```
Alpine/musl and other architectures are not currently bundled. Binaries target
Node-API version 8, but still require a compatible OS and libc. For source builds
or custom native options, see the
[build and test guide](https://github.com/savoirfairelinux/opendht/blob/master/nodejs/BUILD.md).
CMake.js builds OpenDHT from the parent source directory in `nodejs/build/native`.
It does not change the repository's existing build directory. Tools, Python,
peer discovery, documentation, and native tests default to disabled in this build.
Native CMake options can be passed through, for example:
`DhtRunner` manages a node, `hash()` turns an application key into a DHT key, and
values carry a binary payload and metadata. `put()` publishes values, `get()`
retrieves them, and `listen()` subscribes to updates and expiration events.
```sh
npm run build -- --CDOPENDHT_PEER_DISCOVERY=ON
```
For an existing build, change cached options directly with CMake, for example
`cmake -S . -B build -DOPENDHT_PROXY_CLIENT=ON`, then rebuild. A custom build can
disable proxy support with `-DOPENDHT_PROXY_CLIENT=OFF`; requesting a proxy then
throws an explicit unsupported-build error.
The loader checks local builds, then compatible Node-API binaries under `prebuilds/`.
Set `OPENDHT_NODE_BINDING` to an absolute addon path to select an explicit build.
Packaged binaries include OpenDHT and non-system native dependencies, so archive
installation does not require a compiler or a system OpenDHT installation.
## Usage
Save this example as `hello.mjs` and run it with `node hello.mjs`. It starts a
node on an OS-assigned port, bootstraps into the public network, publishes a
value, and reads it back.
```js
import { DhtRunner, hash } from 'opendht';
async function main() {
const writer = new DhtRunner();
const reader = new DhtRunner();
const runner = new DhtRunner();
try {
writer.run({ port: 0, ipv4: '127.0.0.1', ipv6: '::1' });
reader.run({ port: 0, ipv4: '127.0.0.1', ipv6: '::1' });
writer.bootstrap('127.0.0.1', reader.getBoundPort());
reader.bootstrap('127.0.0.1', writer.getBoundPort());
const key = hash('example');
const stored = await writer.put(key, Buffer.from('hello'), { id: 42n });
runner.run({ port: 0 });
runner.bootstrap('bootstrap.jami.net', 4222);
const key = hash('my-app/hello');
const stored = await runner.put(key, Buffer.from('Hello from Node.js!'));
if (!stored) throw new Error('DHT put failed');
for await (const value of reader.get(key)) {
for await (const value of runner.get(key)) {
console.log(value.id, value.data.toString());
}
} finally {
await Promise.all([writer.close(), reader.close()]);
await runner.close();
}
}
main().catch(console.error);
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
```
## API
A bootstrap server supplies initial peers. Applications can use public bootstrap
servers or known peers on a private network. Values expire, and their availability
depends on participating nodes; the DHT does not provide durable storage guarantees.
## Working With Values
- `hash(string | Uint8Array)` returns a SHA-1 hash as a 40-character hex string.
All get/put/listen keys must be hex hashes, not unhashed application keys.
@@ -116,7 +116,7 @@ The binding does not cap the callback queue, accumulated `getAll()` results, or
iterator buffers. Slow iterator consumers can accumulate values without
backpressure. Queued callbacks retain their native values until delivery or cleanup.
## Async Iteration
## Subscriptions and Async Iteration
`get()` and callback-free `listen()` start immediately and return iterators with
`next()`, `return()`, `throw()`, `cancel()`, and `Symbol.asyncDispose`.
@@ -137,7 +137,7 @@ for await (const { value, expired } of runner.listen(hash('updates'))) {
}
```
## Proxy Configuration
## Using a Proxy
Pass the URL of an OpenDHT HTTP(S) proxy at startup:
@@ -154,7 +154,7 @@ The node does not bind UDP sockets in this mode; `port`, `ipv4`, `ipv6`, and
for direct networking. Proxy settings are startup-only; create a new runner to
change transports or servers. Packaged binaries include proxy-client support.
## Crypto
## Signed and Encrypted Values
`PrivateKey.generate(options)` and `Identity.generate(name, options)` return
promises and generate keys off the JS thread. Options accept `algorithm: 'ec'`
@@ -197,47 +197,12 @@ mismatched identities, and unsupported encryption keys raise JS exceptions.
Only generation is asynchronous; import/export/sign/encrypt/decrypt are
synchronous and should be used from worker threads for large workloads.
## Packaging And CI
From a successful Release build:
```sh
npm run package
npm run test:package
```
`bundle` copies the addon into `prebuilds/<platform>-<arch>/`, gathers its runtime
dependencies, rewrites native loader paths, and copies dependency license
notices. macOS needs `dylibbundler` and Apple developer tools; Linux needs
`patchelf` and Debian/Ubuntu dependency copyright files. Windows uses the vcpkg
installed tree (`VCPKG_INSTALLED_DIR`, `VCPKG_DEFAULT_TRIPLET`) and MSVC tools.
`OPENDHT_LIBRARY_PATH` adds native library search directories when bundling.
An explicit addon path may be passed to `npm run bundle -- /absolute/addon.node`.
Bundling replaces only the current platform's generated prebuild directory.
`test:package` creates an npm archive, installs it in a temporary consumer with
install scripts disabled and no dev dependencies, forces prebuild-only loading,
and runs the full runtime suite. Pass an archive file or a directory containing
one archive to test it directly, for example `npm run test:package -- dist`.
Only runtime JS, declarations, the example's TypeScript source, documentation,
and prebuilds are included in the archive. `prepack` compiles the example, so
archive creation needs the development dependencies; archive installation does not.
The [Node.js package workflow](../.github/workflows/nodejs-package.yml) builds:
| Target | Build Baseline |
| --- | --- |
| Linux x64 | Ubuntu 24.04 / glibc 2.39 (Noble dependency image) |
| macOS ARM64 and x64 | macOS 15 |
| Windows x64 | Windows Server 2022 / MSVC |
CI combines platform prebuilds into one npm archive and verifies that archive on
Node 22, 24, and 26 on each platform, including Ubuntu 24.04 and 26.04. Branch
pushes, pull requests, and manual runs build and test without publishing.
musl/Alpine and other architectures are not currently built. Node-API stability
does not remove OS/libc or native dependency compatibility requirements. Review
the included dependency licenses and source-distribution obligations before
redistributing binaries.
Query filters, AbortSignal support, certificate trust-store validation, CA
issuance controls, and runtime proxy switching remain future work.
issuance controls, and runtime proxy switching remain future work.
## Learn More
- [TypeScript API declarations](https://github.com/savoirfairelinux/opendht/blob/master/nodejs/index.d.ts)
- [Interactive node example](https://github.com/savoirfairelinux/opendht/blob/master/nodejs/examples/dhtnode.ts)
- [Build, test, and packaging guide](https://github.com/savoirfairelinux/opendht/blob/master/nodejs/BUILD.md)
- [OpenDHT project and issue tracker](https://github.com/savoirfairelinux/opendht)
-1
View File
@@ -5,7 +5,6 @@ authors = ["Sébastien Blin <sebastien.blin@savoirfairelinux.com>", "Adrien Bera
edition = "2024"
description = "Rust bindings for OpenDHT"
license = "MIT"
license-file = "../LICENSE"
repository = "https://github.com/savoirfairelinux/opendht"
[features]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "opendht",
"version-string": "4.4.99",
"version-string": "4.5.0-rc.1",
"port-version": 1,
"description": "OpenDHT: A lightweight C++17 Distributed Hash Table library.",
"homepage": "https://opendht.net",