@himbo22/iroha-sdk-js
v0.1.1
Published
Framework-agnostic, browser-native SFU client SDK for Iroha.
Maintainers
Readme
Iroha SFU SDK
A browser-native TypeScript SDK for the Iroha SFU currently implemented in
D:\\go\\iroha. The runtime is framework-neutral and has zero production dependencies;
SvelteKit is only the local development workspace and capability demo.
What this SDK implements
- The Go server's exact JSON WebSocket envelope, including JSON-encoded SDP and ICE payloads.
- One signaling socket and exactly two peer connections per session:
- publisher — the browser creates offers; the SFU returns answers.
- subscriber — the SFU creates offers; the browser returns answers.
- Serialized publisher, subscriber, and signaling operations so concurrent browser callbacks cannot race SDP negotiation or WebSocket writes.
- Per-peer-connection ICE staging, including candidates that arrive before remote SDP.
- A bounded outgoing-signaling queue and bounded manual-subscription queue; automatic subscriptions drain serially rather than flooding the SFU.
- Cleanup that closes peer connections, rejects in-flight work, and closes signaling without stopping caller-owned media tracks.
Install and use
The package is configured for public npm publishing as iroha-sfu-sdk. Its public entry point is
ready for application use. Before the first release, add the final repository metadata and choose
the license that matches your project.
Use from another local project
Build and pack the SDK, then install the generated tarball in the consuming application. This works with Svelte, React, Vue, or plain TypeScript because the SDK runtime is framework-neutral.
Set-Location D:\svelte\iroha
pnpm run build
pnpm pack
Set-Location D:\svelte\my-app
pnpm add 'D:\svelte\iroha\iroha-sfu-sdk-0.1.0.tgz'The package is intentionally private, but local pnpm pack and pnpm add still work. Re-run
pnpm pack after SDK changes and reinstall the new tarball in the application.
For rapid development-only iteration, pnpm linking is also available:
Set-Location D:\svelte\iroha
pnpm run build
pnpm link --global
Set-Location D:\svelte\my-app
pnpm link --global iroha-sfu-sdkTarball installation is preferred for production-like testing because it matches the files that will eventually be published.
import { createIrohaSfuClient } from 'iroha-sfu-sdk';
const client = createIrohaSfuClient({
url: 'wss://sfu.example.com/ws',
// Production deployments should supply TURN as well as any STUN servers they operate.
rtcConfiguration: {
iceServers: [
{ urls: 'stun:stun.example.com:3478' },
{
urls: 'turns:turn.example.com:5349?transport=tcp',
username: 'short-lived-credential',
credential: 'short-lived-secret'
}
]
}
});
client.on('error', (error) => console.error(error));
client.on('published', ({ producerId, kind }) => {
console.log(`Published ${kind}: ${producerId}`);
});
client.on('producerAvailable', ({ producerId }) => {
// The current server requires explicit subscriptions. Handle failures in the UI.
void client.subscribe(producerId).catch(console.error);
});
client.on('track', ({ track, streams, producerId }) => {
const stream = streams[0] ?? new MediaStream([track]);
// Assign `stream` to an HTMLMediaElement's srcObject in your application.
console.log('Remote track', producerId, stream);
});
await client.connect();
const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
await client.publish(localStream);
// Stop locally owned tracks yourself when appropriate, then tear down the session.
await client.close();Register event handlers before connect(): the SFU can announce existing producers immediately
after it accepts a WebSocket.
Set autoSubscribe: true to request every announced remote producer automatically. This is
disabled by default so applications remain in control of bandwidth and presentation.
Operation semantics
connect()resolves only after the server'sjoinframe provides a participant ID.joinedand bufferedproducerAvailableevents are emitted only after that point.publish(streamOrTracks)batches new tracks into one publisher offer and resolves after the publisher answer is applied. Watchpublishedfor server-generated producer IDs.subscribe(producerId)resolves after the SDK sends the subscriber answer. The current server has no finalsubscription_readyacknowledgment, so it does not guarantee media has begun.close()is idempotent and does not stop media tracks supplied by the application.- A failed connection, terminal peer-connection state, or ambiguous subscription transaction closes the client. Create a new client to try again; there is no server resume protocol.
track.producerIdis best-effort because the server does not provide a stable SDP m-line or transaction mapping for tracks.
Current server-contract limits
These are server capabilities, not silently papered over by the SDK:
- The handler exposes
GET /wswith no authentication and currently puts every connection in the default room. There is no functionalroomIdSDK option. - There is no request/transaction ID, structured error event, subscription completion event, or reconnect/resume protocol. Create a new client after an unrecoverable connection failure.
unsubscribeis declared server-side but is not dispatched by the WebSocket handler, so this SDK intentionally has no publicunsubscribe()API.- A producer-close removal currently does not negotiate a fresh subscriber offer. Treat
producerClosedas a notification for application UI cleanup only: the browser receiver can stay live until the server serializes removal and sends anoffer/subscriberrenegotiation. - The server's built-in STUN configuration alone is not sufficient for dependable internet NAT
traversal. Pass a TURN-capable
rtcConfiguration; do not hard-code public TURN credentials.
Public API
createIrohaSfuClient(options) // returns IrohaSfuClient
client.connect(signal?)
client.publish(MediaStream | MediaStreamTrack | readonly MediaStreamTrack[])
client.subscribe(producerId)
client.close()
client.on('joined' | 'published' | 'producerAvailable' | 'producerClosed' | 'track' | 'error', fn)The package also exports the lower-level SfuClient, WebSocketTransport, Iroha wire-codec
helpers, and types for advanced integrations and deterministic testing.
Development
pnpm run dev # local Svelte capability demo
pnpm run check # TypeScript and Svelte diagnostics
pnpm run lint # ESLint
pnpm run test # unit tests
pnpm run build # package + demo production build
pnpm run validate # formatting, lint, types, tests, build, package smoke checkPublish to npm
The package name iroha-sfu-sdk was available when this project was prepared; npm names can be
claimed by someone else, so check it again immediately before publishing.
First, add a license field and LICENSE file, and add the repository URL to package.json.
Then authenticate and publish:
Set-Location D:\svelte\iroha
pnpm login
pnpm version patch
pnpm run release:check
pnpm publish --access public --provenanceUse pnpm version minor or pnpm version major when the API change requires it. After publishing,
anyone can install the SDK with:
pnpm add iroha-sfu-sdkFor CI publishing, configure npm trusted publishing or an NPM_TOKEN; do not commit credentials
to the repository. pnpm run release:check validates the exact package contents without uploading.
Dependency policy
Runtime dependencies are prohibited unless browser platform APIs cannot safely meet a concrete
requirement. The source runtime uses RTCPeerConnection, WebSocket, MediaStream, and
AbortSignal directly. Development tooling follows Svelte's official packaging path with
TypeScript, ESLint, Prettier, Vitest, and publint.
Before release, choose the npm scope and license, add repository metadata, test against a staging
Iroha SFU, run pnpm run release:check, and publish from protected CI with provenance.
