Documentation Index
Fetch the complete documentation index at: https://docs-mstore.faisalaffan.com/llms.txt
Use this file to discover all available pages before exploring further.
Konfigurasi Environment
Panduan lengkap untuk konfigurasi environment MStore Mobile.
๐ Multiple Environments
MStore mendukung 3 environment berbeda:
- Development - Untuk development lokal
- Staging - Untuk testing sebelum production
- Production - Untuk release ke users
๐ Environment Files
Struktur File
deploy/
โโโ .env.dev # Development environment
โโโ .env.staging # Staging environment
โโโ .env.prod # Production environment
.env.dev (Development)
# API Configuration
API_BASE_URL=https://dev-api.mstore.com
API_TIMEOUT=30000
# MQTT Configuration
MQTT_BROKER=dev-mqtt.mstore.com
MQTT_PORT=1883
MQTT_USERNAME=dev_user
MQTT_PASSWORD=dev_password_123
MQTT_CLIENT_ID=mstore_mobile_dev
# Feature Flags
ENABLE_ANALYTICS=false
ENABLE_CRASHLYTICS=false
ENABLE_DEBUG_LOGGING=true
# MinIO/S3 Configuration
MINIO_ENDPOINT=https://dev-storage.mstore.com
MINIO_ACCESS_KEY=dev_access_key
MINIO_SECRET_KEY=dev_secret_key
MINIO_BUCKET=mstore-dev
.env.staging (Staging)
# API Configuration
API_BASE_URL=https://staging-api.mstore.com
API_TIMEOUT=20000
# MQTT Configuration
MQTT_BROKER=staging-mqtt.mstore.com
MQTT_PORT=1883
MQTT_USERNAME=staging_user
MQTT_PASSWORD=staging_password_456
MQTT_CLIENT_ID=mstore_mobile_staging
# Feature Flags
ENABLE_ANALYTICS=true
ENABLE_CRASHLYTICS=true
ENABLE_DEBUG_LOGGING=true
# MinIO/S3 Configuration
MINIO_ENDPOINT=https://staging-storage.mstore.com
MINIO_ACCESS_KEY=staging_access_key
MINIO_SECRET_KEY=staging_secret_key
MINIO_BUCKET=mstore-staging
.env.prod (Production)
# API Configuration
API_BASE_URL=https://api.mstore.com
API_TIMEOUT=15000
# MQTT Configuration
MQTT_BROKER=mqtt.mstore.com
MQTT_PORT=1883
MQTT_USERNAME=prod_user
MQTT_PASSWORD=prod_secure_password_789
MQTT_CLIENT_ID=mstore_mobile_prod
# Feature Flags
ENABLE_ANALYTICS=true
ENABLE_CRASHLYTICS=true
ENABLE_DEBUG_LOGGING=false
# MinIO/S3 Configuration
MINIO_ENDPOINT=https://storage.mstore.com
MINIO_ACCESS_KEY=prod_access_key
MINIO_SECRET_KEY=prod_secret_key
MINIO_BUCKET=mstore-production
๐ง App Constants
File: lib/pkg/common/app_constants.dart
import 'package:flutter_dotenv/flutter_dotenv.dart';
// API Configuration
final String API_BASE_URL = dotenv.env['API_BASE_URL'] ?? '';
final int API_TIMEOUT = int.tryParse(dotenv.env['API_TIMEOUT'] ?? '15000') ?? 15000;
// MQTT Configuration
final String MQTT_BROKER = dotenv.env['MQTT_BROKER'] ?? '';
final String MQTT_PORT = dotenv.env['MQTT_PORT'] ?? '1883';
final String MQTT_USERNAME = dotenv.env['MQTT_USERNAME'] ?? '';
final String MQTT_PASSWORD = dotenv.env['MQTT_PASSWORD'] ?? '';
final String MQTT_CLIENT_ID = dotenv.env['MQTT_CLIENT_ID'] ?? '';
// Feature Flags
final bool ENABLE_ANALYTICS = dotenv.env['ENABLE_ANALYTICS'] == 'true';
final bool ENABLE_CRASHLYTICS = dotenv.env['ENABLE_CRASHLYTICS'] == 'true';
final bool ENABLE_DEBUG_LOGGING = dotenv.env['ENABLE_DEBUG_LOGGING'] == 'true';
// Storage Configuration
final String MINIO_ENDPOINT = dotenv.env['MINIO_ENDPOINT'] ?? '';
final String MINIO_ACCESS_KEY = dotenv.env['MINIO_ACCESS_KEY'] ?? '';
final String MINIO_SECRET_KEY = dotenv.env['MINIO_SECRET_KEY'] ?? '';
final String MINIO_BUCKET = dotenv.env['MINIO_BUCKET'] ?? '';
๐ฅ Firebase Configuration
Multiple Firebase Projects
MStore menggunakan Firebase project berbeda untuk setiap environment.
iOS Configuration
ios/Runner/
โโโ GoogleService-Info.plist # Development (default)
โโโ GoogleService-Info-Staging.plist # Staging
โโโ GoogleService-Info-Production.plist # Production
Script untuk switch Firebase config (iOS):
# ios/scripts/copy-firebase-config.sh
#!/bin/bash
FLAVOR=$1
if [ "$FLAVOR" == "production" ]; then
cp ios/Runner/GoogleService-Info-Production.plist ios/Runner/GoogleService-Info.plist
elif [ "$FLAVOR" == "staging" ]; then
cp ios/Runner/GoogleService-Info-Staging.plist ios/Runner/GoogleService-Info.plist
else
cp ios/Runner/GoogleService-Info.plist ios/Runner/GoogleService-Info.plist
fi
Android Configuration
android/app/src/
โโโ development/
โ โโโ google-services.json
โโโ staging/
โ โโโ google-services.json
โโโ production/
โโโ google-services.json
Android Gradle otomatis memilih config berdasarkan flavor.
Firebase Options
File: lib/core/firebase/firebase_options_*.dart
// firebase_options_dev.dart
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (Platform.isIOS) {
return ios;
} else if (Platform.isAndroid) {
return android;
} else if (Platform.isMacOS) {
return macos;
} else {
return web;
}
}
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIza...',
appId: '1:123:ios:abc',
messagingSenderId: '123',
projectId: 'mstore-dev',
storageBucket: 'mstore-dev.appspot.com',
iosBundleId: 'com.mstore.mobile.dev',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIza...',
appId: '1:123:android:def',
messagingSenderId: '123',
projectId: 'mstore-dev',
storageBucket: 'mstore-dev.appspot.com',
);
// ... web, macos
}
๐จ Flavor Configuration
iOS (Xcode Schemes)
- Open Xcode
- Product โ Scheme โ Manage Schemes
- Create schemes:
Runner-Development
Runner-Staging
Runner-Production
Android (build.gradle)
// android/app/build.gradle
android {
flavorDimensions "environment"
productFlavors {
development {
dimension "environment"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
resValue "string", "app_name", "MStore Dev"
}
staging {
dimension "environment"
applicationIdSuffix ".staging"
versionNameSuffix "-staging"
resValue "string", "app_name", "MStore Staging"
}
production {
dimension "environment"
resValue "string", "app_name", "MStore"
}
}
}
๐ Running with Flavors
Development
# iOS
flutter run --flavor development -t lib/main_development.dart
# Android
flutter run --flavor development -t lib/main_development.dart
# Web
flutter run -d chrome --flavor development -t lib/main_development.dart
Staging
flutter run --flavor staging -t lib/main_staging.dart
Production
flutter run --flavor production -t lib/main_production.dart
๐๏ธ Build Commands
Development Build
# iOS
flutter build ios --flavor development -t lib/main_development.dart
# Android APK
flutter build apk --flavor development -t lib/main_development.dart
# Android App Bundle
flutter build appbundle --flavor development -t lib/main_development.dart
Production Build
# iOS
flutter build ios --release --flavor production -t lib/main_production.dart
# Android
flutter build appbundle --release --flavor production -t lib/main_production.dart
๐ Secure Configuration
Sensitive Data
JANGAN commit sensitive data ke Git!
# .gitignore
deploy/.env.*
ios/Runner/GoogleService-Info*.plist
android/app/google-services.json
android/app/src/*/google-services.json
Environment Variables di CI/CD
Gunakan secrets management:
GitHub Actions
# .github/workflows/build.yml
env:
API_BASE_URL: ${{ secrets.API_BASE_URL }}
MQTT_PASSWORD: ${{ secrets.MQTT_PASSWORD }}
GitLab CI
# .gitlab-ci.yml
variables:
API_BASE_URL: $API_BASE_URL
MQTT_PASSWORD: $MQTT_PASSWORD
๐ฑ App Configuration
App Info
// lib/pkg/common/app_info.dart
class AppInfo {
static const String appName = 'MStore';
static const String packageName = 'com.mstore.mobile';
static const String version = '1.0.0';
static const int buildNumber = 202510052314;
static String get fullVersion => '$version+$buildNumber';
}
// lib/pkg/common/platform_config.dart
class PlatformConfig {
static bool get isIOS => Platform.isIOS;
static bool get isAndroid => Platform.isAndroid;
static bool get isWeb => kIsWeb;
static bool get isMobile => isIOS || isAndroid;
static bool get isDesktop => Platform.isMacOS || Platform.isWindows;
// Platform-specific features
static bool get supportsBiometric => isMobile;
static bool get supportsBluetoothPrinter => isMobile;
static bool get supportsNFC => isAndroid;
}
๐ฏ Feature Flags
Remote Config (Firebase)
class FeatureFlagService {
final FirebaseRemoteConfig _remoteConfig;
Future<void> init() async {
await _remoteConfig.setConfigSettings(
RemoteConfigSettings(
fetchTimeout: const Duration(minutes: 1),
minimumFetchInterval: const Duration(hours: 1),
),
);
await _remoteConfig.setDefaults({
'enable_new_checkout': false,
'enable_loyalty_program': false,
'maintenance_mode': false,
});
await _remoteConfig.fetchAndActivate();
}
bool isFeatureEnabled(String feature) {
return _remoteConfig.getBool(feature);
}
}
Local Feature Flags
class LocalFeatureFlags {
static const bool enableBetaFeatures = bool.fromEnvironment(
'ENABLE_BETA_FEATURES',
defaultValue: false,
);
static const bool enableDebugTools = bool.fromEnvironment(
'ENABLE_DEBUG_TOOLS',
defaultValue: false,
);
}
๐๏ธ Database Configuration
Isar Database
class DatabaseConfig {
static String get databaseName {
if (kDebugMode) {
return 'mstore_dev.isar';
} else {
return 'mstore.isar';
}
}
static Future<Isar> openDatabase() async {
final dir = await getApplicationDocumentsDirectory();
return await Isar.open(
[
ProductLocalSchema,
TransactionLocalSchema,
// ... other schemas
],
directory: dir.path,
name: databaseName,
inspector: kDebugMode, // Enable inspector in debug mode
);
}
}
๐ Debugging Configuration
void main() {
if (kDebugMode) {
// Enable debug logging
Logger.root.level = Level.ALL;
// Enable network inspector
HttpOverrides.global = DebugHttpOverrides();
// Enable performance overlay
debugPaintSizeEnabled = false;
debugPaintBaselinesEnabled = false;
}
runApp(MyApp());
}
VS Code Launch Configuration
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Development",
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": ["--flavor", "development"]
},
{
"name": "Staging",
"request": "launch",
"type": "dart",
"program": "lib/main_staging.dart",
"args": ["--flavor", "staging"]
},
{
"name": "Production",
"request": "launch",
"type": "dart",
"program": "lib/main_production.dart",
"args": ["--flavor", "production"]
}
]
}
๐ Monitoring Configuration
Firebase Crashlytics
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (ENABLE_CRASHLYTICS) {
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
PlatformDispatcher.instance.onError = (error, stack) {
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
return true;
};
}
runApp(MyApp());
}
Firebase Analytics
class AnalyticsService {
final FirebaseAnalytics _analytics = FirebaseAnalytics.instance;
Future<void> logEvent(String name, Map<String, dynamic> parameters) async {
if (!ENABLE_ANALYTICS) return;
await _analytics.logEvent(
name: name,
parameters: parameters,
);
}
}
๐งช Testing Configuration
// test/test_config.dart
class TestConfig {
static const String mockApiBaseUrl = 'https://mock-api.test';
static const String testDatabaseName = 'test.isar';
static Future<void> setupTestEnvironment() async {
TestWidgetsFlutterBinding.ensureInitialized();
// Load test environment
await dotenv.load(fileName: 'deploy/.env.test');
// Setup mock services
setupMockDI();
}
}
Next Steps
Best Practices:
- โ
Gunakan environment files untuk configuration
- โ
Jangan commit sensitive data
- โ
Gunakan feature flags untuk gradual rollout
- โ
Setup proper monitoring di production
- โ
Test di semua environments sebelum release