From 138023f98c9c6d769cb3329f5e12b7ecdc68a1ec Mon Sep 17 00:00:00 2001 From: Tyler Stark Date: Sat, 30 Apr 2022 13:54:51 -0500 Subject: [PATCH 1/2] Updates to exported CloudEvent Types. This commit makes several updates to the exported CloudEvent types. * Billing types include a notificationType * [Link](https://github.com/googleapis/google-cloudevents/blob/main/proto/google/events/firebase/firebasealerts/v1/cloud_event_payload.proto#L132-L133) * Crashlytics have more documentation on fields * Storage has an exported `StorageEvent` which includes the bucket. * Storage function api references `StorageEvent` to better match to expected output. --- src/v2/providers/alerts/alerts.ts | 8 ++++ src/v2/providers/alerts/appDistribution.ts | 2 + src/v2/providers/alerts/billing.ts | 8 ++++ src/v2/providers/alerts/crashlytics.ts | 36 +++++++++++++++++- src/v2/providers/storage.ts | 44 ++++++++++++---------- 5 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/v2/providers/alerts/alerts.ts b/src/v2/providers/alerts/alerts.ts index 173267422..44edd4e55 100644 --- a/src/v2/providers/alerts/alerts.ts +++ b/src/v2/providers/alerts/alerts.ts @@ -6,13 +6,21 @@ import * as options from '../../options'; * The CloudEvent data emitted by Firebase Alerts. */ export interface FirebaseAlertData { + /** Time that the event has created. */ createTime: string; + /** Time that the event has ended. Optional, only present for ongoing alerts. */ endTime: string; + /** Payload of the event, which includes the details of the specific alert. */ payload: T; } interface WithAlertTypeAndApp { + /** The type of the alerts that got triggered. */ alertType: string; + /** + * The Firebase App ID that’s associated with the alert. This is optional, + * and only present when the alert is targeting at a specific Firebase App. + */ appId?: string; } /** diff --git a/src/v2/providers/alerts/appDistribution.ts b/src/v2/providers/alerts/appDistribution.ts index ce5512dd4..94bd81ab8 100644 --- a/src/v2/providers/alerts/appDistribution.ts +++ b/src/v2/providers/alerts/appDistribution.ts @@ -15,7 +15,9 @@ export interface NewTesterDevicePayload { } interface WithAlertTypeAndApp { + /** The type of the alerts that got triggered. */ alertType: string; + /** The Firebase App ID that’s associated with the alert. */ appId: string; } /** diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index 8ba9b06c9..b9aaffc09 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -8,8 +8,12 @@ import * as options from '../../options'; */ export interface PlanUpdatePayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.BillingPlanUpdatePayload'; + /** A Firebase billing plan. */ billingPlan: string; + /** The email address of the person that triggered billing plan change */ principalEmail: string; + /** The type of the notification, e.g. upgrade, downgrade */ + notificationType: string; } /** @@ -18,10 +22,14 @@ export interface PlanUpdatePayload { */ export interface PlanAutomatedUpdatePayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.BillingPlanAutomatedUpdatePayload'; + /** A Firebase billing plan. */ billingPlan: string; + /** The type of the notification, e.g. upgrade, downgrade */ + notificationType: string; } interface WithAlertType { + /** The type of the alerts that got triggered. */ alertType: string; } /** diff --git a/src/v2/providers/alerts/crashlytics.ts b/src/v2/providers/alerts/crashlytics.ts index 4e2b4b121..19a57eb29 100644 --- a/src/v2/providers/alerts/crashlytics.ts +++ b/src/v2/providers/alerts/crashlytics.ts @@ -16,6 +16,7 @@ interface Issue { */ export interface NewFatalIssuePayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsNewFatalIssuePayload'; + /** Basic information of the Crashlytics issue */ issue: Issue; } @@ -25,6 +26,7 @@ export interface NewFatalIssuePayload { */ export interface NewNonfatalIssuePayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsNewNonfatalIssuePayload'; + /** Basic information of the Crashlytics issue */ issue: Issue; } @@ -34,16 +36,26 @@ export interface NewNonfatalIssuePayload { */ export interface RegressionAlertPayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsRegressionAlertPayload'; + /** The type of the Crashlytics issue, e.g. new fatal, new nonfatal, ANR */ type: string; + /** Basic information of the Crashlytics issue */ issue: Issue; + /** + * The time that the Crashlytics issues was most recently resolved before it + * began to reoccur. + */ resolveTime: string; } /** Generic crashlytics trending issue interface */ interface TrendingIssueDetails { + /** The type of the Crashlytics issue, e.g. new fatal, new nonfatal, ANR */ type: string; + /** Basic information of the Crashlytics issue */ issue: Issue; + /** The number of crashes that occurred with the issue */ eventCount: number; + /** The number of distinct users that were affected by the issue */ userCount: number; } @@ -53,8 +65,13 @@ interface TrendingIssueDetails { */ export interface StabilityDigestPayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsStabilityDigestPayload'; + /** + * The date that the digest gets created. Issues in the digest should have the + * same date as the digest date + */ digestDate: string; - trendingIssues: TrendingIssueDetails[]; + /** A stability digest containing several trending Crashlytics issues */ + trendingIssues: TrendingIssueDetails[]; } /** @@ -63,10 +80,24 @@ export interface StabilityDigestPayload { */ export interface VelocityAlertPayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsVelocityAlertPayload'; + /** Basic information of the Crashlytics issue */ issue: Issue; + /** The time that the Crashlytics issue gets created */ createTime: string; + /** + * The number of user sessions for the given app version that had this + * specific crash issue in the time period used to trigger the velocity alert. + */ crashCount: number; + /** + * The percentage of user sessions for the given app version that had this + * specific crash issue in the time period used to trigger the velocity alert. + */ crashPercentage: number; + /** + * The first app version where this issue was seen, and not necessarily the + * version that has triggered the alert. + */ firstVersion: string; } @@ -76,11 +107,14 @@ export interface VelocityAlertPayload { */ export interface NewAnrIssuePayload { ['@type']: 'type.googleapis.com/google.events.firebase.firebasealerts.v1.CrashlyticsNewAnrIssuePayload'; + /** Basic information of the Crashlytics issue */ issue: Issue; } interface WithAlertTypeAndApp { + /** The type of the alerts that got triggered. */ alertType: string; + /** The Firebase App ID that’s associated with the alert. */ appId: string; } /** diff --git a/src/v2/providers/storage.ts b/src/v2/providers/storage.ts index f4ce5b004..0e39cf572 100644 --- a/src/v2/providers/storage.ts +++ b/src/v2/providers/storage.ts @@ -174,6 +174,12 @@ export interface CustomerEncryption { keySha256?: string; } +interface WithBucket { + bucket: string; +} + +export type StorageEvent = CloudEvent; + /** @internal */ export const archivedEvent = 'google.cloud.storage.object.v1.archived'; /** @internal */ @@ -191,17 +197,17 @@ export interface StorageOptions extends options.EventHandlerOptions { /** Handle a storage object archived */ export function onObjectArchived( - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectArchived( bucket: string, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectArchived( opts: StorageOptions, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectArchived( @@ -209,49 +215,49 @@ export function onObjectArchived( | string | StorageOptions | ((event: CloudEvent) => any | Promise), - handler?: (event: CloudEvent) => any | Promise + handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(archivedEvent, buketOrOptsOrHandler, handler); } /** Handle a storage object finalized */ export function onObjectFinalized( - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectFinalized( bucket: string, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectFinalized( opts: StorageOptions, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectFinalized( buketOrOptsOrHandler: | string | StorageOptions - | ((event: CloudEvent) => any | Promise), - handler?: (event: CloudEvent) => any | Promise + | ((event: StorageEvent) => any | Promise), + handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(finalizedEvent, buketOrOptsOrHandler, handler); } /** Handle a storage object deleted */ export function onObjectDeleted( - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectDeleted( bucket: string, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectDeleted( opts: StorageOptions, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectDeleted( @@ -259,24 +265,24 @@ export function onObjectDeleted( | string | StorageOptions | ((event: CloudEvent) => any | Promise), - handler?: (event: CloudEvent) => any | Promise + handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(deletedEvent, buketOrOptsOrHandler, handler); } /** Handle a storage object metadata updated */ export function onObjectMetadataUpdated( - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectMetadataUpdated( bucket: string, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectMetadataUpdated( opts: StorageOptions, - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction; export function onObjectMetadataUpdated( @@ -284,7 +290,7 @@ export function onObjectMetadataUpdated( | string | StorageOptions | ((event: CloudEvent) => any | Promise), - handler?: (event: CloudEvent) => any | Promise + handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(metadataUpdatedEvent, buketOrOptsOrHandler, handler); } @@ -296,7 +302,7 @@ export function onOperation( | string | StorageOptions | ((event: CloudEvent) => any | Promise), - handler: (event: CloudEvent) => any | Promise + handler: (event: StorageEvent) => any | Promise ): CloudFunction { if (typeof bucketOrOptsOrHandler === 'function') { handler = bucketOrOptsOrHandler as ( @@ -310,7 +316,7 @@ export function onOperation( ); const func = (raw: CloudEvent) => { - return handler(raw as CloudEvent); + return handler(raw as StorageEvent); }; func.run = handler; From a802869d5c514cc9ee1368757f7d4bfac2812d0a Mon Sep 17 00:00:00 2001 From: Tyler Stark Date: Sat, 30 Apr 2022 14:07:33 -0500 Subject: [PATCH 2/2] Fixed NPE issue for Storage without Config Updated more signatures to optionally expect a bucket. --- src/v2/providers/alerts/crashlytics.ts | 2 +- src/v2/providers/storage.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/v2/providers/alerts/crashlytics.ts b/src/v2/providers/alerts/crashlytics.ts index 19a57eb29..14e8a87e8 100644 --- a/src/v2/providers/alerts/crashlytics.ts +++ b/src/v2/providers/alerts/crashlytics.ts @@ -71,7 +71,7 @@ export interface StabilityDigestPayload { */ digestDate: string; /** A stability digest containing several trending Crashlytics issues */ - trendingIssues: TrendingIssueDetails[]; + trendingIssues: TrendingIssueDetails[]; } /** diff --git a/src/v2/providers/storage.ts b/src/v2/providers/storage.ts index 0e39cf572..6c815615e 100644 --- a/src/v2/providers/storage.ts +++ b/src/v2/providers/storage.ts @@ -175,6 +175,7 @@ export interface CustomerEncryption { } interface WithBucket { + /** The name of the bucket containing this object. */ bucket: string; } @@ -214,7 +215,7 @@ export function onObjectArchived( buketOrOptsOrHandler: | string | StorageOptions - | ((event: CloudEvent) => any | Promise), + | ((event: StorageEvent) => any | Promise), handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(archivedEvent, buketOrOptsOrHandler, handler); @@ -264,7 +265,7 @@ export function onObjectDeleted( buketOrOptsOrHandler: | string | StorageOptions - | ((event: CloudEvent) => any | Promise), + | ((event: StorageEvent) => any | Promise), handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(deletedEvent, buketOrOptsOrHandler, handler); @@ -289,7 +290,7 @@ export function onObjectMetadataUpdated( buketOrOptsOrHandler: | string | StorageOptions - | ((event: CloudEvent) => any | Promise), + | ((event: StorageEvent) => any | Promise), handler?: (event: StorageEvent) => any | Promise ): CloudFunction { return onOperation(metadataUpdatedEvent, buketOrOptsOrHandler, handler); @@ -301,12 +302,12 @@ export function onOperation( bucketOrOptsOrHandler: | string | StorageOptions - | ((event: CloudEvent) => any | Promise), + | ((event: StorageEvent) => any | Promise), handler: (event: StorageEvent) => any | Promise ): CloudFunction { if (typeof bucketOrOptsOrHandler === 'function') { handler = bucketOrOptsOrHandler as ( - event: CloudEvent + event: StorageEvent ) => any | Promise; bucketOrOptsOrHandler = {}; } @@ -388,7 +389,7 @@ export function getOptsAndBucket( bucket = bucketOrOpts; opts = {}; } else { - bucket = bucketOrOpts.bucket || firebaseConfig().storageBucket; + bucket = bucketOrOpts.bucket || firebaseConfig()?.storageBucket; opts = { ...bucketOrOpts }; delete (opts as any).bucket; }