Skip to content

Commit 600dc48

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

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

docs/connect/client.mdx

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,131 @@ func main() {
181181
}
182182
```
183183

184+
## Directory Structure & Organization
185+
186+
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.
187+
188+
### Configuration
189+
190+
Configure the router to point to your root services directory using a storage provider:
191+
192+
```yaml config.yaml
193+
connect_rpc:
194+
enabled: true
195+
server:
196+
listen_addr: "0.0.0.0:8081"
197+
services_provider_id: "fs-services"
198+
199+
storage_providers:
200+
file_system:
201+
- id: "fs-services"
202+
path: "./services" # Root services directory
203+
```
204+
205+
The router will recursively walk the `services` directory and automatically discover all proto files and their associated GraphQL operations.
206+
207+
### Recommended Structure
208+
209+
For organization purposes, we recommend keeping all services in a root `services` directory, with subdirectories for packages and individual services.
210+
211+
#### Single Service per Package
212+
213+
When you have one service per package, you can organize files directly in the package directory:
214+
215+
```
216+
services/
217+
└── employee.v1/ # Package directory
218+
├── employee.proto # Proto definition
219+
├── employee.proto.lock.json
220+
├── GetEmployee.graphql # Operation files
221+
├── UpdateEmployee.graphql
222+
└── DeleteEmployee.graphql
223+
```
224+
225+
Or with operations in a subdirectory:
226+
227+
```
228+
services/
229+
└── employee.v1/
230+
├── employee.proto
231+
├── employee.proto.lock.json
232+
└── operations/
233+
├── GetEmployee.graphql
234+
├── UpdateEmployee.graphql
235+
└── DeleteEmployee.graphql
236+
```
237+
238+
#### Multiple Services per Package
239+
240+
When multiple services share the same proto package, organize them in service subdirectories:
241+
242+
```
243+
services/
244+
└── company.v1/ # Package directory
245+
├── EmployeeService/ # First service
246+
│ ├── employee.proto # package company.v1; service EmployeeService
247+
│ ├── employee.proto.lock.json
248+
│ └── operations/
249+
│ ├── GetEmployee.graphql
250+
│ └── UpdateEmployee.graphql
251+
└── DepartmentService/ # Second service, same package
252+
├── department.proto # package company.v1; service DepartmentService
253+
├── department.proto.lock.json
254+
└── operations/
255+
├── GetDepartment.graphql
256+
└── ListDepartments.graphql
257+
```
258+
259+
### Flexible Organization
260+
261+
The router determines service identity by proto package declarations, not directory names. This gives you flexibility in organizing your files:
262+
263+
```
264+
services/
265+
├── hr-services/
266+
│ ├── employee.proto # package company.v1; service EmployeeService
267+
│ └── GetEmployee.graphql
268+
└── admin-services/
269+
├── department.proto # package company.v1; service DepartmentService
270+
└── GetDepartment.graphql
271+
```
272+
273+
<Note>
274+
**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.
275+
</Note>
276+
277+
### Discovery Rules
278+
279+
The router follows these rules when discovering services:
280+
281+
1. **Recursive Discovery**: The router recursively walks the services directory to find all `.proto` files
282+
2. **Proto Association**: Each `.proto` file discovered becomes a service endpoint
283+
3. **Operation Association**: All `.graphql` files in the same directory (or subdirectories) are associated with the nearest parent `.proto` file
284+
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)
285+
286+
#### Example: Nested Proto Files
287+
288+
```
289+
services/
290+
└── employee.v1/
291+
├── employee.proto # ✅ Discovered as a service
292+
├── GetEmployee.graphql # ✅ Associated with employee.proto
293+
└── nested/
294+
├── other.proto # ❌ NOT discovered (parent proto found first)
295+
└── UpdateEmployee.graphql # ✅ Still associated with employee.proto
296+
```
297+
298+
<Warning>
299+
**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.
300+
</Warning>
301+
302+
### Best Practices
303+
304+
1. **Use Semantic Versioning**: Include version numbers in package names (e.g., `employee.v1`, `employee.v2`) to support API evolution
305+
2. **Co-locate Operations**: Keep GraphQL operations close to their proto definitions for easier maintenance
306+
3. **Consistent Naming**: Use clear, descriptive names for packages and services that reflect their purpose
307+
4. **Lock File Management**: Always commit `.proto.lock.json` files to version control to maintain field number stability
308+
184309
## Observability
185310
186311
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)