Skip to content

Commit 1a66bd9

Browse files
committed
directory structure and file organisation
1 parent 1e50b68 commit 1a66bd9

File tree

1 file changed

+139
-7
lines changed

1 file changed

+139
-7
lines changed

docs/connect/client.mdx

Lines changed: 139 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,21 @@ Use [buf](https://buf.build/) or `protoc` to generate the client code for your a
125125
Example `buf.gen.yaml` for Go:
126126

127127
```yaml buf.gen.yaml
128-
version: v1
128+
version: v2
129+
managed:
130+
enabled: true
131+
override:
132+
- file_option: go_package_prefix
133+
value: github.com/wundergraph/cosmo/router-tests/testdata/connectrpc/client
129134
plugins:
130-
- plugin: buf.build/connectrpc/go
131-
out: gen/go
132-
opt: paths=source_relative
133-
- plugin: buf.build/protocolbuffers/go
134-
out: gen/go
135-
opt: paths=source_relative
135+
- remote: buf.build/protocolbuffers/go
136+
out: client
137+
opt:
138+
- paths=source_relative
139+
- remote: buf.build/connectrpc/go
140+
out: client
141+
opt:
142+
- paths=source_relative
136143
```
137144

138145
Run the generation:
@@ -181,6 +188,131 @@ func main() {
181188
}
182189
```
183190

191+
## Directory Structure & Organization
192+
193+
The Cosmo Router uses a convention-based directory structure to automatically discover and load Connect RPC services. This approach co-locates proto files with their GraphQL operations for easy management.
194+
195+
### Configuration
196+
197+
Configure the router to point to your root services directory using a storage provider:
198+
199+
```yaml config.yaml
200+
connect_rpc:
201+
enabled: true
202+
server:
203+
listen_addr: "0.0.0.0:8081"
204+
services_provider_id: "fs-services"
205+
206+
storage_providers:
207+
file_system:
208+
- id: "fs-services"
209+
path: "./services" # Root services directory
210+
```
211+
212+
The router will recursively walk the `services` directory and automatically discover all proto files and their associated GraphQL operations.
213+
214+
### Recommended Structure
215+
216+
For organization purposes, we recommend keeping all services in a root `services` directory, with subdirectories for packages and individual services.
217+
218+
#### Single Service per Package
219+
220+
When you have one service per package, you can organize files directly in the package directory:
221+
222+
```
223+
services/
224+
└── employee.v1/ # Package directory
225+
├── employee.proto # Proto definition
226+
├── employee.proto.lock.json
227+
├── GetEmployee.graphql # Operation files
228+
├── UpdateEmployee.graphql
229+
└── DeleteEmployee.graphql
230+
```
231+
232+
Or with operations in a subdirectory:
233+
234+
```
235+
services/
236+
└── employee.v1/
237+
├── employee.proto
238+
├── employee.proto.lock.json
239+
└── operations/
240+
├── GetEmployee.graphql
241+
├── UpdateEmployee.graphql
242+
└── DeleteEmployee.graphql
243+
```
244+
245+
#### Multiple Services per Package
246+
247+
When multiple services share the same proto package, organize them in service subdirectories:
248+
249+
```
250+
services/
251+
└── company.v1/ # Package directory
252+
├── EmployeeService/ # First service
253+
│ ├── employee.proto # package company.v1; service EmployeeService
254+
│ ├── employee.proto.lock.json
255+
│ └── operations/
256+
│ ├── GetEmployee.graphql
257+
│ └── UpdateEmployee.graphql
258+
└── DepartmentService/ # Second service, same package
259+
├── department.proto # package company.v1; service DepartmentService
260+
├── department.proto.lock.json
261+
└── operations/
262+
├── GetDepartment.graphql
263+
└── ListDepartments.graphql
264+
```
265+
266+
### Flexible Organization
267+
268+
The router determines service identity by proto package declarations, not directory names. This gives you flexibility in organizing your files:
269+
270+
```
271+
services/
272+
├── hr-services/
273+
│ ├── employee.proto # package company.v1; service EmployeeService
274+
│ └── GetEmployee.graphql
275+
└── admin-services/
276+
├── department.proto # package company.v1; service DepartmentService
277+
└── GetDepartment.graphql
278+
```
279+
280+
<Note>
281+
**Service Uniqueness**: The combination of proto package name and service name must be unique. For example, you can have multiple services with the same package name (e.g., `company.v1`) as long as they have different service names (`EmployeeService`, `DepartmentService`). The router uses the package + service combination to identify and route requests.
282+
</Note>
283+
284+
### Discovery Rules
285+
286+
The router follows these rules when discovering services:
287+
288+
1. **Recursive Discovery**: The router recursively walks the services directory to find all `.proto` files
289+
2. **Proto Association**: Each `.proto` file discovered becomes a service endpoint
290+
3. **Operation Association**: All `.graphql` files in the same directory (or subdirectories) are associated with the nearest parent `.proto` file
291+
4. **Nested Proto Limitation**: If a `.proto` file is found in a directory, any `.proto` files in subdirectories are **not** discovered (the parent proto takes precedence)
292+
293+
#### Example: Nested Proto Files
294+
295+
```
296+
services/
297+
└── employee.v1/
298+
├── employee.proto # ✅ Discovered as a service
299+
├── GetEmployee.graphql # ✅ Associated with employee.proto
300+
└── nested/
301+
├── other.proto # ❌ NOT discovered (parent proto found first)
302+
└── UpdateEmployee.graphql # ✅ Still associated with employee.proto
303+
```
304+
305+
<Warning>
306+
**Avoid Nested Proto Files**: Do not place `.proto` files in subdirectories of a directory that already contains a `.proto` file. The nested proto files will not be discovered by the router.
307+
</Warning>
308+
309+
### Best Practices
310+
311+
1. **Use Semantic Versioning**: Include version numbers in package names (e.g., `employee.v1`, `employee.v2`) to support API evolution
312+
2. **Co-locate Operations**: Keep GraphQL operations close to their proto definitions for easier maintenance
313+
3. **Consistent Naming**: Use clear, descriptive names for packages and services that reflect their purpose
314+
4. **Lock File Management**: Always commit `.proto.lock.json` files to version control to maintain field number stability
315+
184316
## Observability
185317
186318
The Cosmo Router provides built-in [observability features](/router/metrics-and-monitoring) that work seamlessly with Connect Client. Because the Router translates RPC calls into GraphQL operations, you get detailed metrics and tracing for both layers.

0 commit comments

Comments
 (0)