Firebase Provider (drft_firebase)

The Firebase provider enables DRFT to manage Firebase projects and apps - essential infrastructure for Flutter applications.

Why Firebase Provider?

  • Flutter Ecosystem: Most Flutter apps use Firebase for backend services
  • Comprehensive Configuration: Projects and apps for iOS, Android, and Web
  • Terraform Gap: Limited Firebase support in Terraform
  • High Value: Solves real pain points for Flutter developers

Installation

# pubspec.yaml
dependencies:
  drft: ^1.0.0
  drft_firebase: ^1.0.0

Configuration

The Firebase provider uses the firebase_management package and supports Application Default Credentials (ADC) or explicit credential configuration.

import 'package:drft/drft.dart';
import 'package:drft_firebase/drft_firebase.dart';
import 'package:firebase_management/firebase_management.dart';

final provider = FirebaseProvider(
  // Optional: provide credentials explicitly
  // If not provided, will use Application Default Credentials
  credentials: Credentials.fromServiceAccount('path/to/service-account.json'),
);

Authentication

The provider supports multiple authentication methods:

  1. Application Default Credentials (ADC) - Recommended for local development

    gcloud auth application-default login
    
  2. Service Account JSON - For production and CI/CD

    FirebaseProvider(
      credentials: Credentials.fromServiceAccount('service-account.json'),
    )
    
  3. Environment Variables - Set GOOGLE_APPLICATION_CREDENTIALS

    export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
    

Resources

Firebase Project

Represents a Firebase project that exists externally. This is a data source - it cannot be created, updated, or deleted through DRFT. Projects must be managed through the Firebase Console or Google Cloud Console.

FirebaseProject(
  id: 'my-project',
  projectId: 'my-project-id',  // Must match existing Firebase project
  displayName: 'My Firebase Project',
)

Properties:

  • id (required): Unique identifier for the resource in DRFT
  • projectId (required): The Firebase project ID (must be globally unique)
  • displayName (required): Display name for the project

Operations:

  • Read: Verify project exists and get current state
  • Create: Not supported (create via Firebase Console)
  • Update: Not supported (data source - read-only)
  • Delete: Not supported (delete via Firebase Console)

Data Source Behavior:

  • FirebaseProject extends ReadOnlyResource (read-only external resource)
  • It will never appear in create, update, or delete operations
  • It is read during planning and refresh to verify existence
  • Other resources (like FirebaseApp) can depend on it to get the projectId

Firebase App

Represents a Firebase app (iOS, Android, or Web) within a Firebase project. Supports full CRUD operations.

// iOS App
FirebaseApp(
  id: 'ios-app',
  projectId: 'my-project-id',
  platform: FirebaseAppPlatform.ios,
  displayName: 'My iOS App',
  bundleId: 'com.example.app',  // Required for iOS
)

// Android App
FirebaseApp(
  id: 'android-app',
  projectId: 'my-project-id',
  platform: FirebaseAppPlatform.android,
  displayName: 'My Android App',
  packageName: 'com.example.app',  // Required for Android
)

// Web App
FirebaseApp(
  id: 'web-app',
  projectId: 'my-project-id',
  platform: FirebaseAppPlatform.web,
  displayName: 'My Web App',
)

Properties:

  • id (required): Unique identifier for the resource in DRFT
  • projectId (required): The Firebase project ID this app belongs to
  • platform (required): FirebaseAppPlatform.ios, .android, or .web
  • displayName (required): Display name of the app
  • bundleId (optional): Bundle ID for iOS apps (required when platform is iOS)
  • packageName (optional): Package name for Android apps (required when platform is Android)

Operations:

  • Create: Creates new Firebase app for the specified platform
  • Read: Reads current app state from Firebase
  • Update: Updates app display name (other properties are immutable)
  • ⚠️ Delete: Placeholder (API support pending)

Immutable Properties: Once created, the following properties cannot be changed:

  • platform - Cannot change app platform
  • bundleId - Cannot change iOS bundle ID
  • packageName - Cannot change Android package name

Updatable Properties:

  • displayName - Can be updated using the updateApp method

Coming Soon

The following resources are planned for future releases:

  • Firebase Authentication - Configure authentication providers and settings
  • Firestore Database - Create and manage Firestore databases
  • Cloud Storage - Manage Cloud Storage buckets
  • Remote Config - Configure remote configuration parameters
  • App Check - Set up App Check providers

Complete Example

import 'package:drft/drft.dart';
import 'package:drft_firebase/drft_firebase.dart';

void main() async {
  final stack = DrftStack(
    name: 'flutter-app-backend',
    providers: [
      FirebaseProvider(
        // Uses Application Default Credentials if not provided
        // credentials: Credentials.fromServiceAccount('service-account.json'),
      ),
    ],
    resources: [
      // Firebase Project (must exist in Firebase Console)
      FirebaseProject(
        id: 'my-project',
        projectId: 'my-flutter-app',
        displayName: 'My Flutter App Backend',
      ),
      
      // iOS App
      FirebaseApp(
        id: 'ios-app',
        projectId: 'my-flutter-app',
        platform: FirebaseAppPlatform.ios,
        displayName: 'My iOS App',
        bundleId: 'com.example.app',
      ),
      
      // Android App
      FirebaseApp(
        id: 'android-app',
        projectId: 'my-flutter-app',
        platform: FirebaseAppPlatform.android,
        displayName: 'My Android App',
        packageName: 'com.example.app',
      ),
      
      // Web App
      FirebaseApp(
        id: 'web-app',
        projectId: 'my-flutter-app',
        platform: FirebaseAppPlatform.web,
        displayName: 'My Web App',
      ),
    ],
  );
  
  // Plan changes
  final plan = await stack.plan();
  print(plan.summary);
  
  // Apply changes
  final result = await stack.apply(plan);
  print(result.summary);
}

Usage Examples

Creating Firebase Apps

final stack = DrftStack(
  name: 'my-stack',
  providers: [FirebaseProvider()],
  resources: [
    FirebaseProject(
      id: 'project',
      projectId: 'my-project-id',
      displayName: 'My Project',
    ),
    FirebaseApp(
      id: 'ios-app',
      projectId: 'my-project-id',
      platform: FirebaseAppPlatform.ios,
      displayName: 'iOS App',
      bundleId: 'com.example.app',
    ),
  ],
);

// Plan and apply
final plan = await stack.plan();
await stack.apply(plan);

Updating App Display Name

// After initial creation, you can update the display name
final updatedApp = FirebaseApp(
  id: 'ios-app',
  projectId: 'my-project-id',
  platform: FirebaseAppPlatform.ios,
  displayName: 'Updated App Name',  // Changed display name
  bundleId: 'com.example.app',
);

final plan = await stack.plan();
await stack.apply(plan);

Reading Current State

// Refresh state from actual Firebase infrastructure
final currentState = await stack.refresh();

// Access app state
final appState = currentState.resources['ios-app'] as FirebaseAppState;
print('App ID: ${appState.appId}');
print('Display Name: ${appState.resource.displayName}');

Implementation Notes

Authentication

The Firebase provider uses the firebase_management package and supports:

  • Application Default Credentials (ADC) - Recommended for local development
  • Service Account JSON - For production and CI/CD
  • Environment Variables - Via GOOGLE_APPLICATION_CREDENTIALS

API Limitations

  • Project Creation/Deletion: Must be done through Firebase Console or Google Cloud Console
  • App Deletion: Currently not supported by the API (placeholder implementation)
  • Immutable Properties: Platform, bundleId, and packageName cannot be changed after creation
  • Rate Limits: Firebase Management API has rate limits that may affect operations

State Management

Firebase resources are tracked by their resource IDs in DRFT:

  • Projects: Tracked by projectId
  • Apps: Tracked by id with matching logic based on platform and bundleId/packageName/displayName

The provider automatically retrieves the Firebase-assigned appId after creation, which is stored in FirebaseAppState.

Resource Matching

When reading Firebase apps, the provider matches apps using:

  1. Platform match (iOS, Android, or Web)
  2. Bundle ID match (for iOS) or Package Name match (for Android)
  3. Display Name match (fallback)

Resources Roadmap

Phase 1 (Current)

  • Firebase Projects (read support)
  • Firebase Apps (iOS, Android, Web) - full CRUD operations
    • Create apps
    • Read apps
    • Update display name
    • ⚠️ Delete apps (API support pending)

Phase 2 (Planned)

  • 🎯 APNS Auth Keys (resource defined, provider methods pending)
  • 🎯 Android SHA Fingerprints (resource defined, provider methods pending)
  • 🎯 Firebase Authentication configuration
  • 🎯 Firestore Databases
  • 🎯 Cloud Storage Buckets

Phase 3 (Future)

  • 🎯 Remote Config
  • 🎯 App Check
  • 🎯 Cloud Functions configuration
  • 🎯 Cloud Messaging (FCM)
  • 🎯 Realtime Database
  • 🎯 Firebase Hosting
  • 🎯 Cloud Firestore Indexes