Skip to content

build!: split into core + per-transport modules (#27, #28, #29)#60

Draft
jamesarich wants to merge 2 commits into
mainfrom
claude/address-issues-27-28-29
Draft

build!: split into core + per-transport modules (#27, #28, #29)#60
jamesarich wants to merge 2 commits into
mainfrom
claude/address-issues-27-28-29

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Addresses the three actionable open issues by restructuring the library along the transport boundary, following the org's flagship meshtastic-sdk as prior art.

What changed

#27 — split :library into per-transport modules

  • :core (org.meshtastic:mqtt-client-core) — all protocol logic + the transport SPI
  • :transport-tcp (…-transport-tcp) — TcpTransport (ktor-network + TLS); every target except browser
  • :transport-ws (…-transport-ws) — WebSocketTransport; every target incl. wasmJs
  • :bom (mqtt-client-bom) — java-platform BOM pinning the above
  • build-logic convention plugins (mqtt.kmp.library, mqtt.publishing); root-level Dokka + Kover aggregation

Breaking: the transport seam is now a public SPI. MqttTransport + the new MqttTransportFactory (with a + combinator) are public; the expect/actual createPlatformTransport factory is removed. Consumers set MqttConfig.Builder.transportFactory. VariableByteInt is public so transports can frame packets. This was the unavoidable consequence I flagged before starting — a clean Gradle-module split is impossible while MqttTransport stays internal and selection runs through within-module expect/actual. meshtastic-sdk resolves it the same way (public RadioTransport).

#29 — Konsist architecture rules (reshaped to the new boundary)

  • Public-API allowlist for :core; MqttPacket internality + data class/val invariants
  • Config-time guard that :core declares no dependency on a transport module
  • Kept in :core jvmTest — the issue's "move to commonTest" is not viable (Konsist is JVM-only). Dropped the obsolete "MqttTransport internal" rule and the misleading no-println KDoc; skipped the issue comment's Mutex ban (it contradicts this repo).

#28 — ADRs 0006–0010

Multi-module distribution + public SPI (supersedes 0001), Mutex send serialization, public-API allowlist, dual 3.1.1/5.0 support (replaces the stale "no 3.1.1 retrofit" premise — 3.1.1 already ships), packet-ID allocation. Plus README / AGENTS / CHANGELOG / CI updates.

Verification (local, macOS host)

Green: :core:jvmTest (unit + Konsist), spotlessCheck, detekt, apiCheck (new per-module baselines), koverVerify (≥80% aggregate), and cross-target compiles for wasmJs, macosArm64, and the sample. Native linuxX64/mingwX64 cross-compiles are left to CI.

Closes #27
Closes #28
Closes #29

🤖 Generated with Claude Code

jamesarich and others added 2 commits June 13, 2026 14:50
Replace the single org.meshtastic:mqtt-client artifact with a transport-free
:core plus per-transport modules and a BOM, mirroring the meshtastic-sdk house
pattern (Closes #27):

- :core (mqtt-client-core)            — all protocol logic + the transport SPI
- :transport-tcp (…-transport-tcp)    — TcpTransport (ktor-network + TLS), no wasmJs
- :transport-ws  (…-transport-ws)     — WebSocketTransport, all targets incl. browser
- :bom (mqtt-client-bom)              — java-platform BOM pinning the above
- build-logic/convention              — mqtt.kmp.library + mqtt.publishing plugins

BREAKING: the transport seam is now a public SPI. MqttTransport and the new
MqttTransportFactory (with a `+` combinator) are public; the expect/actual
createPlatformTransport factory is removed. Consumers set
MqttConfig.Builder.transportFactory (e.g. TcpTransportFactory()). VariableByteInt
is public so transport modules can frame packets.

Reshape the Konsist architecture suite to the new boundary (Closes #29): public-API
allowlist for :core, MqttPacket internality + data-class/val invariants, and a
config-time guard that :core declares no dependency on a transport module. Drops
the obsolete "MqttTransport internal" rule and the misleading no-println KDoc.

Update root build (Dokka/Kover aggregation), settings, gradle.properties, the
version catalog, the sample (core + both transports), and CI task references.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record the load-bearing decisions as ADRs in the existing Nygard format (Closes #28):

- 0006 Multi-module distribution with a public transport SPI (supersedes 0001's
  internal/expect-actual packaging)
- 0007 Single-Mutex send serialization
- 0008 Internal-by-default with an explicit public-API allowlist
- 0009 Dual MQTT 3.1.1 + 5.0 support with automatic fallback (replaces the issue's
  stale "no 3.1.1 retrofit" premise — 3.1.1 already ships)
- 0010 Monotonic, Mutex-guarded packet-ID allocation

Mark 0001 partially superseded by 0006 and refresh the ADR index. Update README
(install via BOM + per-transport modules, public transport SPI, transportFactory in
every runnable example), AGENTS.md (module layout, publishing, internal-by-default
rule), and CHANGELOG (breaking-change + migration notes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant