
Coroutine-first Socket.IO client exposing Flow/StateFlow/suspend APIs, in-house Engine.IO v4 / Socket.IO v5 codec, no third-party protocol/logging deps, WebSocket+polling, multiplexing, backoff reconnect, sealed errors.
A coroutine-first Socket.IO client for Kotlin Multiplatform — Android, iOS and JVM — with an in-house Engine.IO v4 / Socket.IO v5 implementation and no third-party protocol or logging dependencies.
implementation("io.github.adventures92:sockit:0.0.2")val client = SocketClient.connect(
"https://example.com",
socketOptions {
transports(Transports.WEBSOCKET)
auth { put("token", jwt) }
},
)
val socket = client.namespace()
launch { socket.connectionState.collect(::render) }
launch { socket.events("quote").collect(::handleQuote) }
socket.openAwait()
socket.emit(Subscribe(buildJsonObject { put("pair", "BTC-INR") }))📖 Documentation · API reference
| Sockit | Typical alternatives | |
|---|---|---|
| Targets | Android + iOS + JVM, one codebase | JS socket.io-client wrappers, JVM-only clients |
| API |
StateFlow / Flow / suspend
|
Callback on / emit
|
| Protocol | In-house Engine.IO 4 / Socket.IO 5 codec | Third-party protocol stacks |
| Dependencies |
kotlinx-* + Ktor only |
Mixed logging / protocol stacks |
| Threading | Single serial worker — no upgrade/drain/close races | Varies |
Transports are polling and WebSocket with automatic upgrade, multiplexed per origin, with
exponential-backoff reconnect, binary attachments, server-initiated acks and a sealed error model.
Verified against the official socket.io-protocol test vectors and a live socket.io 4.5.4 –
4.8.1 server matrix on every pull request.
| Module | Purpose |
|---|---|
socketio/ |
The library. The only published artifact. |
shared/ |
Compose Multiplatform demo — also the consumer-encapsulation gate that proves internal types cannot leak. |
androidApp/ |
Android demo entry point. |
iosApp/ |
iOS demo entry point (Xcode). |
docs/ |
Design system of record — architecture, diagrams, conformance & maintenance. |
Requires JDK 17+ and the Android SDK. Everything runs through the Gradle wrapper.
# Quality gates — run before considering any :socketio change done
./gradlew :socketio:apiCheck spotlessCheck :socketio:detekt
# Unit + protocol tests (no server needed)
./gradlew :socketio:jvmTest --tests "dev.adven.sockit.protocol.*"
# Full JVM suite — spawns the bundled Node echo server itself
cd socketio/src/jvmTest/resources && npm ci && cd -
./gradlew :socketio:jvmTest
# Platform smoke (simulator / device required)
./gradlew :socketio:iosSimulatorArm64Test
./gradlew :socketio:connectedAndroidDeviceTest
# API reference
./gradlew :socketio:dokkaGeneratePublicationHtml # → socketio/build/dokka/html/Formatting is spotless + ktlint (./gradlew spotlessApply); static analysis is detekt at
maxIssues: 0. Any change to the public api/ package needs a matching
./gradlew :socketio:apiDump.
./gradlew :androidApp:assembleDebug # Android
# iOS: open iosApp/ in Xcode and runFull wire/FSM logs are compiled out of release builds. For local library development:
./scripts/toggle-socketio-internal-logging.sh on # or off / status / (no arg = flip)
./gradlew :androidApp:installDebug # rebuild — the flag is compile-timeThe script writes gradle/socketio-dev.local.properties (gitignored); every Gradle build reads it
automatically. One-off override: ./gradlew -Psocketio.internalLogging=false …. Logs land in
Logcat on Android, the Xcode console on iOS, and stdout under jvmTest.
Consumer-facing logging is separate and sanitized — Logger.essential { … } via
socketOptions { logger = … }, single tag SocketIO, no URLs, tokens or payloads. See
logging.
Issues and pull requests are welcome. See CONTRIBUTING.md for the workflow and the gates a change has to pass.
Apache 2.0 — see acknowledgements for prior art this client was studied against.
A coroutine-first Socket.IO client for Kotlin Multiplatform — Android, iOS and JVM — with an in-house Engine.IO v4 / Socket.IO v5 implementation and no third-party protocol or logging dependencies.
implementation("io.github.adventures92:sockit:0.0.2")val client = SocketClient.connect(
"https://example.com",
socketOptions {
transports(Transports.WEBSOCKET)
auth { put("token", jwt) }
},
)
val socket = client.namespace()
launch { socket.connectionState.collect(::render) }
launch { socket.events("quote").collect(::handleQuote) }
socket.openAwait()
socket.emit(Subscribe(buildJsonObject { put("pair", "BTC-INR") }))📖 Documentation · API reference
| Sockit | Typical alternatives | |
|---|---|---|
| Targets | Android + iOS + JVM, one codebase | JS socket.io-client wrappers, JVM-only clients |
| API |
StateFlow / Flow / suspend
|
Callback on / emit
|
| Protocol | In-house Engine.IO 4 / Socket.IO 5 codec | Third-party protocol stacks |
| Dependencies |
kotlinx-* + Ktor only |
Mixed logging / protocol stacks |
| Threading | Single serial worker — no upgrade/drain/close races | Varies |
Transports are polling and WebSocket with automatic upgrade, multiplexed per origin, with
exponential-backoff reconnect, binary attachments, server-initiated acks and a sealed error model.
Verified against the official socket.io-protocol test vectors and a live socket.io 4.5.4 –
4.8.1 server matrix on every pull request.
| Module | Purpose |
|---|---|
socketio/ |
The library. The only published artifact. |
shared/ |
Compose Multiplatform demo — also the consumer-encapsulation gate that proves internal types cannot leak. |
androidApp/ |
Android demo entry point. |
iosApp/ |
iOS demo entry point (Xcode). |
docs/ |
Design system of record — architecture, diagrams, conformance & maintenance. |
Requires JDK 17+ and the Android SDK. Everything runs through the Gradle wrapper.
# Quality gates — run before considering any :socketio change done
./gradlew :socketio:apiCheck spotlessCheck :socketio:detekt
# Unit + protocol tests (no server needed)
./gradlew :socketio:jvmTest --tests "dev.adven.sockit.protocol.*"
# Full JVM suite — spawns the bundled Node echo server itself
cd socketio/src/jvmTest/resources && npm ci && cd -
./gradlew :socketio:jvmTest
# Platform smoke (simulator / device required)
./gradlew :socketio:iosSimulatorArm64Test
./gradlew :socketio:connectedAndroidDeviceTest
# API reference
./gradlew :socketio:dokkaGeneratePublicationHtml # → socketio/build/dokka/html/Formatting is spotless + ktlint (./gradlew spotlessApply); static analysis is detekt at
maxIssues: 0. Any change to the public api/ package needs a matching
./gradlew :socketio:apiDump.
./gradlew :androidApp:assembleDebug # Android
# iOS: open iosApp/ in Xcode and runFull wire/FSM logs are compiled out of release builds. For local library development:
./scripts/toggle-socketio-internal-logging.sh on # or off / status / (no arg = flip)
./gradlew :androidApp:installDebug # rebuild — the flag is compile-timeThe script writes gradle/socketio-dev.local.properties (gitignored); every Gradle build reads it
automatically. One-off override: ./gradlew -Psocketio.internalLogging=false …. Logs land in
Logcat on Android, the Xcode console on iOS, and stdout under jvmTest.
Consumer-facing logging is separate and sanitized — Logger.essential { … } via
socketOptions { logger = … }, single tag SocketIO, no URLs, tokens or payloads. See
logging.
Issues and pull requests are welcome. See CONTRIBUTING.md for the workflow and the gates a change has to pass.
Apache 2.0 — see acknowledgements for prior art this client was studied against.