Skip to content

refactor: add native transport seam under IRC client#3

Open
louzt wants to merge 2 commits into
obbyworld:mainfrom
louzt:feat/native-transport-seam
Open

refactor: add native transport seam under IRC client#3
louzt wants to merge 2 commits into
obbyworld:mainfrom
louzt:feat/native-transport-seam

Conversation

@louzt
Copy link
Copy Markdown

@louzt louzt commented Apr 23, 2026

Summary

This PR introduces a native socket transport seam under tobby's IRC client so future non-TCP transport work can be integrated without coupling the UI/store/IRC layers to any external transport engine repository.

What this changes

  • replaces direct NodeTCPSocket construction inside IRCClient.connect() with an injectable SocketTransportFactory
  • keeps the current TCP/TLS behavior as the default implementation
  • adds focused unit tests for the transport seam
  • adds a single ARCHITECTURE.md with Mermaid diagrams showing the current layering and the intended native transport evolution path

Why this matters

Today tobby is hard-wired to raw TCP/TLS at the point where the IRC client opens its byte transport.

That makes experimentation with a native overlay transport unnecessarily invasive.
This PR keeps the existing behavior intact while creating a narrow integration seam for future transport implementations.

Non-goals

  • no transport behavior change yet
  • no QUIC implementation in this PR
  • no dependency on an external engine crate or repository

Verification

  • bun x vitest run tests/unit/socketTransport.test.ts tests/nodeTcpSocket.test.ts
  • bun run typecheck

Note

The existing Husky hook in this repo currently calls bunx, which is not available in this environment. The code in this PR was validated explicitly with the commands above.

Summary by CodeRabbit

  • Documentation

    • Added comprehensive architecture docs and a README pointer explaining the system layering and transport seam for future native transports.
  • Refactor

    • Introduced a configurable socket transport abstraction so transports can be swapped without changing the IRC layer.
  • Tests

    • Added unit tests verifying transport factory injection, default behavior, and reset functionality.

Replace the hardcoded NodeTCPSocket construction with an injectable socket transport factory so future native transport work can be integrated without making the IRC/UI layers depend on an external engine repository.\n\nAlso adds ARCHITECTURE.md with Mermaid diagrams and focused tests covering the new seam.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55489ca1-004d-49d9-9f9b-7288f6b78af2

📥 Commits

Reviewing files that changed from the base of the PR and between a18dc39 and 6b35f0d.

📒 Files selected for processing (1)
  • tests/unit/socketTransport.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/socketTransport.test.ts

📝 Walkthrough

Walkthrough

Introduces a transport-abstraction for sockets: extracts ISocket types, adds a configurable SocketTransportFactory with runtime injection/reset, updates the IRC client to use the factory, and adds architecture docs and tests to validate custom transport injection and default restoration. (48 words)

Changes

Cohort / File(s) Summary
Architecture & Docs
ARCHITECTURE.md, README.md
Adds ARCHITECTURE.md describing transport-agnostic IRC layering and references it from README.md.
Socket Types
src/lib/socketTypes.ts
Introduces ISocket, SocketTransportContext, and SocketTransportFactory type declarations used across the transport seam.
Socket Transport Factory
src/lib/socketTransport.ts
New module implementing a configurable factory: createSocketTransport(url), setSocketTransportFactory(), resetSocketTransportFactory(); re-exports socket types.
Node TCP Socket
src/lib/nodeTcpSocket.ts
Removes in-file ISocket declaration and imports ISocket from src/lib/socketTypes.ts; NodeTCPSocket behavior unchanged.
IRC Client Integration
src/utils/ircClient.ts
Replaces direct NodeTCPSocket instantiation with createSocketTransport(url); event wiring unchanged.
Tests
tests/unit/socketTransport.test.ts
Adds tests for custom factory injection, argument passing, and resetSocketTransportFactory() restoring default NodeTCPSocket behavior (including host/port parsing check).

Sequence Diagram

sequenceDiagram
    participant IRC as IRCClient
    participant Factory as SocketTransportFactory
    participant NodeTCP as NodeTCPSocket
    participant ISocket as ISocket

    IRC->>Factory: createSocketTransport(url)
    Factory->>NodeTCP: instantiate with parsed host/port (default)
    Factory-->>IRC: returns ISocket
    IRC->>ISocket: attach onopen/onmessage/onerror/onclose
    IRC->>ISocket: send(data) / close()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped in code, a tiny tweak,

sockets freed from a rigid teak.
Factories bloom, transports may roam,
IRC keeps its cozy home.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: add native transport seam under IRC client' directly and specifically describes the main structural change: introducing a transport abstraction layer beneath the IRC client to enable future transport flexibility.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/lib/socketTransport.ts (1)

1-20: LGTM — simple seam with proper lifecycle controls.

Default factory, override, and reset cover the immediate needs, and the re-exports keep consumer imports consolidated. One optional thought for later: the mutable module-level socketTransportFactory is a fine seam today, but if you ever need per-client isolation (e.g., one IRC connection with a fake transport while another keeps TCP, or parallelized integration tests without afterEach discipline), promoting this to a small class or a per-IRCClient injection point would avoid cross-cutting state. Not necessary for this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/socketTransport.ts` around lines 1 - 20, The current module-level
mutable socketTransportFactory (used by createSocketTransport,
setSocketTransportFactory, resetSocketTransportFactory and
defaultSocketTransportFactory/NodeTCPSocket) prevents per-client isolation; to
support per-client injection, add an optional SocketTransportFactory parameter
to the public API that needs it (e.g., the IRCClient constructor or
createSocketTransport signature) and thread that factory through to where
sockets are created instead of reading the module-level socketTransportFactory,
leaving the existing setters as test/global conveniences; ensure the new
consumer-facing API accepts a SocketTransportFactory and falls back to
defaultSocketTransportFactory when undefined.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/socketTransport.test.ts`:
- Around line 34-44: The test currently triggers a real TCP connect via
NodeTCPSocket's constructor; instead stub out net.connect (and tls.connect if
needed) before calling createSocketTransport so the constructor doesn't dial
out: use jest.spyOn(require('net'), 'connect').mockImplementation(() => ({ on:
() => {}, once: () => {}, end: () => {}, destroy: () => {} })) (and similarly
stub tls.connect if TLS paths are exercised), call
resetSocketTransportFactory(), run
createSocketTransport('irc://127.0.0.1:65535') to assert it returns a
NodeTCPSocket without real network I/O, then restore the spies; reference
setSocketTransportFactory, resetSocketTransportFactory, createSocketTransport,
and NodeTCPSocket to locate code.

---

Nitpick comments:
In `@src/lib/socketTransport.ts`:
- Around line 1-20: The current module-level mutable socketTransportFactory
(used by createSocketTransport, setSocketTransportFactory,
resetSocketTransportFactory and defaultSocketTransportFactory/NodeTCPSocket)
prevents per-client isolation; to support per-client injection, add an optional
SocketTransportFactory parameter to the public API that needs it (e.g., the
IRCClient constructor or createSocketTransport signature) and thread that
factory through to where sockets are created instead of reading the module-level
socketTransportFactory, leaving the existing setters as test/global
conveniences; ensure the new consumer-facing API accepts a
SocketTransportFactory and falls back to defaultSocketTransportFactory when
undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f59c0416-e400-4206-be21-8c6a28e9b9d8

📥 Commits

Reviewing files that changed from the base of the PR and between 1bd5860 and a18dc39.

📒 Files selected for processing (7)
  • ARCHITECTURE.md
  • README.md
  • src/lib/nodeTcpSocket.ts
  • src/lib/socketTransport.ts
  • src/lib/socketTypes.ts
  • src/utils/ircClient.ts
  • tests/unit/socketTransport.test.ts

Comment thread tests/unit/socketTransport.test.ts
Stub net.connect in the reset test so the unit test verifies the default factory without performing real loopback network I/O.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant