@@ -156,82 +156,80 @@ $ secretspec check --provider env
156156```
157157
158158
159- ## Rust SDK with Type-Safe Code Generation
159+ ## Rust SDK
160+
161+ SecretSpec provides a proc macro that generates strongly-typed Rust structs from your ` secretspec.toml ` file at compile time.
162+
163+ ### Add to your ` Cargo.toml ` :
164+ ``` toml
165+ [dependencies ]
166+ secretspec = { version = " 0.1" , features = [" codegen" ] }
167+ ```
160168
161169### Basic Usage
162170
163171``` rust
164- use secretspec :: SecretSpec ;
172+ // Generate typed structs from secretspec.toml
173+ secretspec :: define_secrets! (" secretspec.toml" );
165174
166175fn main () -> Result <(), Box <dyn std :: error :: Error >> {
167- let spec = SecretSpec :: load ()? ;
176+ // Load secrets with type-safe struct
177+ let secrets = SecretSpec :: load (Provider :: Keyring )? ;
178+
179+ // Field names are lowercased versions of secret names
180+ println! (" Database: {}" , secrets . database_url); // DATABASE_URL -> database_url
168181
169- // Validate and get all secrets for the current environment
170- let secrets = spec . validate (None , None )? ;
182+ // Optional secrets are Option<String>
183+ if let Some (redis ) = & secrets . redis_url {
184+ println! (" Redis: {}" , redis );
185+ }
171186
172- // Access individual secrets
173- let db_url = secrets . get (" DATABASE_URL" )
174- . ok_or (" DATABASE_URL not found" )? ;
187+ // Set all secrets as environment variables
188+ secrets . set_as_env_vars ();
175189
176- println! (" Connecting to: {}" , db_url );
177190 Ok (())
178191}
179192```
180193
181- ### Type-Safe Code Generation
194+ ### Profile-Specific Types
182195
183- SecretSpec uses a proc macro to generate strongly-typed Rust structs from your ` secretspec.toml ` file :
196+ The macro generates exact types for each profile, ensuring compile-time safety :
184197
185- 1 . ** Add to your ` Cargo.toml ` :**
186- ``` toml
187- [dependencies ]
188- secretspec = { version = " 0.1" , features = [" codegen" ] }
189- ```
198+ ``` rust
199+ // Load with profile-specific types for maximum type safety
200+ match SecretSpec :: load_profile (Provider :: Keyring , Profile :: Production )? {
201+ SecretSpecProfile :: Production { api_key , database_url , redis_url , .. } => {
202+ // In production: api_key is String (required)
203+ // database_url is String (required)
204+ // redis_url might be String or Option<String> based on config
205+ println! (" Production API key: {}" , api_key );
206+ }
207+ SecretSpecProfile :: Development { api_key , database_url , .. } => {
208+ // In development: api_key is Option<String> (has default)
209+ // database_url is Option<String> (has default)
210+ if let Some (key ) = api_key {
211+ println! (" Dev API key: {}" , key );
212+ }
213+ }
214+ _ => {}
215+ }
216+ ```
190217
191- 2 . ** Use the proc macro in your code:**
192- ``` rust
193- // Generate typed structs from secretspec.toml
194- secretspec :: define_secrets! (" secretspec.toml" );
195-
196- use secretspec :: codegen :: Provider ;
197-
198- fn main () -> Result <(), Box <dyn std :: error :: Error >> {
199- // Load with strongly-typed struct
200- let secrets = SecretSpec :: load (Provider :: Keyring )? ;
201-
202- // Required secrets are guaranteed to exist
203- println! (" Database: {}" , secrets . database_url);
204-
205- // Optional secrets are Option<String>
206- if let Some (redis ) = & secrets . redis_url {
207- println! (" Redis: {}" , redis );
208- }
209-
210- // Set all secrets as environment variables
211- secrets . set_as_env_vars ();
212-
213- Ok (())
214- }
215- ```
218+ ### Generated Types
216219
217- 3 . ** Load with specific profile for exact types:**
218- ``` rust
219- // Load with profile-specific types
220- match SecretSpec :: load_profile (Provider :: Keyring , Profile :: Production ) {
221- Ok (SecretSpecProfile :: Production { api_key , database_url , .. }) => {
222- // In production, api_key is String (required)
223- println! (" API Key: {}" , api_key );
224- }
225- _ => unreachable! (),
226- }
227- ```
220+ The macro generates several types based on your ` secretspec.toml ` :
221+
222+ - ** ` SecretSpec ` ** - Main struct with union types (fields are ` Option<String> ` if optional in * any* profile)
223+ - ** ` SecretSpecProfile ` ** - Enum with profile-specific variants containing exact types
224+ - ** ` Profile ` ** - Enum of all profiles from your config (e.g., ` Development ` , ` Production ` )
225+ - ** ` Provider ` ** - Type-safe provider selection (` Keyring ` , ` Dotenv ` , ` Env ` )
226+
227+ ### Type Rules
228228
229- The macro generates:
230- - ` SecretSpec ` struct with union types (safe for any profile)
231- - ` SecretSpecProfile ` enum with exact types for each profile
232- - ` Profile ` enum with all profiles from your TOML
233- - Required secrets as ` String ` or ` Option<String> ` based on profile requirements
234- - Compile-time type safety
229+ - Secret fields are named as lowercase versions of the environment variable (e.g., ` DATABASE_URL ` → ` database_url ` )
230+ - A field is ` String ` if it's required and has no default in ALL profiles
231+ - A field is ` Option<String> ` if it's optional or has a default in ANY profile
232+ - Profile-specific types reflect the exact requirements for that profile
235233
236234## Adding a New Provider Backend
237235
0 commit comments