-
Notifications
You must be signed in to change notification settings - Fork 157
Open
Description
📋 Feature Description
Add an Environment Switcher to DebugSwift that allows developers to quickly toggle between different environments (dev, staging, production) and manage environment-specific configurations.
🎯 Motivation
Most apps support multiple environments with different:
- API base URLs
- Feature flags
- Authentication endpoints
- Analytics keys
- Third-party SDK configurations
- Database connections
Currently, developers switch environments by:
- Changing build schemes
- Modifying configuration files
- Rebuilding the app
This is time-consuming and error-prone. An in-app environment switcher would dramatically improve development workflow.
✨ Proposed Features
Core Functionality
- Quick Environment Switch: Toggle environments instantly
- Environment Profiles: Predefined environment configurations
- Custom Environments: Create and manage custom environments
- Configuration Management: Store environment-specific settings
- Auto Data Clear: Optionally clear data on environment switch
- Environment Indicator: Visual badge showing current environment
Environment Configuration
- API Base URL: Environment-specific endpoints
- Feature Flags: Enable/disable features per environment
- Authentication: Different auth servers
- Analytics: Environment-specific tracking
- Database: Separate databases per environment
- Custom Keys: Any environment-specific values
Advanced Features
- Environment History: Track environment switches
- Quick Switch Gesture: Shake or swipe to change environment
- Environment Comparison: Compare settings across environments
- Import/Export: Share environment configurations
- Network Stub Integration: Auto-mock for specific environments
- Certificate Pinning: Per-environment SSL configurations
🎨 UI/UX Design
Environment Switcher Screen
┌─────────────────────────────────────────┐
│ Environment Switcher [✓ Active] │
├─────────────────────────────────────────┤
│ Current Environment: Production │
├─────────────────────────────────────────┤
│ Available Environments │
│ │
│ ● Development │
│ https://dev-api.example.com │
│ [Select] │
│ │
│ ◯ Staging │
│ https://staging-api.example.com │
│ [Select] │
│ │
│ ◯ Production (Current) │
│ https://api.example.com │
│ [✓ Active] │
│ │
│ ◯ QA │
│ https://qa-api.example.com │
│ [Select] │
├─────────────────────────────────────────┤
│ [+ Add Custom Environment] │
├─────────────────────────────────────────┤
│ Options │
│ ☑ Clear network history on switch │
│ ☑ Clear user data on switch │
│ ☑ Restart app after switch │
│ ☐ Show environment badge │
└─────────────────────────────────────────┘
Environment Detail Screen
┌─────────────────────────────────────────┐
│ < Environments Development [Edit]│
├─────────────────────────────────────────┤
│ General │
│ Name: Development │
│ Icon: 🔧 │
│ Color: Blue │
├─────────────────────────────────────────┤
│ API Configuration │
│ Base URL: │
│ https://dev-api.example.com │
│ │
│ Auth URL: │
│ https://dev-auth.example.com │
│ │
│ GraphQL Endpoint: │
│ https://dev-api.example.com/graphql │
├─────────────────────────────────────────┤
│ Feature Flags │
│ ☑ New UI Enabled │
│ ☑ Debug Logging │
│ ☐ Beta Features │
│ ☑ Mock Payments │
├─────────────────────────────────────────┤
│ Custom Configuration │
│ • Analytics Key: dev-analytics-123 │
│ • Database Name: app_dev.db │
│ • Mock Data: Enabled │
│ │
│ [+ Add Custom Key] │
├─────────────────────────────────────────┤
│ Actions │
│ [Export Configuration] │
│ [Duplicate Environment] │
│ [Delete Environment] │
└─────────────────────────────────────────┘
Environment Badge (when enabled)
┌────────────────────────────┐
│ App Screen [DEV 🔧] │ <- Badge in corner
│ │
│ │
└────────────────────────────┘
🔧 Technical Implementation
Architecture
public class EnvironmentManager {
public static let shared = EnvironmentManager()
public var currentEnvironment: Environment {
didSet {
handleEnvironmentChange(from: oldValue, to: currentEnvironment)
}
}
public var availableEnvironments: [Environment]
public var onEnvironmentChanged: ((Environment, Environment) -> Void)?
public func switchEnvironment(_ environment: Environment, clearData: Bool = true)
public func addCustomEnvironment(_ environment: Environment)
public func exportConfiguration() -> Data
public func importConfiguration(_ data: Data) throws
}
public struct Environment: Codable, Identifiable {
public let id: UUID
public var name: String
public var icon: String
public var color: UIColor
public var configuration: EnvironmentConfiguration
public init(
name: String,
icon: String = "🌍",
color: UIColor = .blue,
configuration: EnvironmentConfiguration
)
}
public struct EnvironmentConfiguration: Codable {
public var apiBaseURL: String
public var authURL: String?
public var graphQLEndpoint: String?
public var featureFlags: [String: Bool]
public var customValues: [String: String]
// Convenience accessors
public func value(forKey key: String) -> String?
public func bool(forKey key: String) -> Bool
public func isFeatureEnabled(_ feature: String) -> Bool
}Usage in App
// Define environments in AppDelegate or App struct
func setupEnvironments() {
let development = Environment(
name: "Development",
icon: "🔧",
color: .blue,
configuration: EnvironmentConfiguration(
apiBaseURL: "https://dev-api.example.com",
authURL: "https://dev-auth.example.com",
featureFlags: [
"newUI": true,
"debugLogging": true,
"mockPayments": true
],
customValues: [
"analyticsKey": "dev-analytics-123",
"databaseName": "app_dev.db"
]
)
)
let staging = Environment(
name: "Staging",
icon: "🧪",
color: .orange,
configuration: EnvironmentConfiguration(
apiBaseURL: "https://staging-api.example.com",
authURL: "https://staging-auth.example.com",
featureFlags: [
"newUI": true,
"debugLogging": false,
"mockPayments": false
],
customValues: [
"analyticsKey": "staging-analytics-456"
]
)
)
let production = Environment(
name: "Production",
icon: "🚀",
color: .green,
configuration: EnvironmentConfiguration(
apiBaseURL: "https://api.example.com",
authURL: "https://auth.example.com",
featureFlags: [:],
customValues: [:]
)
)
DebugSwift.Environment.availableEnvironments = [
development, staging, production
]
DebugSwift.Environment.currentEnvironment = development
}
// Access environment configuration
let apiURL = DebugSwift.Environment.current.configuration.apiBaseURL
let isFeatureEnabled = DebugSwift.Environment.current.configuration.isFeatureEnabled("newUI")
// Listen for environment changes
DebugSwift.Environment.onEnvironmentChanged = { old, new in
print("Switched from \(old.name) to \(new.name)")
// Clear network history
DebugSwift.Network.shared.clearNetworkHistory()
// Reconnect services
APIClient.shared.reconnect()
// Optionally restart app
if DebugSwift.Environment.restartOnSwitch {
exit(0) // System will restart the app
}
}Environment Badge
class EnvironmentBadgeView: UIView {
private let label = UILabel()
func show(environment: Environment) {
label.text = "\(environment.icon) \(environment.name)"
backgroundColor = environment.color.withAlphaComponent(0.8)
// Position in top-right corner
if let window = UIApplication.shared.windows.first {
window.addSubview(self)
self.frame = CGRect(
x: window.bounds.width - 100,
y: window.safeAreaInsets.top,
width: 90,
height: 30
)
}
}
}Environment Persistence
extension EnvironmentManager {
private let currentEnvironmentKey = "debugswift.current.environment"
func saveCurrentEnvironment() {
if let data = try? JSONEncoder().encode(currentEnvironment) {
UserDefaults.standard.set(data, forKey: currentEnvironmentKey)
}
}
func loadCurrentEnvironment() {
guard let data = UserDefaults.standard.data(forKey: currentEnvironmentKey),
let environment = try? JSONDecoder().decode(Environment.self, from: data) else {
return
}
currentEnvironment = environment
}
}📝 Implementation Checklist
Phase 1: Basic Environment Switching
- Environment data structure
- Environment storage and persistence
- Basic environment switcher UI
- Environment configuration management
- Current environment indicator
Phase 2: Enhanced Features
- Custom environment creation
- Feature flags management
- Auto data clear on switch
- Environment badge overlay
- Import/export configurations
Phase 3: Advanced Features
- Quick switch gesture (shake)
- Environment comparison view
- History tracking
- Network integration (auto-clear)
- Certificate pinning per environment
- Environment validation
🧪 Testing Requirements
- Environment switching tests
- Configuration persistence tests
- Feature flag tests
- Import/export tests
- Data clearing tests
- UI state restoration tests
📚 Documentation
### Environment Switcher
- Quick toggle between dev/staging/production
- Environment-specific configurations
- Feature flags management
- Auto data clearing on switch
- Custom environments
// Setup environments
DebugSwift.Environment.configure(
environments: [development, staging, production],
default: development
)
// Access current environment
let apiURL = DebugSwift.Environment.current.apiBaseURL
// Listen for changes
DebugSwift.Environment.onEnvironmentChanged = { old, new in
// Handle environment switch
}🎯 Success Criteria
- Switch environments without rebuilding
- Manage environment-specific configurations
- Clear data automatically on switch
- Visual environment indicator
- Import/export configurations
- Feature flags per environment
- Minimal setup required
- Persist environment across launches
📊 Priority
High - Major developer productivity improvement.
🏷️ Labels
enhancement, feature, app-tools, developer-experience, high-priority
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
Backlog