11# Firebase Functions for Dart
22
33[ ![ Tests] ( https://github.com/invertase/firebase_functions/actions/workflows/test.yml/badge.svg )] ( https://github.com/invertase/firebase_functions/actions/workflows/test.yml )
4- [ ![ PR Checks] ( https://github.com/invertase/firebase_functions/actions/workflows/pr-checks .yml/badge.svg )] ( https://github.com/invertase/firebase_functions/actions/workflows/pr-checks.yml )
4+ [ ![ PR Checks] ( https://github.com/invertase/firebase_functions/actions/workflows/test .yml/badge.svg )] ( https://github.com/invertase/firebase_functions/actions/workflows/pr-checks.yml )
55
66Write Firebase Cloud Functions in Dart with full type safety and performance.
77
@@ -16,10 +16,29 @@ This package provides a complete Dart implementation of Firebase Cloud Functions
1616| ** Firestore** | ✅ Complete | ` onDocumentCreated ` , ` onDocumentUpdated ` , ` onDocumentDeleted ` , ` onDocumentWritten ` , ` onDocumentCreatedWithAuthContext ` , ` onDocumentUpdatedWithAuthContext ` , ` onDocumentDeletedWithAuthContext ` , ` onDocumentWrittenWithAuthContext ` |
1717| ** Realtime Database** | ✅ Complete | ` onValueCreated ` , ` onValueUpdated ` , ` onValueDeleted ` , ` onValueWritten ` |
1818| ** Storage** | ✅ Complete | ` onObjectFinalized ` , ` onObjectArchived ` , ` onObjectDeleted ` , ` onObjectMetadataUpdated ` |
19- | ** Firebase Alerts** | ✅ Complete | Crashlytics, Billing, Performance alerts |
19+ | ** Scheduler** | ✅ Complete | ` onSchedule ` |
20+ | ** Firebase Alerts** | ✅ Complete | ` onInAppFeedbackPublished ` , ` onNewAnrIssuePublished ` , ` onNewFatalIssuePublished ` , ` onNewNonfatalIssuePublished ` , ` onNewTesterIosDevicePublished ` , ` onPlanAutomatedUpdatePublished ` , ` onPlanUpdatePublished ` , ` onRegressionAlertPublished ` , ` onStabilityDigestPublished ` , ` onThresholdAlertPublished ` , ` onVelocityAlertPublished ` |
2021| ** Eventarc** | ✅ Complete | ` onCustomEventPublished ` |
2122| ** Identity Platform** | ✅ Complete | ` beforeUserCreated ` , ` beforeUserSignedIn ` (+ ` beforeEmailSent ` , ` beforeSmsSent ` * ) |
2223
24+ ## Table of Contents
25+
26+ - [ Features] ( #features )
27+ - [ Prerequisites] ( #prerequisites )
28+ - [ Installation] ( #installation )
29+ - [ Quick Start] ( #quick-start )
30+ - [ HTTPS Functions] ( #https-functions )
31+ - [ Pub/Sub Triggers] ( #pubsub-triggers )
32+ - [ Firestore Triggers] ( #firestore-triggers )
33+ - [ Realtime Database Triggers] ( #realtime-database-triggers )
34+ - [ Storage Triggers] ( #storage-triggers )
35+ - [ Scheduler Triggers] ( #scheduler-triggers )
36+ - [ Firebase Alerts] ( #firebase-alerts )
37+ - [ Identity Platform (Auth Blocking)] ( #identity-platform-auth-blocking )
38+ - [ Parameters & Configuration] ( #parameters--configuration )
39+ - [ Project Configuration] ( #project-configuration )
40+ - [ Development] ( #development )
41+
2342## Features
2443
2544- ** Type-safe** : Leverage Dart's strong type system with typed callable functions and CloudEvents
@@ -265,6 +284,26 @@ firebase.firestore.onDocumentWrittenWithAuthContext(
265284
266285## Realtime Database Triggers
267286
287+ Respond to changes in Firebase Realtime Database. The ` ref ` parameter supports path wildcards (e.g., ` {messageId} ` ) which are extracted into ` event.params ` .
288+
289+ | Function | Triggers when | Event data |
290+ | ----------| ---------------| ------------|
291+ | ` onValueCreated ` | Data is created | ` DataSnapshot? ` |
292+ | ` onValueUpdated ` | Data is updated | ` Change<DataSnapshot>? ` (before/after) |
293+ | ` onValueDeleted ` | Data is deleted | ` DataSnapshot? ` (deleted data) |
294+ | ` onValueWritten ` | Any write (create/update/delete) | ` Change<DataSnapshot>? ` (before/after) |
295+
296+ ### DataSnapshot API
297+
298+ The ` DataSnapshot ` class provides methods to inspect the data:
299+
300+ - ` val() ` — Returns the snapshot contents (Map, List, String, num, bool, or null)
301+ - ` exists() ` — Returns ` true ` if the snapshot contains data
302+ - ` child(path) ` — Gets a child snapshot at the given path
303+ - ` hasChild(path) ` / ` hasChildren() ` — Check for child data
304+ - ` numChildren() ` — Number of child properties
305+ - ` key ` — Last segment of the reference path
306+
268307``` dart
269308// Value created
270309firebase.database.onValueCreated(
@@ -277,7 +316,7 @@ firebase.database.onValueCreated(
277316 },
278317);
279318
280- // Value updated
319+ // Value updated — access before/after states
281320firebase.database.onValueUpdated(
282321 ref: 'messages/{messageId}',
283322 (event) async {
@@ -297,7 +336,7 @@ firebase.database.onValueDeleted(
297336 },
298337);
299338
300- // All write operations
339+ // All write operations — determine operation type from before/after
301340firebase.database.onValueWritten(
302341 ref: 'users/{userId}/status',
303342 (event) async {
@@ -310,8 +349,45 @@ firebase.database.onValueWritten(
310349);
311350```
312351
352+ ### Database Instance Targeting
353+
354+ Use ` ReferenceOptions ` to target a specific database instance:
355+
356+ ``` dart
357+ firebase.database.onValueCreated(
358+ ref: 'messages/{messageId}',
359+ options: const ReferenceOptions(instance: 'my-project-default-rtdb'),
360+ (event) async {
361+ print('Instance: ${event.instance}');
362+ },
363+ );
364+ ```
365+
313366## Storage Triggers
314367
368+ Respond to changes in Cloud Storage objects. The ` bucket ` parameter specifies which storage bucket to watch.
369+
370+ | Function | Triggers when |
371+ | ----------| ---------------|
372+ | ` onObjectFinalized ` | Object is created or overwritten |
373+ | ` onObjectDeleted ` | Object is permanently deleted |
374+ | ` onObjectArchived ` | Object is archived (versioned buckets) |
375+ | ` onObjectMetadataUpdated ` | Object metadata is updated |
376+
377+ ### StorageObjectData Properties
378+
379+ The event data provides full object metadata:
380+
381+ - ` name ` — Object path within the bucket
382+ - ` bucket ` — Bucket name
383+ - ` contentType ` — MIME type
384+ - ` size ` — Content length in bytes
385+ - ` storageClass ` — Storage class (STANDARD, NEARLINE, COLDLINE, etc.)
386+ - ` metadata ` — User-provided key-value metadata
387+ - ` timeCreated ` / ` updated ` / ` timeDeleted ` — Timestamps
388+ - ` md5Hash ` / ` crc32c ` — Checksums
389+ - ` generation ` / ` metageneration ` — Versioning info
390+
315391``` dart
316392// Object finalized (created or overwritten)
317393firebase.storage.onObjectFinalized(
@@ -324,7 +400,7 @@ firebase.storage.onObjectFinalized(
324400 },
325401);
326402
327- // Object archived
403+ // Object archived (versioned buckets only)
328404firebase.storage.onObjectArchived(
329405 bucket: 'my-bucket',
330406 (event) async {
@@ -354,6 +430,72 @@ firebase.storage.onObjectMetadataUpdated(
354430);
355431```
356432
433+ ## Scheduler Triggers
434+
435+ Run functions on a recurring schedule using Cloud Scheduler. The ` schedule ` parameter accepts standard Unix crontab expressions.
436+
437+ ### Cron Syntax
438+
439+ ```
440+ ┌───────────── minute (0-59)
441+ │ ┌───────────── hour (0-23)
442+ │ │ ┌───────────── day of month (1-31)
443+ │ │ │ ┌───────────── month (1-12)
444+ │ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
445+ │ │ │ │ │
446+ * * * * *
447+ ```
448+
449+ Common examples: ` 0 0 * * * ` (daily midnight), ` */5 * * * * ` (every 5 min), ` 0 9 * * 1-5 ` (weekdays 9 AM).
450+
451+ ### ScheduledEvent Properties
452+
453+ - ` jobName ` — Cloud Scheduler job name (null if manually invoked)
454+ - ` scheduleTime ` — Scheduled execution time (RFC 3339 string)
455+ - ` scheduleDateTime ` — Parsed ` DateTime ` convenience getter
456+
457+ ``` dart
458+ // Basic schedule — runs every day at midnight (UTC)
459+ firebase.scheduler.onSchedule(
460+ schedule: '0 0 * * *',
461+ (event) async {
462+ print('Job: ${event.jobName}');
463+ print('Schedule time: ${event.scheduleTime}');
464+ },
465+ );
466+ ```
467+
468+ ### Timezone and Retry Configuration
469+
470+ Use ` ScheduleOptions ` to set a timezone and configure retry behavior for failed invocations:
471+
472+ ``` dart
473+ firebase.scheduler.onSchedule(
474+ schedule: '0 9 * * 1-5',
475+ options: const ScheduleOptions(
476+ timeZone: TimeZone('America/New_York'),
477+ retryConfig: RetryConfig(
478+ retryCount: RetryCount(3),
479+ maxRetrySeconds: MaxRetrySeconds(60),
480+ minBackoffSeconds: MinBackoffSeconds(5),
481+ maxBackoffSeconds: MaxBackoffSeconds(30),
482+ ),
483+ memory: Memory(MemoryOption.mb256),
484+ ),
485+ (event) async {
486+ print('Executed at: ${event.scheduleDateTime}');
487+ },
488+ );
489+ ```
490+
491+ | RetryConfig field | Description |
492+ | ---| ---|
493+ | ` retryCount ` | Number of retry attempts |
494+ | ` maxRetrySeconds ` | Maximum total time for retries |
495+ | ` minBackoffSeconds ` | Minimum wait before retry (0-3600) |
496+ | ` maxBackoffSeconds ` | Maximum wait before retry (0-3600) |
497+ | ` maxDoublings ` | Times to double backoff before going linear |
498+
357499## Firebase Alerts
358500
359501``` dart
@@ -366,6 +508,17 @@ firebase.alerts.crashlytics.onNewFatalIssuePublished(
366508 },
367509);
368510
511+ // Crashlytics velocity alerts
512+ firebase.alerts.crashlytics.onVelocityAlertPublished(
513+ (event) async {
514+ final payload = event.data?.payload;
515+ print('Velocity alert: ${payload?.issue.title}');
516+ print('Crash count: ${payload?.crashCount}');
517+ print('Percentage: ${payload?.crashPercentage}%');
518+ print('First version: ${payload?.firstVersion}');
519+ },
520+ );
521+
369522// Billing plan updates
370523firebase.alerts.billing.onPlanUpdatePublished(
371524 (event) async {
@@ -375,6 +528,16 @@ firebase.alerts.billing.onPlanUpdatePublished(
375528 },
376529);
377530
531+ // Billing automated plan updates
532+ firebase.alerts.billing.onPlanAutomatedUpdatePublished(
533+ (event) async {
534+ final payload = event.data?.payload;
535+ print('Automated plan update:');
536+ print(' Plan: ${payload?.billingPlan}');
537+ print(' Type: ${payload?.notificationType}');
538+ },
539+ );
540+
378541// Performance threshold alerts
379542firebase.alerts.performance.onThresholdAlertPublished(
380543 options: const AlertOptions(appId: '1:123456789:ios:abcdef'),
@@ -385,6 +548,18 @@ firebase.alerts.performance.onThresholdAlertPublished(
385548 print('Actual: ${payload?.violationValue}');
386549 },
387550);
551+
552+ // App Distribution in-app feedback
553+ firebase.alerts.appDistribution.onInAppFeedbackPublished(
554+ (event) async {
555+ final payload = event.data?.payload;
556+ print('In-app feedback:');
557+ print(' Tester: ${payload?.testerEmail}');
558+ print(' App version: ${payload?.appVersion}');
559+ print(' Text: ${payload?.text}');
560+ print(' Console: ${payload?.feedbackConsoleUri}');
561+ },
562+ );
388563```
389564
390565## Eventarc
0 commit comments