{"id":24774969,"url":"https://github.com/aperturerobotics/starpc","last_synced_at":"2026-05-18T06:20:01.038Z","repository":{"id":36970701,"uuid":"496938667","full_name":"aperturerobotics/starpc","owner":"aperturerobotics","description":"Protobuf 3 streaming RPCs for TypeScript, Go, Rust, C++","archived":false,"fork":false,"pushed_at":"2026-05-15T01:01:12.000Z","size":3182,"stargazers_count":72,"open_issues_count":2,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-05-15T03:10:21.561Z","etag":null,"topics":["go","protobuf","rpc","rpc-framework","rust","typescript","websocket"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aperturerobotics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-05-27T09:33:36.000Z","updated_at":"2026-05-13T17:27:53.000Z","dependencies_parsed_at":"2026-05-15T03:03:46.074Z","dependency_job_id":null,"html_url":"https://github.com/aperturerobotics/starpc","commit_stats":{"total_commits":602,"total_committers":5,"mean_commits":120.4,"dds":0.5980066445182723,"last_synced_commit":"d2301e14ccf3f7259fb110d0c08e89c79d609af3"},"previous_names":["paralin/starpc"],"tags_count":235,"template":false,"template_full_name":null,"purl":"pkg:github/aperturerobotics/starpc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aperturerobotics%2Fstarpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aperturerobotics%2Fstarpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aperturerobotics%2Fstarpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aperturerobotics%2Fstarpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aperturerobotics","download_url":"https://codeload.github.com/aperturerobotics/starpc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aperturerobotics%2Fstarpc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33167437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T05:43:36.989Z","status":"ssl_error","status_checked_at":"2026-05-18T05:43:19.133Z","response_time":71,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","protobuf","rpc","rpc-framework","rust","typescript","websocket"],"created_at":"2025-01-29T06:31:32.498Z","updated_at":"2026-05-18T06:20:01.019Z","avatar_url":"https://github.com/aperturerobotics.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# starpc\n\n[![npm](https://img.shields.io/npm/v/starpc?style=flat-square)](https://www.npmjs.com/package/starpc)\n[![crates.io](https://img.shields.io/crates/v/starpc.svg?style=flat-square)](https://crates.io/crates/starpc)\n[![Build status](https://img.shields.io/github/actions/workflow/status/aperturerobotics/starpc/tests.yml?style=flat-square\u0026branch=master)](https://github.com/aperturerobotics/starpc/actions)\n[![GoDoc Widget]][GoDoc] [![Go Report Card Widget]][Go Report Card]\n\n\u003e Streaming Protobuf RPC with bidirectional streaming over any multiplexed transport.\n\n[GoDoc]: https://godoc.org/github.com/aperturerobotics/starpc\n[GoDoc Widget]: https://godoc.org/github.com/aperturerobotics/starpc?status.svg\n[Go Report Card Widget]: https://goreportcard.com/badge/github.com/aperturerobotics/starpc\n[Go Report Card]: https://goreportcard.com/report/github.com/aperturerobotics/starpc\n\n## Table of Contents\n\n- [Features](#features)\n- [Documentation](#documentation)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Examples](#examples)\n  - [Protobuf Definition](#protobuf)\n  - [Go Implementation](#go)\n  - [TypeScript Implementation](#typescript)\n  - [Rust Implementation](#rust)\n- [Debugging](#debugging)\n- [Development Setup](#development-setup)\n- [Support](#support)\n\n## Features\n\n- Full [Proto3 services] support for TypeScript, Go, and Rust\n- Bidirectional streaming in browsers via WebSocket or WebRTC\n- Built on libp2p streams with [@chainsafe/libp2p-yamux]\n- Efficient multiplexing of RPCs over single connections\n- Zero-reflection Go via [protobuf-go-lite]\n- Lightweight TypeScript via [protobuf-es-lite]\n- Async Rust via [prost] and [tokio]\n- Sub-stream support via [rpcstream]\n\n[Proto3 services]: https://developers.google.com/protocol-buffers/docs/proto3#services\n[@chainsafe/libp2p-yamux]: https://github.com/ChainSafe/js-libp2p-yamux\n[protobuf-go-lite]: https://github.com/aperturerobotics/protobuf-go-lite\n[protobuf-es-lite]: https://github.com/aperturerobotics/protobuf-es-lite\n[prost]: https://github.com/tokio-rs/prost\n[tokio]: https://github.com/tokio-rs/tokio\n[rpcstream]: ./rpcstream\n\n## Documentation\n\n- [Getting Started with TypeScript](./GET_STARTED_TYPESCRIPT.md)\n- [Getting Started with Go](./GET_STARTED_GO.md)\n- [Getting Started with Rust](./GET_STARTED_RUST.md)\n\n## Installation\n\n```bash\n# Clone the template project\ngit clone -b starpc https://github.com/aperturerobotics/protobuf-project\ncd protobuf-project\n\n# Install dependencies (any of these work)\nbun install\nnpm install\npnpm install\n\n# Generate TypeScript and Go code\nbun run gen\n```\n\n## Quick Start\n\n1. Start with the [protobuf-project] template repository (starpc branch)\n2. Add your .proto files to the project\n3. Run `bun run gen` to generate TypeScript and Go code\n4. Implement your services using the examples below\n\n[protobuf-project]: https://github.com/aperturerobotics/protobuf-project/tree/starpc\n\n### Protobuf\n\nThe following examples use the [echo](./echo/echo.proto) protobuf sample.\n\n```protobuf\nsyntax = \"proto3\";\npackage echo;\n\n// Echoer service returns the given message.\nservice Echoer {\n  // Echo returns the given message.\n  rpc Echo(EchoMsg) returns (EchoMsg);\n  // EchoServerStream is an example of a server -\u003e client one-way stream.\n  rpc EchoServerStream(EchoMsg) returns (stream EchoMsg);\n  // EchoClientStream is an example of client-\u003eserver one-way stream.\n  rpc EchoClientStream(stream EchoMsg) returns (EchoMsg);\n  // EchoBidiStream is an example of a two-way stream.\n  rpc EchoBidiStream(stream EchoMsg) returns (stream EchoMsg);\n}\n\n// EchoMsg is the message body for Echo.\nmessage EchoMsg {\n  string body = 1;\n}\n```\n\n### Go\n\nThis example demonstrates both the server and client:\n\n```go\n// construct the server\nechoServer := \u0026echo.EchoServer{}\nmux := srpc.NewMux()\nif err := echo.SRPCRegisterEchoer(mux, echoServer); err != nil {\n\tt.Fatal(err.Error())\n}\nserver := srpc.NewServer(mux)\n\n// create an in-memory connection to the server\nopenStream := srpc.NewServerPipe(server)\n\n// construct the client\nclient := srpc.NewClient(openStream)\n\n// construct the client rpc interface\nclientEcho := echo.NewSRPCEchoerClient(client)\nctx := context.Background()\nbodyTxt := \"hello world\"\nout, err := clientEcho.Echo(ctx, \u0026echo.EchoMsg{\n\tBody: bodyTxt,\n})\nif err != nil {\n\tt.Fatal(err.Error())\n}\nif out.GetBody() != bodyTxt {\n\tt.Fatalf(\"expected %q got %q\", bodyTxt, out.GetBody())\n}\n```\n\n### TypeScript\n\nFor Go \u003c-\u003e TypeScript interop, see the [integration] test.\nFor TypeScript \u003c-\u003e TypeScript, see the [e2e] test.\n\n[e2e]: ./e2e/e2e.ts\n[integration]: ./integration/integration.ts\n\n### Rust\n\nAdd the dependencies to your `Cargo.toml`:\n\n```toml\n[dependencies]\nstarpc = \"0.49\"\nprost = \"0.14\"\ntokio = { version = \"1\", features = [\"rt\", \"macros\"] }\n\n[build-dependencies]\nstarpc = { version = \"0.49\", features = [\"build\"] }\nprost-build = \"0.14\"\n```\n\nCreate a `build.rs` to generate code from your proto files:\n\n```rust\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    starpc::build::configure()\n        .compile_protos(\u0026[\"proto/echo.proto\"], \u0026[\"proto\"])?;\n    Ok(())\n}\n```\n\nImplement and use your service:\n\n```rust\nuse starpc::{Client, Mux, Server, SrpcClient};\nuse std::sync::Arc;\n\n// Include generated code\nmod proto {\n    include!(concat!(env!(\"OUT_DIR\"), \"/echo.rs\"));\n}\n\nuse proto::*;\n\n// Implement the server trait\nstruct EchoServer;\n\n#[starpc::async_trait]\nimpl EchoerServer for EchoServer {\n    async fn echo(\u0026self, request: EchoMsg) -\u003e starpc::Result\u003cEchoMsg\u003e {\n        Ok(request) // Echo back the message\n    }\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    // Create server\n    let mux = Arc::new(Mux::new());\n    mux.register(Arc::new(EchoerHandler::new(EchoServer)))?;\n    let server = Server::with_arc(mux);\n\n    // Create an in-memory connection for demonstration\n    let (client_stream, server_stream) = tokio::io::duplex(64 * 1024);\n\n    // Spawn server handler\n    tokio::spawn(async move {\n        let _ = server.handle_stream(server_stream).await;\n    });\n\n    // Create client\n    let opener = starpc::client::transport::SingleStreamOpener::new(client_stream);\n    let client = SrpcClient::new(opener);\n    let echoer = EchoerClientImpl::new(client);\n\n    // Make RPC call\n    let response = echoer.echo(\u0026EchoMsg { body: \"Hello!\".into() }).await?;\n    println!(\"Response: {}\", response.body);\n\n    Ok(())\n}\n```\n\nSee the [echo example](./echo/main.rs) for a complete working example.\n\n#### WebSocket Example\n\nConnect to a WebSocket server:\n\n```typescript\nimport { WebSocketConn } from 'starpc'\nimport { EchoerClient } from './echo/index.js'\n\nconst ws = new WebSocket('ws://localhost:8080/api')\nconst conn = new WebSocketConn(ws)\nconst client = conn.buildClient()\nconst echoer = new EchoerClient(client)\n\nconst result = await echoer.Echo({ body: 'Hello world!' })\nconsole.log('result:', result.body)\n```\n\n#### In-Memory Example\n\nServer and client with an in-memory pipe:\n\n```typescript\nimport { pipe } from 'it-pipe'\nimport { createHandler, createMux, Server, StreamConn } from 'starpc'\nimport { EchoerDefinition, EchoerServer } from './echo/index.js'\n\n// Create server with registered handlers\nconst mux = createMux()\nconst echoer = new EchoerServer()\nmux.register(createHandler(EchoerDefinition, echoer))\nconst server = new Server(mux.lookupMethod)\n\n// Create client and server connections, pipe together\nconst clientConn = new StreamConn()\nconst serverConn = new StreamConn(server)\npipe(clientConn, serverConn, clientConn)\n\n// Build client and make RPC calls\nconst client = clientConn.buildClient()\nconst echoerClient = new EchoerClient(client)\n\n// Unary call\nconst result = await echoerClient.Echo({ body: 'Hello world!' })\nconsole.log('result:', result.body)\n\n// Client streaming\nimport { pushable } from 'it-pushable'\nconst stream = pushable({ objectMode: true })\nstream.push({ body: 'Message 1' })\nstream.push({ body: 'Message 2' })\nstream.end()\nconst response = await echoerClient.EchoClientStream(stream)\nconsole.log('response:', response.body)\n\n// Server streaming\nfor await (const msg of echoerClient.EchoServerStream({ body: 'Hello' })) {\n  console.log('server msg:', msg.body)\n}\n```\n\n## Debugging\n\nEnable debug logging in TypeScript using the `DEBUG` environment variable:\n\n```bash\n# Enable all starpc logs\nDEBUG=starpc:* node app.js\n\n# Enable specific component logs\nDEBUG=starpc:stream-conn node app.js\n```\n\n## Attribution\n\n`protoc-gen-go-starpc` is a heavily modified version of `protoc-gen-go-drpc`.\nCheck out [drpc] as well - it's compatible with grpc, twirp, and more.\n\n[drpc]: https://github.com/storj/drpc\n\nUses [vtprotobuf] to generate Protobuf marshal/unmarshal code for Go.\n\n[vtprotobuf]: https://github.com/planetscale/vtprotobuf\n\n`protoc-gen-es-starpc` is a modified version of `protoc-gen-connect-es`.\nUses [protobuf-es-lite] (fork of [protobuf-es]) for TypeScript.\n\n[protobuf-es]: https://github.com/bufbuild/protobuf-es\n\n## Development Setup\n\n### MacOS\n\nThe `aptre` CLI handles all protobuf generation without requiring additional\nhomebrew packages. Just run `bun run gen` after installing bun.\n\n## Support\n\n- [GitHub Issues][issues]\n- [Discord][discord]\n- [Matrix][matrix]\n\n[issues]: https://github.com/aperturerobotics/starpc/issues/new\n[discord]: https://discord.gg/KJutMESRsT\n[matrix]: https://matrix.to/#/#aperturerobotics:matrix.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faperturerobotics%2Fstarpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faperturerobotics%2Fstarpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faperturerobotics%2Fstarpc/lists"}