Hierarchical Configuration
Hierarchical configuration allows you to set SDK configuration parameters at multiple levels, with more specific levels overriding broader ones. This provides fine-grained control over how your SDK behaves for different services, methods, or individual requests.
Configuration Hierarchy
Configuration settings cascade through four levels, from most general to most specific:
- SDK Level: Applied to all services, methods, and requests
- Service Level: Applied to all methods within a specific service
- Method Level: Applied to a specific method
- Request Level: Applied to a single API call
When a configuration is set at multiple levels, the more specific level takes precedence. For example, a baseUrl set at the method level will override one set at the SDK level for that specific method.
Language Support
Supported SDK languages:
| TypeScript / Javascript | Java / Kotlin | Python | C# | Go | PHP |
|---|---|---|---|---|---|
| ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
Support for hierarchical configuration in other languages is coming soon. Currently, only TypeScript SDKs support full hierarchical configuration (SDK, Service, Method, and Request levels).
How It Works
Configuration Resolution
When making an API call, the SDK resolves configuration by merging settings from all hierarchy levels, with more specific levels overriding broader ones:
Request Config (most specific)
↓ merges with
Method Config
↓ merges with
Service Config
↓ merges with
SDK Config (most general)
The final resolved configuration is used for the API request.
baseUrl vs Environment Precedence
When resolving the base URL for a request, the SDK follows a two-step process:
-
Hierarchical Merge: First, the configuration is resolved by merging settings from all levels: Request > Method > Service > SDK. More specific levels override broader ones. This applies to both
baseUrlandenvironment. -
baseUrlPrecedence: After the merge, if the final resolved configuration contains both abaseUrland anenvironment, thebaseUrlis always used. Theenvironmentis only used if nobaseUrlis present in the final configuration.
For example:
-
If SDK-level has
baseUrl: "https://api.example.com"and method-level hasenvironment: Environment.STAGING, the SDK-levelbaseUrlwill be used (baseUrlis stronger). -
If SDK-level has
baseUrl: "https://api.example.com"and method-level also hasbaseUrl: "https://staging.example.com", the method-levelbaseUrlwill be used (hierarchy applies - more specific wins). -
If SDK-level has
environment: Environment.PRODUCTIONand method-level hasenvironment: Environment.STAGING, the method-levelenvironmentwill be used (hierarchy applies - more specific wins). -
If SDK-level has
environment: Environment.PRODUCTIONand method-level hasbaseUrl: "https://staging.example.com", the method-levelbaseUrlwill be used (hierarchy applies, andbaseUrlis stronger).
baseUrl vs environment-
Use
baseUrlfor a direct string URL that gives you full control over the exact endpoint, like for a one-off custom server. -
Use
environmentto switch between a predefined set of URLs, likePRODUCTION,STAGING, orDEVELOPMENT.
Examples
- TypeScript
SDK-Level Configuration
Set configuration when initializing the SDK. This applies to all services, methods, and requests:
import { ExcitingSoda, Environment } from 'excitingsoda';
// Option 1: Set baseUrl at SDK level
const sdk = new ExcitingSoda({
baseUrl: 'https://api.example.com',
timeoutMs: 5000
});
import { ExcitingSoda, Environment } from 'excitingsoda';
// Option 2: Use environment enum
const sdk = new ExcitingSoda({
environment: Environment.PRODUCTION
});
Service-Level Configuration
Override configuration for all methods within a specific service:
// Set configuration for the users service
sdk.users.setConfig({
baseUrl: 'https://users-api.example.com',
timeoutMs: 10000
});
// All calls to sdk.users.* will use this configuration
await sdk.users.getUser('123');
await sdk.users.listUsers();
Method-Level Configuration
Override configuration for a specific method:
// Set configuration for a specific method
sdk.users.setGetUserConfig({
baseUrl: 'https://legacy-users.example.com',
timeoutMs: 15000
});
// Only this method uses the custom config
await sdk.users.getUser('123'); // Uses method-level config
await sdk.users.listUsers(); // Uses service-level or SDK-level config
Request-Level Configuration
Override configuration for a single API call:
// Override config for just this one request
await sdk.users.getUser('123', {
baseUrl: 'https://custom-endpoint.example.com',
timeoutMs: 20000
});
Complete Example: Hierarchy in Action
import { ExcitingSoda, Environment } from 'excitingsoda';
// 1. SDK-level: Default for everything
const sdk = new ExcitingSoda({
baseUrl: 'https://api.example.com',
timeoutMs: 5000
});
// 2. Service-level: Override for users service
sdk.users.setConfig({
timeoutMs: 10000 // Users service gets 10s timeout
});
// 3. Method-level: Override for specific method
sdk.users.setGetUserConfig({
baseUrl: 'https://legacy-api.example.com' // Only getUser uses this URL
});
// 4. Request-level: Override for this one call
await sdk.users.getUser('123', {
timeoutMs: 30000 // This call gets 30s timeout
});
// Resolution for the getUser call above:
// baseUrl: 'https://legacy-api.example.com' (from method-level)
// timeoutMs: 30000 (from request-level, overrides service-level 10000)
baseUrl vs Environment Precedence
Both baseUrl and environment follow the normal hierarchy (more specific overrides less specific), but baseUrl is "stronger" - if both are present in the resolved config, baseUrl takes precedence:
// Hierarchy applies: method-level environment overrides SDK-level environment
const sdk = new ExcitingSoda({
environment: Environment.PRODUCTION
});
sdk.users.setGetUserConfig({
environment: Environment.STAGING // This will be used (more specific wins)
});
// Hierarchy applies: method-level baseUrl overrides SDK-level baseUrl
const sdk = new ExcitingSoda({
baseUrl: 'https://api.example.com'
});
sdk.users.setGetUserConfig({
baseUrl: 'https://staging.example.com' // This will be used (more specific wins)
});
// baseUrl is stronger: SDK-level baseUrl overrides method-level environment
const sdk = new ExcitingSoda({
baseUrl: 'https://api.example.com' // This will be used
});
sdk.users.setGetUserConfig({
environment: Environment.STAGING // This is ignored - baseUrl is stronger
});
// Hierarchy + baseUrl strength: method-level baseUrl overrides SDK-level environment
const sdk = new ExcitingSoda({
environment: Environment.PRODUCTION
});
sdk.users.setGetUserConfig({
baseUrl: 'https://staging.example.com' // This will be used (hierarchy + baseUrl is stronger)
});