Skip to content

Commit 2d4ee42

Browse files
authored
feat: add object ID options.proto (#30)
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent 5c69b2a commit 2d4ee42

File tree

2 files changed

+118
-5
lines changed

2 files changed

+118
-5
lines changed

docs/explanation/protobuf-extension-naming.md

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Protobuf Extension Naming
22

3-
Naming conventions for protobuf extensions in trogon-proto.
3+
Guidelines for creating protobuf extensions in trogon-proto. Follow these conventions when adding new extensions.
44

55
## Rules
66

@@ -50,17 +50,55 @@ message EnumValueOptions {
5050

5151
`Namespace` stays in `namespace.proto` because it's shared by `FileOptions`, `EnumOptions`, and `EnumValueOptions.Format`.
5252

53-
## Current Structure
53+
## Structure Template
5454

55+
When creating a new extension at `trogon/<feature>/<version>/options.proto`:
56+
57+
```text
58+
trogon/<feature>/<version>/options.proto
59+
├─ FileOptions { ... } → file (8700XX)
60+
├─ MessageOptions { ... } → message (8700XX)
61+
├─ EnumOptions { ... } → enum (8700XX)
62+
├─ EnumValueOptions { ... } → enum_value (8700XX)
63+
├─ FieldOptions { ... } → field (8700XX)
64+
└─ <Nested Types> — type-specific, nested inside parent Options
5565
```
56-
options.proto
66+
67+
**Pick the descriptor types you need:**
68+
- `FileOptions` - file-level options (e.g., module namespace)
69+
- `MessageOptions` - message-level options (e.g., validation rules)
70+
- `EnumOptions` - enum-level options (e.g., allowed values)
71+
- `EnumValueOptions` - enum value-level options (e.g., code generation hints)
72+
- `FieldOptions` - field-level options (e.g., format constraints)
73+
74+
**Field number selection:**
75+
- Start at next available number in 870000+ range
76+
- Each wrapper gets its own extension number
77+
- Internal fields within wrappers can reuse numbers (they're scoped)
78+
79+
## Field Number Registry
80+
81+
Claim your extension numbers here to prevent conflicts:
82+
83+
| Number | Extension | Descriptor Type |
84+
|--------|-----------|-----------------|
85+
| 870000 | trogon.uuid.v1 | google.protobuf.FileOptions |
86+
| 870001 | trogon.uuid.v1 | google.protobuf.EnumOptions |
87+
| 870002 | trogon.uuid.v1 | google.protobuf.EnumValueOptions |
88+
| 870010 | trogon.object_id.v1alpha1 | google.protobuf.EnumValueOptions |
89+
| 870011–870999 | *Available* ||
90+
91+
## Examples in This Repo
92+
93+
```text
94+
trogon/uuid/v1/options.proto
5795
├─ FileOptions { namespace } → file (870000)
5896
├─ EnumOptions { namespace } → enum (870001)
5997
└─ EnumValueOptions { format } → enum_value (870002)
6098
└─ Format (nested) { namespace, template }
6199
62-
namespace.proto
63-
└─ Namespace { uuid | dns | url } — shared
100+
trogon/object_id/v1alpha1/options.proto
101+
└─ EnumValueOptions { object_type, separator } → enum_value (870010)
64102
```
65103

66104
## Field Number Ranges
@@ -71,6 +109,42 @@ namespace.proto
71109
| 1,000–99,999 | Public (register first) |
72110
| **100,000+** | **Private (use this)** |
73111

112+
## Creating a New Extension
113+
114+
1. **Choose a feature name and version**: `trogon/<feature>/<version>/`
115+
- Use semantic versioning: `v1`, `v2`, or alpha/beta: `v1alpha1`, `v1beta1`
116+
- Example: `trogon/validation/v1/`, `trogon/codegen/v1alpha1/`
117+
118+
2. **Create `options.proto`**: `proto/trogon/<feature>/<version>/options.proto`
119+
```protobuf
120+
syntax = "proto3";
121+
package trogon.<feature>.<version>;
122+
123+
import "elixirpb.proto";
124+
import "google/protobuf/descriptor.proto";
125+
126+
option (elixirpb.file).module_prefix = "TrogonProto.<Feature>.<Version>";
127+
```
128+
129+
3. **Define wrapper messages** for each descriptor type you need:
130+
```protobuf
131+
message EnumValueOptions {
132+
string my_field = 1;
133+
optional string my_optional_field = 2;
134+
}
135+
```
136+
137+
4. **Extend the Google descriptor** with your wrapper:
138+
```protobuf
139+
extend google.protobuf.EnumValueOptions {
140+
optional EnumValueOptions enum_value = 8700XX; // pick next available
141+
}
142+
```
143+
144+
5. **Document in this file** - add your extension to the "Examples" section
145+
146+
6. **Update field number registry** - claim your number(s) in this doc to prevent conflicts
147+
74148
## References
75149

76150
- [buf.validate](https://github.com/bufbuild/protovalidate)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
syntax = "proto3";
2+
package trogon.object_id.v1alpha1;
3+
4+
import "elixirpb.proto";
5+
import "google/protobuf/descriptor.proto";
6+
7+
option (elixirpb.file).module_prefix = "TrogonProto.ObjectId.V1Alpha1";
8+
9+
// EnumValueOptions defines enum-value-level options for object ID types.
10+
message EnumValueOptions {
11+
// The object type prefix for this ID (e.g., "review", "order", "fanid").
12+
string object_type = 1;
13+
14+
// Separator between prefix and id value. Defaults to "_" if not set.
15+
optional string separator = 2;
16+
}
17+
18+
extend google.protobuf.EnumValueOptions {
19+
// enum_value specifies the object ID type for an enum value.
20+
//
21+
// Example usage:
22+
//
23+
// // acme/type/v1/object_type.proto
24+
// syntax = "proto3";
25+
// package acme.type.v1;
26+
//
27+
// import "trogon/object_id/v1alpha1/options.proto";
28+
//
29+
// enum ObjectType {
30+
// OBJECT_TYPE_UNSPECIFIED = 0;
31+
// OBJECT_TYPE_ORDER = 1 [(trogon.object_id.v1alpha1.enum_value).object_type = "order"];
32+
// OBJECT_TYPE_SPECIAL = 2 [(trogon.object_id.v1alpha1.enum_value) = {
33+
// object_type: "special",
34+
// separator: "#"
35+
// }];
36+
// }
37+
//
38+
optional EnumValueOptions enum_value = 870010;
39+
}

0 commit comments

Comments
 (0)