This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git

commit dd4cce785578efad34311fe19384ac4defdc18a5
Author: chaokunyang <[email protected]>
AuthorDate: Sun Jun 21 12:54:01 2026 +0000

    🔄 synced local 'docs/guide/' with remote 'docs/guide/'
---
 docs/guide/dart/grpc-support.md    | 292 +++++++++++++++++++++++++++++++++++++
 docs/guide/dart/index.md           |   1 +
 docs/guide/dart/troubleshooting.md |  17 +++
 3 files changed, 310 insertions(+)

diff --git a/docs/guide/dart/grpc-support.md b/docs/guide/dart/grpc-support.md
new file mode 100644
index 0000000000..cda566adcc
--- /dev/null
+++ b/docs/guide/dart/grpc-support.md
@@ -0,0 +1,292 @@
+---
+title: gRPC Support
+sidebar_position: 12
+id: grpc_support
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Fory can generate Dart gRPC service companions for schemas that define 
services.
+The generated code uses normal `package:grpc` clients, service bases, method
+descriptors, call options, deadlines, cancellations, and status codes, while
+request and response objects are serialized with Fory instead of protobuf.
+
+Use this mode when both RPC peers are generated from the same Fory IDL, 
protobuf
+IDL, or FlatBuffers IDL and both sides expect Fory-encoded message bodies. Use
+normal protobuf gRPC generation for APIs that must be consumed by generic
+protobuf clients, reflection tools, or components that expect protobuf message
+bytes.
+
+## Add Dependencies
+
+The `fory` package does not add gRPC dependencies. Add `grpc` (and the
+`build_runner` dev dependency that generates the Fory serializer code) in the
+application that compiles or runs generated service companions:
+
+```yaml
+dependencies:
+  fory: ^1.1.0
+  grpc: ^4.0.0
+
+dev_dependencies:
+  build_runner: ^2.4.0
+```
+
+The same dependencies cover both client and server applications.
+
+## Define a Service
+
+Service definitions can come from Fory IDL, protobuf IDL, or FlatBuffers
+`rpc_service` definitions. A Fory IDL service looks like this:
+
+```protobuf
+package demo.greeter;
+
+message HelloRequest {
+  string name = 1;
+}
+
+message HelloReply {
+  string reply = 1;
+}
+
+service Greeter {
+  rpc SayHello (HelloRequest) returns (HelloReply);
+}
+```
+
+Generate Dart model and gRPC companion code with `--grpc`:
+
+```bash
+foryc service.fdl --dart_out=./lib/generated --grpc
+```
+
+Then run `build_runner` once to emit the Fory serializer part file for the
+generated models (this step is required before the code can run):
+
+```bash
+dart run build_runner build --delete-conflicting-outputs
+```
+
+For this schema, the Dart generator emits (the model file and module are named
+from the package leaf, `greeter`):
+
+| File                                        | Purpose                        
                      |
+| ------------------------------------------- | 
---------------------------------------------------- |
+| `demo/greeter/greeter.dart`                 | Fory model types and the 
schema module               |
+| `demo/greeter/greeter.fory.dart`            | Serializers and registration 
(built by build_runner) |
+| `demo/greeter/greeter_grpc.dart`            | gRPC client, service base, and 
method descriptors    |
+| `GreeterForyModule` in `greeter.dart`       | Fory registration module for 
generated types         |
+| `GreeterServiceBase` in `greeter_grpc.dart` | Base class for server 
implementations                |
+| `GreeterClient` in `greeter_grpc.dart`      | Client stub for gRPC calls     
                      |
+
+The generated client and service base obtain a ready `Fory` automatically and
+register the schema's types on first use, so no manual registration step is
+required. To share a custom `Fory` (for example one configured with extra
+modules), call `GreeterForyModule.install(yourFory)` once before the first RPC;
+this is optional.
+
+## Implement a Server
+
+Extend the generated `GreeterServiceBase` and host it with grpc-dart's 
`Server`:
+
+```dart
+import 'dart:io';
+
+import 'package:grpc/grpc.dart';
+import 'demo/greeter/greeter.dart';
+import 'demo/greeter/greeter_grpc.dart';
+
+class GreeterService extends GreeterServiceBase {
+  @override
+  Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
+    final reply = HelloReply()..reply = 'Hello, ${request.name}';
+    return reply;
+  }
+}
+
+Future<void> main() async {
+  final server = Server.create(services: [GreeterService()]);
+  await server.serve(address: InternetAddress.loopbackIPv4, port: 50051);
+}
+```
+
+## Create a Client
+
+Use the generated client with a `ClientChannel`:
+
+```dart
+import 'package:grpc/grpc.dart';
+import 'demo/greeter/greeter.dart';
+import 'demo/greeter/greeter_grpc.dart';
+
+Future<void> main() async {
+  final channel = ClientChannel(
+    'localhost',
+    port: 50051,
+    options: const ChannelOptions(
+      credentials: ChannelCredentials.insecure(),
+    ),
+  );
+  final client = GreeterClient(channel);
+
+  final reply = await client.sayHello(HelloRequest()..name = 'Fory');
+  print(reply.reply);
+
+  await channel.shutdown();
+}
+```
+
+## Streaming RPCs
+
+Fory service definitions can use the same gRPC streaming shapes:
+
+```protobuf
+service Greeter {
+  rpc SayHello (HelloRequest) returns (HelloReply);
+  rpc LotsOfReplies (HelloRequest) returns (stream HelloReply);
+  rpc LotsOfGreetings (stream HelloRequest) returns (HelloReply);
+  rpc Chat (stream HelloRequest) returns (stream HelloReply);
+}
+```
+
+Generated Dart methods follow grpc-dart conventions. Single responses return a
+`ResponseFuture<R>` (client-streaming adapts the call with `.single`); 
streaming
+responses return a `ResponseStream<R>`. On the server, single requests arrive 
as
+the message type and streaming requests as a `Stream`; the method returns a
+`Future` for single responses and a `Stream` for streaming responses:
+
+| IDL shape                                 | Client method                    
                    | Server method (override)                               |
+| ----------------------------------------- | 
---------------------------------------------------- | 
------------------------------------------------------ |
+| `rpc A (Req) returns (Res)`               | `ResponseFuture<Res> a(Req 
request, {CallOptions?})` | `Future<Res> a(ServiceCall call, Req request)`      
   |
+| `rpc A (Req) returns (stream Res)`        | `ResponseStream<Res> a(Req 
request, {CallOptions?})` | `Stream<Res> a(ServiceCall call, Req request)`      
   |
+| `rpc A (stream Req) returns (Res)`        | `ResponseFuture<Res> 
a(Stream<Req> request, {...})`  | `Future<Res> a(ServiceCall call, Stream<Req> 
request)` |
+| `rpc A (stream Req) returns (stream Res)` | `ResponseStream<Res> 
a(Stream<Req> request, {...})`  | `Stream<Res> a(ServiceCall call, Stream<Req> 
request)` |
+
+Server implementations use the generated streaming method shapes directly:
+
+```dart
+class GreeterService extends GreeterServiceBase {
+  @override
+  Stream<HelloReply> lotsOfReplies(
+    ServiceCall call,
+    HelloRequest request,
+  ) async* {
+    for (final greeting in ['Hello, ${request.name}', 'Welcome, 
${request.name}']) {
+      yield HelloReply()..reply = greeting;
+    }
+  }
+
+  @override
+  Future<HelloReply> lotsOfGreetings(
+    ServiceCall call,
+    Stream<HelloRequest> request,
+  ) async {
+    final names = <String>[];
+    await for (final message in request) {
+      names.add(message.name);
+    }
+    return HelloReply()..reply = names.join(', ');
+  }
+
+  @override
+  Stream<HelloReply> chat(
+    ServiceCall call,
+    Stream<HelloRequest> request,
+  ) async* {
+    await for (final message in request) {
+      yield HelloReply()..reply = 'Hello, ${message.name}';
+    }
+  }
+}
+```
+
+Generated clients return the standard grpc-dart call objects:
+
+```dart
+// Server streaming.
+await for (final reply in client.lotsOfReplies(HelloRequest()..name = 'Fory')) 
{
+  print(reply.reply);
+}
+
+// Client streaming.
+final summary = await client.lotsOfGreetings(
+  Stream.fromIterable([
+    HelloRequest()..name = 'Ada',
+    HelloRequest()..name = 'Grace',
+  ]),
+);
+print(summary.reply);
+
+// Bidirectional streaming.
+await for (final reply in client.chat(
+  Stream.fromIterable([HelloRequest()..name = 'Fory']),
+)) {
+  print(reply.reply);
+}
+```
+
+The generated descriptors preserve the exact IDL service and method names for
+the gRPC path, while the Dart methods use camelCase names.
+
+## Generated Module Names
+
+Dart model files and schema modules are named after the package's last segment,
+not the gRPC service name. (When a schema has no package, the source file stem 
is
+used instead.)
+
+| Schema input (package)          | Model file          | Schema module        
   |
+| ------------------------------- | ------------------- | 
----------------------- |
+| `service.fdl` (`demo.greeter`)  | `greeter.dart`      | `GreeterForyModule`  
   |
+| `api.fdl` (`demo.order_events`) | `order_events.dart` | 
`OrderEventsForyModule` |
+| `greeter.fdl` (`demo.greeter`)  | `greeter.dart`      | `GreeterForyModule`  
   |
+
+A gRPC service named `Greeter` still generates the companion
+`<stem>_grpc.dart` with `GreeterClient` and `GreeterServiceBase`; it does not
+change the schema module name. If several schema files use the same package
+leaf, place them in distinct output directories or choose package/file names 
that
+produce distinct Dart model files.
+
+## Operations
+
+The generated service code only replaces request and response serialization.
+All normal gRPC operational features still belong to your gRPC stack:
+
+- Deadlines and cancellations
+- TLS and authentication
+- Name resolution and load balancing
+- Client and server interceptors
+- Status codes and metadata
+- Channel lifecycle management
+
+## Troubleshooting
+
+### Missing `package:grpc` Types
+
+Add `grpc` to your application dependencies. Generated Fory service files 
import
+grpc-dart APIs, but `fory` intentionally does not depend on gRPC.
+
+### Generated Code References a Missing `.fory.dart` Part
+
+Run `dart run build_runner build --delete-conflicting-outputs` after generating
+or regenerating the Dart sources. The serializer part file is produced by
+`build_runner`, not by `foryc`.
+
+### Protobuf Clients Cannot Decode the Service
+
+Fory gRPC companions do not use protobuf wire encoding for messages. Use a
+Fory-generated client for Fory-generated services, or expose a separate 
protobuf
+service endpoint for generic protobuf clients.
diff --git a/docs/guide/dart/index.md b/docs/guide/dart/index.md
index 6c467bbe1c..d779afc99d 100644
--- a/docs/guide/dart/index.md
+++ b/docs/guide/dart/index.md
@@ -138,6 +138,7 @@ dart run build_runner build --delete-conflicting-outputs
 | [Supported Types](supported-types.md)           | Built-in xlang values, 
wrappers, collections, and structs       |
 | [Schema Evolution](schema-evolution.md)         | Compatible structs and 
evolving schemas                         |
 | [Web Platform Support](web-platform-support.md) | Dart VM/AOT, Flutter, and 
web support, limits, and validation   |
+| [gRPC Support](grpc-support.md)                 | Generated Fory-backed gRPC 
service companions                   |
 | [Troubleshooting](troubleshooting.md)           | Common errors, 
diagnostics, and validation steps                |
 
 ## Related Resources
diff --git a/docs/guide/dart/troubleshooting.md 
b/docs/guide/dart/troubleshooting.md
index d94ac4e794..5f066920a2 100644
--- a/docs/guide/dart/troubleshooting.md
+++ b/docs/guide/dart/troubleshooting.md
@@ -138,9 +138,26 @@ dart run build_runner build --delete-conflicting-outputs
 dart test
 ```
 
+## Generated gRPC files cannot find `package:grpc` types
+
+**Cause**: gRPC packages are application dependencies. The `fory` package does
+not add gRPC as a hard dependency.
+
+**Fix**: Add `grpc` to your `pubspec.yaml` (and the `build_runner` dev
+dependency), then run `dart pub get`. See [gRPC Support](grpc-support.md).
+
+## A protobuf client cannot decode a Fory gRPC service
+
+**Cause**: Fory gRPC companions use gRPC transports with Fory-encoded message
+bodies, not protobuf wire encoding.
+
+**Fix**: Use a Fory-generated client for Fory-generated services, or expose a
+separate protobuf service endpoint for generic protobuf clients.
+
 ## Related Topics
 
 - [Xlang Serialization](xlang-serialization.md)
 - [Code Generation](code-generation.md)
 - [Custom Serializers](custom-serializers.md)
 - [Web Platform Support](web-platform-support.md)
+- [gRPC Support](grpc-support.md)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to