When you create an extension, you write its logic using Cloud Functions, in
much the same way as you would write a function that would only ever be used in
your own project. You declare your functions in the `extension.yaml` file, and
when users install your extension, these functions get deployed into their
project.

See the [Cloud Functions](https://firebase.google.com/docs/functions.md.txt) documentation for general information on using
Cloud Functions.

## 1st and 2nd generation Cloud Functions

Firebase supports both
[1st-generation and 2nd-generation Cloud Functions](https://firebase.google.com/docs/functions/version-comparison.md.txt). However, Firebase
Extensions currently have some restrictions on which generation of cloud
function you can use with certain trigger types. For this reason, many
extensions include a mix of 1st and 2nd generation functions.

Function generation support is noted for each trigger type, below.

## Special considerations

- Some function definitions require you to specify information that is also
  specified in the `extension.yaml` file. For example, Cloud Firestore has a
  `document()` method that specifies the document pattern to watch, and its
  corresponding declaration in `extension.yaml` has a `resource` field that
  specifies the same.

  In these situations, the configuration specified in the `extension.yaml`
  file is used and the configuration specified in the function definition is
  ignored.

  It is common practice to specify the configured value in the function
  definition regardless, for the sake of documentation. The examples on this
  page follow this pattern.
- The Cloud Functions 1st gen SDK has a `functions.config()` method and
  `functions:config:set` CLI command that you can use to work with
  parameterized values in 1st gen functions. This technique is deprecated in
  Cloud Functions and will *not work at all* in an extension. Instead, use
  the `functions.params` module (recommended) or `process.env`.

## Using TypeScript

Most of the documentation for developing your own extension describes workflows
using JavaScript for Cloud Functions for Firebase. However, you can instead write
your functions using TypeScript.

In fact, all the
[official Firebase extensions](https://github.com/firebase/extensions)
are written in TypeScript. You can review those extensions for some best
practices to use TypeScript for your extension.

**If you do write your extension's functions in TypeScript, you must do the
following before installing your extension:**

1. Compile your extension's functions source code to JavaScript.

   The [`firebase ext:dev:init`
   command](https://firebase.google.com/docs/extensions/publishers/get-started#setup)
   allows you to choose TypeScript for writing your functions. The command
   provides you with a complete, installable extension *as well as a build
   script that you can run with `npm run build`*.
2. In your `package.json` file, make sure to point the `main` field at the
   generated JavaScript.

3. If you're installing or uploading your extension from local source,
   compile your TypeScript files first.

## Supported function triggers

### HTTP triggers

An HTTP-triggered function is deployed to a public `https` endpoint and runs
when the endpoint is accessed.

See [Call functions via HTTP requests](https://firebase.google.com/docs/functions/1st-gen/http-events-1st.md.txt) in the Cloud Functions
documentation for information on writing HTTP-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { https } from "firebase-functions/v1";

export const yourFunctionName = https.onRequest(async (req, resp) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      runtime: nodejs16
      httpsTrigger: {}
  - name: anotherFunction
    type: ...
```

### Callable functions

Callable functions are similar to HTTP-triggered functions, but they implement a
protocol that makes them convenient to call from your client-side code.

See [Call functions from your app](https://firebase.google.com/docs/functions/1st-gen/callable-1st.md.txt) in the Cloud Functions documentation
for information on using callable functions.

#### Function definition (1st-gen only)

```javascript
import { https } from "firebase-functions/v1";

export const yourFunctionName = https.onCall(async (data, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      runtime: nodejs16
      httpsTrigger: {}
  - name: anotherFunction
    type: ...
```

### Scheduled function triggers

A scheduled function runs repeatedly based on a customizable schedule.

See [Schedule functions](https://firebase.google.com/docs/functions/1st-gen/schedule-functions-1st.md.txt) in the Cloud Functions documentation for
information on writing scheduled functions.

#### Function definition (1st-gen only)

```javascript
import { pubsub } from "firebase-functions/v1";

export const yourFunctionName = pubsub.schedule("every 6 hours").onRun((context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      scheduleTrigger:
        schedule: 'every 5 minutes'
  - name: anotherFunction
    type: ...
```

Here are the available subfields for `scheduleTrigger`:

| **Field** | **Description** |
|---|---|
| `schedule` *(required)* | The frequency at which you want the function to run. This field can accept strings that use either syntax (wrapping in *single-quotes* is required): - [unix-cron syntax](https://cloud.google.com/scheduler/docs/configuring/cron-job-schedules) (for example, `'5 11 * * *'`) - [App Engine syntax](https://cloud.google.com/appengine/docs/standard/nodejs/scheduling-jobs-with-cron-yaml#defining_the_cron_job_schedule) (for example, `'every 5 minutes'`) |
| `timeZone` *(optional)* | The time zone in which the schedule will run. - Use [standardardized time zone abbreviations.](https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations) - Defaults to `UTC` |

If you want users to be able to configure the schedule when they install your
extension, add a new parameter to your `extension.yaml` file and reference the
parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      scheduleTrigger:
        schedule: ${SCHEDULE_FREQUENCY}
  - name: anotherFunction
    type: ...

params:
  - param: SCHEDULE_FREQUENCY
    label: Schedule
    description: How often do you want to run yourFunctionName()?
    type: string
    default: 'every 5 minutes'  # Specifying a default is optional.
    required: true
```

> [!CAUTION]
> Cloud Scheduler allows 3 jobs at no cost per *billing account* . This is not at the project-level, but at the *billing account level* . So if you have multiple projects associated with the same billing account, you need to be aware of how many Cloud Scheduler jobs you may have. Learn more about [Cloud Scheduler pricing](https://cloud.google.com/scheduler#pricing).
>
> Each installed instance of a scheduled extension will have a single
> Cloud Scheduler job provisioned for the project. Paused jobs are counted
> as jobs.

### Task queue triggers

A task queue function is triggered either on your extension's [lifecycle
events](https://firebase.google.com/docs/extensions/publishers/lifecycle-events) or when manually added to your extension's task queue using the Admin
SDK's [`TaskQueue.enqueue()` method](https://firebase.google.com/docs/reference/admin/node/firebase-admin.functions.taskqueue.md.txt#taskqueueenqueue).

See [Handle your extension's lifecycle events](https://firebase.google.com/docs/extensions/publishers/lifecycle-events.md.txt) for information on writing
functions that handle lifecycle events.

See [Enqueue functions with Cloud Tasks](https://firebase.google.com/docs/functions/1st-gen/task-functions-1st.md.txt) in the Cloud Functions
documentation for information on writing task queue functions.

#### Function definition (1st-gen only)

```javascript
import { tasks } from "firebase-functions/v1";

export const yourFunctionName = tasks.taskQueue().onDispatch(async (data, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: myTaskFunction
    type: firebaseextensions.v1beta.function
    description: >-
      Perform a task when triggered by a lifecycle event
    properties:
      taskQueueTrigger: {}
```

Set the `taskQueueTrigger` property set to either `{}` or a map of options which
tune the rate limits and retry behavior of the task queue (see [Tuning the task
queue](https://firebase.google.com/docs/extensions/publishers/lifecycle-events#task-queue-properties)).

If you want to trigger your function on your extension's lifecycle events, add
`lifecycleEvents` records with the name of the function and an optional
processing message, which will be displayed in the Firebase console when
processing begins.

```yaml
lifecycleEvents:
  onInstall:
    function: myTaskFunction
    processingMessage: Resizing your existing images
  onUpdate:
    function: myOtherTaskFunction
    processingMessage: Setting up your extension
  onConfigure:
    function: myOtherTaskFunction
    processingMessage: Setting up your extension
```

> [!NOTE]
> **Note:** The message you specify here is automatically set as your extension's processing status in the Firebase console when triggering your function. To update or clear the processing status when your processing task finishes its work, call [`setProcessingState()`](https://firebase.google.com/docs/extensions/publishers/lifecycle-events.md.txt#set-processing-state).

### Analytics

An Analytics-triggered function runs when a specified Analytics event gets
logged.

See [Google Analytics triggers](https://firebase.google.com/docs/functions/1st-gen/analytics-events-1st) in the Cloud Functions documentation for
information on writing Analytics-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { analytics } from "firebase-functions/v1";

export const yourFunctionName = analytics.event("event_name").onLog((event, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/google.firebase.analytics/eventTypes/event.log
        resource: projects/${PROJECT_ID}/events/ga_event
  - name: anotherFunction
    type: ...
```

If you want users to be able to configure the Analytics event to listen for
when they install your extension, add a new parameter to your `extension.yaml`
file and reference the parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/google.firebase.analytics/eventTypes/event.log
        resource: projects/${PROJECT_ID}/events/${EVENT_NAME}
  - name: anotherFunction
    type: ...

params:
  - param: EVENT_NAME
    label: Analytics event
    description: What event do you want to respond to?
    type: string
    default: ga_event  # Specifying a default is optional.
    required: true
```

### Authentication

An authentication-triggered function runs when a user is created or deleted.

See [Firebase Authentication triggers](https://firebase.google.com/docs/functions/1st-gen/auth-events-1st) in the Cloud Functions
documentation for information on writing auth-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { auth } from "firebase-functions/v1";

export const yourFunctionName = auth.user().onCreate((user, context) => {
  // ...
});

export const yourFunctionName2 = auth.user().onDelete((user, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/firebase.auth/eventTypes/user.create
        resource: projects/${PROJECT_ID}
  - name: anotherFunction
    type: ...
```

The following table shows how to specify each of the supported Authentication event
types:

| Cloud Functions event trigger | `eventType` | Description |
|---|---|---|
| `onCreate()` | `providers/firebase.auth/eventTypes/user.create` | New user created |
| `onDelete()` | `providers/firebase.auth/eventTypes/user.delete` | User deleted |

### Cloud Firestore

A Cloud Firestore-triggered function runs when a document is created, updated,
or deleted.

See [Cloud Firestore triggers](https://firebase.google.com/docs/functions/1st-gen/firestore-events-1st.md.txt) in the Cloud Functions documentation for
information on writing Firestore-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { firestore } from "firebase-functions/v1";

export const yourFunctionName = firestore.document("collection/{doc_id}")
  .onCreate((snapshot, context) => {
    // ...
  });

export const yourFunctionName2 = firestore.document("collection/{doc_id}")
  .onUpdate((change, context) => {
    // ...
  });

export const yourFunctionName3 = firestore.document("collection/{doc_id}")
  .onDelete((snapshot, context) => {
    // ...
  });

export const yourFunctionName4 = firestore.document("collection/{doc_id}")
  .onWrite((change, context) => {
    // onWrite triggers on creation, update, and deletion.
    // ...
  });
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/collection/{documentID}
  - name: anotherFunction
    type: ...
```

The following table shows how to specify each of the supported Cloud Firestore
event types:

| Cloud Functions event trigger | `eventType` | Description |
|---|---|---|
| `onCreate()` | `providers/cloud.firestore/eventTypes/document.create` | New document created |
| `onDelete()` | `providers/cloud.firestore/eventTypes/document.delete` | Document deleted |
| `onUpdate()` | `providers/cloud.firestore/eventTypes/document.update` | Document updated |
| `onWrite()` | `providers/cloud.firestore/eventTypes/document.write` | Document created, deleted, or updated |

If you want users to be able to configure the document path when they install
your extension, add a new parameter to your `extension.yaml` file and reference
the parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/cloud.firestore/eventTypes/document.write
        resource: projects/${PROJECT_ID}/databases/(default)/documents/${YOUR_DOCUMENT_PATH}
  - name: anotherFunction
    type: ...

params:
  - param: YOUR_DOCUMENT_PATH
    label: Cloud Firestore path
    description: Where do you want to watch for changes?
    type: string
    default: path/to/{documentID}  # Specifying a default is optional.
    required: true
```

### Pub/Sub

A Pub/Sub-triggered function runs when a message is published to a specific
topic.

See [Pub/Sub triggers](https://firebase.google.com/docs/functions/1st-gen/pubsub-events-1st.md.txt) in the Cloud Functions documentation for
information on writing Pub/Sub-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { pubsub } from "firebase-functions/v1";

export const yourFunctionName = pubsub.topic("topic_name").onPublish((message, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.pubsub.topic.publish
        resource: projects/${PROJECT_ID}/topics/topic-name
  - name: anotherFunction
    type: ...
```

If you want users to be able to configure the Pub/Sub topic when
they install your extension, add a new parameter to your `extension.yaml` file
and reference the parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.pubsub.topic.publish
        resource: projects/${PROJECT_ID}/topics/${PUBSUB_TOPIC}
  - name: anotherFunction
    type: ...

params:
  - param: PUBSUB_TOPIC
    label: Pub/Sub topic
    description: Which Pub/Sub topic do you want to watch for messages?
    type: string
    default: topic-name  # Specifying a default is optional.
    required: true
```

### Realtime Database

A Realtime Database-triggered function runs when a path that matches a specified
pattern is created, updated, or deleted.

See [Realtime Database triggers](https://firebase.google.com/docs/functions/1st-gen/database-events-1st.md.txt) in the Cloud Functions documentation
for information on writing RTDB-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { database } from "firebase-functions/v1";

export const yourFunctionName = database.ref("path/to/{item}")
  .onCreate((snapshot, context) => {
    // ...
  });

export const yourFunctionName2 = database.ref("path/to/{item}")
  .onUpdate((change, context) => {
    // ...
  });

export const yourFunctionName3 = database.ref("path/to/{item}")
  .onDelete((snapshot, context) => {
    // ...
  });

export const yourFunctionName4 = database.ref("path/to/{item}")
  .onWrite((change, context) => {
    // onWrite triggers on creation, update, and deletion.
    // ...
  });
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/google.firebase.database/eventTypes/ref.create
        # DATABASE_INSTANCE (project's default instance) is an auto-populated
        # parameter value. You can also specify an instance.
        resource: projects/_/instances/${DATABASE_INSTANCE}/refs/path/to/{itemId}
  - name: anotherFunction
    type: ...
```

The following table shows how to specify each of the supported Cloud Firestore
event types:

| Cloud Functions event trigger | `eventType` | Description |
|---|---|---|
| `onCreate()` | `providers/google.firebase.database/eventTypes/ref.create` | Data created |
| `onDelete()` | `providers/google.firebase.database/eventTypes/ref.delete` | Data deleted |
| `onUpdate()` | `providers/google.firebase.database/eventTypes/ref.update` | Data updated |
| `onWrite()` | `providers/google.firebase.database/eventTypes/ref.write` | Data created, deleted, or updated |

If you want users to be able to configure the path to watch when they install
your extension, add a new parameter to your `extension.yaml` file and reference
the parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: providers/google.firebase.database/eventTypes/ref.create
        # DATABASE_INSTANCE (project's default instance) is an auto-populated
        # parameter value. You can also specify an instance.
        resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${DB_PATH}
  - name: anotherFunction
    type: ...

params:
  - param: DB_PATH
    label: Realtime Database path
    description: Where do you want to watch for changes?
    type: string
    default: path/to/{itemId}  # Specifying a default is optional.
    required: true
```

### Remote Config

A Remote Config-triggered function runs when a project's parameter template is
updated.

See [Remote Config triggers](https://firebase.google.com/docs/functions/1st-gen/rc-events-1st.md.txt) in the Cloud Functions documentation for
information on writing Remote Config-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { remoteConfig } from "firebase-functions/v1";

export const yourFunctionName = remoteConfig.onUpdate((version, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.firebase.remoteconfig.update
        resource: projects/${PROJECT_ID}
  - name: anotherFunction
    type: ...
```

### Cloud Storage

A Cloud Storage-triggered function runs when an object is created, archived, or
deleted, or when its metadata changes.

See [Cloud Storage triggers](https://firebase.google.com/docs/functions/1st-gen/gcp-storage-events-1st.md.txt) in the Cloud Functions documentation for
information on writing Storage-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { storage } from "firebase-functions/v1";

export const yourFunctionName = storage.object().onFinalize((object, context) => {
  // ...
});

export const yourFunctionName2 = storage.object().onMetadataUpdate((object, context) => {
  // ...
});

export const yourFunctionName3 = storage.object().onArchive((object, context) => {
  // ...
});

export const yourFunctionName4 = storage.object().onDelete((object, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.storage.object.finalize
        # STORAGE_BUCKET (project's default bucket) is an auto-populated
        # parameter. You can also specify a bucket.
        resource: projects/_/buckets/${STORAGE_BUCKET}
  - name: anotherFunction
    type: ...
```

The following table shows how to specify each of the supported Cloud Storage
event types:

| Cloud Functions event trigger | `eventType` | Description |
|---|---|---|
| `onFinalize()` | `google.storage.object.finalize` | Object created |
| `onMetadataUpdate()` | `google.storage.object.metadataUpdate` | Object metadata updated |
| `onArchive()` | `google.storage.object.archive` | Object was archived |
| `onDelete()` | `google.storage.object.delete` | Object deleted |

If you want users to be able to configure the storage bucket when they install
your extension, add a new parameter to your `extension.yaml` file and reference
the parameter in your function's `resource` declaration:

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.storage.object.finalize
        resource: projects/_/buckets/${YOUR_BUCKET}
  - name: anotherFunction
    type: ...

params:
  - param: YOUR_BUCKET
    label: Cloud Storage bucket
    description: Which bucket do you want to watch for changes?
    type: selectResource
    resourceType: storage.googleapis.com/Bucket
    default: ${STORAGE_BUCKET}  # Specifying a default is optional.
    required: true
```

### Test Lab

A Test Lab-triggered function runs when a test matrix finishes its tests.

See [Firebase Test Lab triggers](https://firebase.google.com/docs/functions/1st-gen/test-lab-events-1st.md.txt) in the Cloud Functions documentation
for information on writing Test Lab-triggered functions.

#### Function definition (1st-gen only)

```javascript
import { testLab } from "firebase-functions/v1";

export const yourFunctionName = testLab.testMatrix().onComplete((matrix, context) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourFunctionName
    type: firebaseextensions.v1beta.function
    properties:
      eventTrigger:
        eventType: google.testing.testMatrix.complete
        resource: projects/${PROJECT_ID}/testMatrices/{matrixId}
  - name: anotherFunction
    type: ...
```

### Crashlytics alert triggers

A Crashlytics-triggered function runs when Crashlytics publishes an
alert.

See [Firebase Alerts triggers](https://firebase.google.com/docs/functions/alert-events.md.txt) in the Cloud Functions documentation for
information on writing alert-triggered functions.

#### Function definition (2nd-gen only)

```javascript
import {
  onNewFatalIssuePublished,
  onNewNonfatalIssuePublished,
  onNewAnrIssuePublished,
  onRegressionAlertPublished,
  onVelocityAlertPublished,
  onStabilityDigestPublished,
} from "firebase-functions/v2/alerts/crashlytics";

export const yourFunctionName = onNewFatalIssuePublished((event) => {
  // ...
});

export const yourFunctionName2 = onNewNonfatalIssuePublished((event) => {
  // ...
});

export const yourFunctionName3 = onNewAnrIssuePublished((event) => {
  // ...
});

export const yourFunctionName4 = onRegressionAlertPublished((event) => {
  // ...
});

export const yourFunctionName5 = onVelocityAlertPublished((event) => {
  // ...
});

export const yourFunctionName6 = onStabilityDigestPublished((event) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourfunctionname
    type: firebaseextensions.v1beta.v2function
    properties:
      buildConfig:
        runtime: nodejs16
      serviceConfig:
        availableMemory: 512M
      eventTrigger:
        eventType: google.firebase.firebasealerts.alerts.v1.published
        triggerRegion: global
        eventFilters:
          - attribute: alerttype
            value: crashlytics.newFatalIssue
  - name: anotherFunction
    type: ...
```

You can use the following values for `alerttype`

- `crashlytics.newFatalIssue`
- `crashlytics.newNonfatalIssue`
- `crashlytics.regression`
- `crashlytics.stabilityDigest`
- `crashlytics.velocity`
- `crashlytics.newAnrIssue`

### Performance Monitoring alert triggers

A Performance Monitoring-triggered function runs when Performance Monitoring publishes an alert.

See [Firebase Alerts triggers](https://firebase.google.com/docs/functions/alert-events.md.txt) in the Cloud Functions documentation for
information on writing alert-triggered functions.

#### Function definition (2nd-gen only)

```javascript
import { onThresholdAlertPublished } from "firebase-functions/v2/alerts/performance";

export const yourFunctionName = onThresholdAlertPublished((event) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourfunctionname
    type: firebaseextensions.v1beta.v2function
    properties:
      buildConfig:
        runtime: nodejs16
      serviceConfig:
        availableMemory: 512M
      eventTrigger:
        eventType: google.firebase.firebasealerts.alerts.v1.published
        triggerRegion: global
        eventFilters:
          - attribute: alerttype
            value: performance.threshold
  - name: anotherFunction
    type: ...
```

### App Distribution alert triggers

A App Distribution-triggered function runs when App Distribution
publishes an alert.

See [Firebase Alerts triggers](https://firebase.google.com/docs/functions/alert-events.md.txt) in the Cloud Functions documentation for
information on writing alert-triggered functions.

#### Function definition (2nd-gen only)

```javascript
import {
  onNewTesterIosDevicePublished,
  onInAppFeedbackPublished
} from "firebase-functions/v2/alerts/appDistribution";

export const yourFunctionName = onNewTesterIosDevicePublished((event) => {
  // ...
});

export const yourFunctionName2 = onInAppFeedbackPublished((event) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourfunctionname
    type: firebaseextensions.v1beta.v2function
    properties:
      buildConfig:
        runtime: nodejs16
      serviceConfig:
        availableMemory: 512M
      eventTrigger:
        eventType: google.firebase.firebasealerts.alerts.v1.published
        triggerRegion: global
        eventFilters:
          - attribute: alerttype
            value: appDistribution.inAppFeedback
  - name: anotherFunction
    type: ...
```

You can use the following values for `alerttype`

- `appDistribution.newTesterIosDevice`
- `appDistribution.inAppFeedback`

### Custom event triggers (Eventarc)

An Eventarc-triggered function runs when a specific event type is published to a
specific channel.

See [Create and handle custom event triggers](https://firebase.google.com/docs/functions/custom-events.md.txt) in the Cloud Functions
documentation for information on writing Eventarc-triggered functions.

You can also *publish* events from your extensions to give users a way to insert
custom logic into your extension. See [Use developer-provided custom logic in an
extension](https://firebase.google.com/docs/extensions/publishers/user-hooks).

#### Function definition (2nd-gen only)

```javascript
import { onCustomEventPublished } from "firebase-functions/v2/eventarc";

export const yourFunctionName = onCustomEventPublished((event) => {
  // ...
});
```

#### Resource declaration (extension.yaml)

```yaml
resources:
  - name: yourfunctionname
    type: firebaseextensions.v1beta.v2function
    properties:
      # LOCATION is a user-configured parameter value specified by the user
      # during installation.
      location: ${param:LOCATION}
      buildConfig:
        runtime: nodejs16
      serviceConfig:
        availableMemory: 512M
        timeoutSeconds: 60
      eventTrigger:
        eventType: firebase.extensions.storage-resize-images.v1.complete
        channel: projects/${param:PROJECT_ID}/locations/us-central1/channels/firebase
  - name: anotherFunction
    type: ...
```

The channel must already exist when your extension is installed. For example, if
you depend on custom events from another extension that creates the channel,
instruct your users to install that extension first.

The above example would create a custom event trigger for the "default" Firebase
channel in `us-central1` region. You can make the channel name and region
customizable by using parameters. For example:

```yaml

params:
  - param: EVENTARC_CHANNEL_NAME
    label: Eventarc channel name
    description: What is the name of the Eventarc channel.
    default: firebase
    type: string
    required: true

resources:
  - name: yourfunctionname
    type: firebaseextensions.v1beta.v2function
    properties:
      location: ${param:LOCATION}
      eventTrigger:
        eventType: firebase.extensions.storage-resize-images.v1.complete
        channel: projects/${param:PROJECT_ID}/locations/${param:LOCATION}/channels/${param:EVENTARC_CHANNEL_NAME}
```