diff --git a/README.md b/README.md index 1c15585..9ab6e90 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ Bufrnix doesn't replace Buf - it **extends** the Protocol Buffer ecosystem with 🔧 Rich Plugin Ecosystem -gRPC, Connect, gRPC-Web, gRPC-Gateway, Twirp, and validation +gRPC, gRPC-Web, gRPC-Gateway, Twirp, and validation 📦 Zero Setup @@ -350,7 +350,6 @@ Generate code for multiple languages simultaneously: grpc.enable = true; gateway.enable = true; # HTTP/JSON transcoding validate.enable = true; # Message validation - connect.enable = true; # Modern Connect protocol }; # Dart for Flutter applications @@ -367,7 +366,6 @@ Generate code for multiple languages simultaneously: outputPath = "src/proto"; packageName = "my-proto"; es.enable = true; # Modern ECMAScript modules - connect.enable = true; # Connect-ES for modern RPC grpcWeb.enable = true; # Browser-compatible gRPC twirp.enable = true; # Twirp RPC framework }; @@ -429,12 +427,6 @@ languages.go = { enable = true; options = ["lang=go"]; }; - - # Modern Connect protocol - connect = { - enable = true; - options = ["paths=source_relative"]; - }; }; ``` @@ -456,16 +448,7 @@ languages.js = { "import_extension=.js" # ES module extensions ]; }; - - # Connect-ES for type-safe RPC - connect = { - enable = true; - options = [ - "target=ts" - "import_extension=.js" - ]; - }; - + # gRPC-Web for browser compatibility grpcWeb = { enable = true; @@ -481,8 +464,8 @@ languages.js = { | Language | Status | Plugins & Features | Output | |----------|---------|-------------------|--------| -| **Go** | ✅ Full | `protoc-gen-go`, gRPC, Connect, Gateway, Validation, VTProtobuf, Struct Transformer | Standard Go packages with comprehensive ecosystem | -| **JavaScript/TypeScript** | ✅ Full | ES modules, gRPC-Web, Connect-ES, Twirp, ts-proto, Protovalidate | Modern JS/TS with type definitions | +| **Go** | ✅ Full | `protoc-gen-go`, gRPC, Gateway, Validation, VTProtobuf, Struct Transformer | Standard Go packages with comprehensive ecosystem | +| **JavaScript/TypeScript** | ✅ Full | ES modules, gRPC-Web, Twirp, ts-proto, Protovalidate | Modern JS/TS with type definitions | | **Python** | ✅ Full | Standard protoc, gRPC, mypy, betterproto, type stubs | Python packages with optional typing | | **Dart** | ✅ Full | `protoc-gen-dart`, gRPC support | Flutter/server Dart classes with type safety | | **PHP** | ✅ Full | Standard protoc, Twirp, Async, Laravel, Symfony, gRPC, RoadRunner | PSR-4 compatible classes with framework integration | @@ -490,7 +473,7 @@ languages.js = { | **C++** | ✅ Full | `protoc-gen-cpp`, gRPC, CMake helpers | Native C++ classes with CMake integration | | **Swift** | ✅ Full | `protoc-gen-swift` | iOS/macOS Swift classes with SwiftProtobuf | | **C#** | ✅ Full | `protoc-gen-csharp`, gRPC | .NET compatible classes with gRPC support | -| **Kotlin** | ✅ Full | `protoc-gen-kotlin`, gRPC, Connect | JVM Kotlin classes with modern RPC support | +| **Kotlin** | ✅ Full | `protoc-gen-kotlin`, gRPC | JVM Kotlin classes with modern RPC support | | **Scala** | ✅ Full | `protoc-gen-scala`, gRPC | Scala classes with functional programming patterns | | **C** | ✅ Full | protobuf-c, nanopb | Embedded-friendly C implementations | | **Documentation** | ✅ Full | HTML/SVG generation, MDX templates | Rich documentation output formats | @@ -528,7 +511,7 @@ nix develop npm install && npm run build && npm start ``` - Multiple JavaScript output formats -- Connect-ES and gRPC-Web clients +- gRPC-Web and Twirp clients - TypeScript integration ### 🐘 [PHP Twirp Example](examples/php-twirp/) @@ -626,7 +609,7 @@ Each language module supports: - `enable`: Boolean to enable/disable the language - `outputPath`: Where to place generated files (relative to root) - `options`: Array of options passed to the base protoc plugin -- Plugin-specific configuration (e.g., `grpc.enable`, `connect.enable`) +- Plugin-specific configuration (e.g., `grpc.enable`, `validate.enable`) See the [Language Modules Documentation](src/languages/README.md) for complete details. @@ -726,7 +709,6 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file - [Protocol Buffers](https://developers.google.com/protocol-buffers) - Google's language-neutral data serialization - [Nix](https://nixos.org/) - Reproducible package management and builds -- [Connect](https://connect.build/) - Modern, type-safe RPC framework - [gRPC](https://grpc.io/) - High-performance RPC framework - [Twirp](https://github.com/twitchtv/twirp) - Simple RPC framework for service-to-service communication diff --git a/doc/src/content/docs/reference/languages/javascript.mdx b/doc/src/content/docs/reference/languages/javascript.mdx index a7b089b..fbf6893 100644 --- a/doc/src/content/docs/reference/languages/javascript.mdx +++ b/doc/src/content/docs/reference/languages/javascript.mdx @@ -19,8 +19,7 @@ JavaScript/TypeScript support provides multiple output formats and RPC options f | Plugin | Description | Generated Files | | --------------------------- | ----------------- | ---------------------- | | **`protoc-gen-js`** | CommonJS messages | `*_pb.js`, `*_pb.d.ts` | -| **`protoc-gen-es`** | ES modules | `*.js`, `*.d.ts` | -| **`protoc-gen-connect-es`** | Connect-ES RPC | `*_connect.js` | +| **`protoc-gen-es`** | ES modules | `*.js`, `*.d.ts` | | **`protoc-gen-grpc-web`** | gRPC-Web client | `*_grpc_web_pb.js` | | **`protoc-gen-twirp_js`** | Twirp RPC | `*_twirp.js` | @@ -57,15 +56,6 @@ languages.js = { ]; }; - # Connect-ES for type-safe RPC - connect = { - enable = true; - options = [ - "target=ts" - "import_extension=.js" - ]; - }; - # gRPC-Web for browser compatibility grpcWeb = { enable = true; @@ -113,9 +103,8 @@ languages = { "./proto/google/api/http.proto" # REST definitions ]; es.enable = true; - connect.enable = true; }; - + # Go: Use only internal services (excludes Google annotations) go = { enable = true; @@ -147,7 +136,6 @@ languages.js = { # No internal services - client security boundary ]; es.enable = true; - connect.enable = true; }; ``` @@ -185,7 +173,7 @@ languages.js = { - Add HTTP/REST annotations for Connect-ES clients + Add HTTP/REST annotations for web clients Prevent frontend access to internal backend services @@ -273,87 +261,6 @@ message StreamUsersRequest { ## Generated Code Usage - - ```typescript - import { UserService } from "./proto/example/v1/example_connect.js"; - import { User, ActiveStatus } from "./proto/example/v1/example_pb.js"; - import { createPromiseClient } from "@connectrpc/connect"; - import { createConnectTransport } from "@connectrpc/connect-web"; - - // Create transport - const transport = createConnectTransport({ - baseUrl: "https://api.example.com", - credentials: "include", - interceptors: [ - (next) => async (req) => { - console.log(`Calling ${req.method.name}`); - const res = await next(req); - console.log(`Response received`); - return res; - }, - ], - }); - - // Create typed client - const client = createPromiseClient(UserService, transport); - - async function main() { - try { - // Create a new user with typed data - const user = new User({ - id: "1", - name: "John Doe", - email: "john@example.com", - age: 30, - tags: ["developer", "typescript"], - metadata: { - department: "Engineering", - location: "Remote" - }, - status: { - case: "active", - value: new ActiveStatus({ - since: "2024-01-01", - activity: "coding" - }) - } - }); - - const createResponse = await client.createUser({ - user: user, - }); - - console.log("Created user:", createResponse.user); - - // Get the user - const getResponse = await client.getUser({ - id: "1", - }); - - console.log("Retrieved user:", getResponse.user); - - // List users with pagination - const listResponse = await client.listUsers({ - pageSize: 10, - pageToken: "", - tags: ["developer"], - }); - - console.log(`Found ${listResponse.users.length} users`); - - // Stream users - for await (const user of client.streamUsers({ tags: ["active"] })) { - console.log("Streamed user:", user.name); - } - } catch (error) { - console.error("RPC failed:", error); - } - } - - main(); - ``` - - ```typescript import { UserServiceClient } from "./proto/example/v1/example_grpc_web_pb"; @@ -551,78 +458,6 @@ message StreamUsersRequest { useTwirp(); ``` - - - ```typescript - import { createServer } from "@connectrpc/connect"; - import { createNodeServer } from "@connectrpc/connect-node"; - import { UserService } from "./proto/example/v1/example_connect"; - import { User } from "./proto/example/v1/example_pb"; - - // In-memory storage - const users = new Map(); - - // Implement service - const userService = { - async getUser(request) { - const user = users.get(request.id); - if (!user) { - throw new Error("User not found"); - } - return { user }; - }, - - async createUser(request) { - users.set(request.user!.id, request.user!); - return { user: request.user! }; - }, - - async listUsers(request) { - const allUsers = Array.from(users.values()); - - // Filter by tags - const filtered = request.tags.length > 0 - ? allUsers.filter(u => - u.tags.some(t => request.tags.includes(t)) - ) - : allUsers; - - // Pagination - const start = request.pageToken ? parseInt(request.pageToken) : 0; - const end = start + request.pageSize; - const page = filtered.slice(start, end); - - return { - users: page, - nextPageToken: end < filtered.length ? end.toString() : "", - totalCount: filtered.length - }; - }, - - async *streamUsers(request) { - for (const [_, user] of users) { - if (request.tags.length === 0 || - user.tags.some(t => request.tags.includes(t))) { - yield user; - // Simulate real-time updates - await new Promise(resolve => setTimeout(resolve, 1000)); - } - } - } - } satisfies typeof UserService; - - // Create and start server - const server = createNodeServer({ - services: [ - { service: UserService, implementation: userService } - ], - address: "localhost:8080", - }); - - await server.start(); - console.log("Server listening on", server.address); - ``` - ## Build Tools Integration @@ -658,8 +493,6 @@ message StreamUsersRequest { "test": "vitest" }, "dependencies": { - "@connectrpc/connect": "^1.0.0", - "@connectrpc/connect-web": "^1.0.0", "@bufbuild/protobuf": "^1.0.0" }, "devDependencies": { @@ -680,8 +513,6 @@ message StreamUsersRequest { export default { optimizeDeps: { include: [ - "@connectrpc/connect", - "@connectrpc/connect-web", "@bufbuild/protobuf", ], }, @@ -692,24 +523,17 @@ export default { ```tsx import { useEffect, useState } from "react"; -import { createPromiseClient } from "@connectrpc/connect"; -import { createConnectTransport } from "@connectrpc/connect-web"; -import { UserService } from "@/proto/example/v1/example_connect"; import { User } from "@/proto/example/v1/example_pb"; -const transport = createConnectTransport({ - baseUrl: import.meta.env.VITE_API_URL, -}); - -const client = createPromiseClient(UserService, transport); - +// Use your preferred RPC framework (gRPC-Web, Twirp, etc.) +// This example shows the React component structure export function UserList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { - client - .listUsers({ pageSize: 20, pageToken: "" }) + // Fetch users using your RPC client + fetchUsers() .then((response) => { setUsers(response.users); setLoading(false); @@ -736,14 +560,13 @@ export function UserList() { ## Best Practices -1. **Use Connect-ES**: Preferred for new projects - type-safe, modern API -2. **Enable TypeScript**: Use `target=ts` for better type safety -3. **ES Modules**: Use `.js` extensions for proper ES module support -4. **Error Handling**: Use proper error types from Connect/gRPC -5. **Streaming**: Use async iterators for efficient streaming -6. **Tree Shaking**: ES modules enable better bundle optimization -7. **Smart File Management**: Use `additionalFiles` to include Google API annotations for REST clients -8. **Security Boundaries**: Use per-language files to prevent frontend access to internal backend services +1. **Enable TypeScript**: Use `target=ts` for better type safety +2. **ES Modules**: Use `.js` extensions for proper ES module support +3. **Error Handling**: Use proper error types from your RPC framework +4. **Streaming**: Use async iterators for efficient streaming +5. **Tree Shaking**: ES modules enable better bundle optimization +6. **Smart File Management**: Use `additionalFiles` to include Google API annotations for REST clients +7. **Security Boundaries**: Use per-language files to prevent frontend access to internal backend services ## Try the Example @@ -771,18 +594,7 @@ import { User } from "./proto/example_pb"; ### CORS Issues -For browser clients, configure server CORS: - -```typescript -const transport = createConnectTransport({ - baseUrl: "https://api.example.com", - credentials: "include", // For cookies - // OR - headers: { - Authorization: "Bearer token", - }, -}); -``` +For browser clients, configure appropriate CORS settings on your server and include authentication headers as needed by your RPC framework (gRPC-Web, Twirp, etc.). ### TypeScript Paths diff --git a/examples/js-annotations/flake.nix b/examples/js-annotations/flake.nix index d6a05ec..1d1c63c 100644 --- a/examples/js-annotations/flake.nix +++ b/examples/js-annotations/flake.nix @@ -76,9 +76,7 @@ echo "Key Features:" echo " ✅ Google API annotations (google.api.http) for REST endpoints" echo " ✅ Protobuf-ES for modern TypeScript message generation" - echo " ✅ Connect-ES for type-safe RPC clients (gRPC + HTTP/REST)" echo " ✅ Complete user management service example" - echo " ✅ Both protocol interfaces from the same .proto files" echo "" echo "Available commands:" echo " nix build - Generate TypeScript code from proto files" @@ -93,10 +91,6 @@ echo " ./gen/ts/google/ - Google API annotations as TypeScript" echo " ./gen/ts/example/ - User service messages and clients" echo "" - echo "The key advantage: Connect-ES generates clients that can talk to services" - echo "via both gRPC (for performance) and HTTP/REST (for web compatibility)" - echo "using the same TypeScript interfaces." - echo "" ''; }; }); diff --git a/examples/js-es-modules/flake.nix b/examples/js-es-modules/flake.nix index 4e91360..8c09e37 100644 --- a/examples/js-es-modules/flake.nix +++ b/examples/js-es-modules/flake.nix @@ -36,12 +36,6 @@ packageName = "@example/proto"; importExtension = ".js"; # For Node.js ES modules compatibility }; - # Connect-ES for modern RPC - connect = { - enable = true; - generatePackageJson = true; - packageName = "@example/connect"; - }; # TypeScript validation support protovalidate = { enable = true; @@ -75,7 +69,6 @@ echo "" echo "Features enabled:" echo " ✅ Protobuf-ES (default TypeScript generator)" - echo " ✅ Connect-ES (modern RPC framework)" echo " ✅ Protovalidate-ES (validation support)" ''; }; diff --git a/examples/multi-output-example/flake.nix b/examples/multi-output-example/flake.nix index 04cf5f5..175503f 100644 --- a/examples/multi-output-example/flake.nix +++ b/examples/multi-output-example/flake.nix @@ -62,7 +62,6 @@ enable = true; target = "ts"; }; - connect.enable = true; }; # Python with multiple output paths for development and distribution diff --git a/examples/ts-flake-parts/flake.nix b/examples/ts-flake-parts/flake.nix index 5387e46..edfc735 100644 --- a/examples/ts-flake-parts/flake.nix +++ b/examples/ts-flake-parts/flake.nix @@ -45,12 +45,6 @@ packageName = "@example/proto-ts"; importExtension = ".js"; }; - # Connect-ES for modern RPC (disabled due to plugin issues) - # connect = { - # enable = true; - # generatePackageJson = true; - # packageName = "@example/connect-ts"; - # }; # TypeScript validation support (disabled for now) # protovalidate = { # enable = true; @@ -84,7 +78,6 @@ echo "This example demonstrates:" echo " • Flake-parts integration with bufrnix" echo " • TypeScript protobuf generation with Protobuf-ES" - echo " • Connect-ES for modern RPC" echo " • Protovalidate-ES for validation" echo "" echo "Commands:" @@ -100,7 +93,6 @@ echo "" echo "Features enabled:" echo " ✅ Protobuf-ES (TypeScript generator)" - echo " ✅ Connect-ES (modern RPC framework)" echo " ✅ Protovalidate-ES (validation support)" echo " ✅ Flake-parts integration" ''; diff --git a/src/languages/js/connect.nix b/src/languages/js/connect.nix deleted file mode 100644 index 2e2929d..0000000 --- a/src/languages/js/connect.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ - pkgs, - lib, - cfg ? {}, - ... -}: -with lib; - if cfg.enable or false - then let - outputPath = cfg.outputPath or "gen/js"; - connectOptions = cfg.options or []; - # Connect-ES functionality is now integrated into protoc-gen-es v2 - # We use protoc-gen-es with plugin=connect_target=ts option - in { - # Runtime dependencies for Connect-ES code generation - runtimeInputs = [ - pkgs.protoc-gen-es # Connect support is built into v2 - ]; - - # Protoc plugin configuration for Connect-ES - # Connect is generated alongside messages with protoc-gen-es v2 - protocPlugins = [ - # Connect generation is handled by ES module with plugin option - (optionalString (connectOptions != []) "--es_opt=plugin=connect_target=ts,${concatStringsSep "," connectOptions}") - ]; - - # Initialization hook for Connect-ES - initHooks = '' - # Connect code is generated alongside protobuf-es messages - echo "Connect-ES service generation enabled via protoc-gen-es v2..." - ''; - - # Code generation hook for Connect-ES - generateHooks = '' - # Connect-ES specific generation steps - echo "Connect-ES services generated alongside Protobuf-ES messages" - - # Generate package.json if needed - ${optionalString (cfg.generatePackageJson or false) '' - if [ ! -f ${outputPath}/package.json ]; then - cat > ${outputPath}/package.json <