From 707c2962c6eed9c6e5e4d778c008c823af0e3e9a Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Wed, 19 Jan 2022 15:04:48 -0800 Subject: [PATCH 1/4] adding in crashlytics changes --- spec/v2/providers/alerts/crashlytics.spec.ts | 562 +++++++++++++++++++ src/v2/providers/alerts/crashlytics.ts | 319 +++++++++++ v2/alerts/crashlytics.js | 26 + 3 files changed, 907 insertions(+) create mode 100644 spec/v2/providers/alerts/crashlytics.spec.ts create mode 100644 src/v2/providers/alerts/crashlytics.ts create mode 100644 v2/alerts/crashlytics.js diff --git a/spec/v2/providers/alerts/crashlytics.spec.ts b/spec/v2/providers/alerts/crashlytics.spec.ts new file mode 100644 index 000000000..e5c62891b --- /dev/null +++ b/spec/v2/providers/alerts/crashlytics.spec.ts @@ -0,0 +1,562 @@ +import { expect } from 'chai'; +import * as alerts from '../../../../src/v2/providers/alerts'; +import * as crashlytics from '../../../../src/v2/providers/alerts/crashlytics'; +import { BASIC_ENDPOINT, BASIC_OPTIONS } from '../helpers'; + +const ALERT_TYPE = 'new-alert-type'; +const APPID = '123456789'; +const myHandler = () => 42; + +describe('crashlytics', () => { + describe('onNewFatalIssuePublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onNewFatalIssuePublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newFatalIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onNewFatalIssuePublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newFatalIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onNewFatalIssuePublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newFatalIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onNewFatalIssuePublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newFatalIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onNewNonfatalIssuePublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onNewNonfatalIssuePublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newNonfatalIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onNewNonfatalIssuePublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newNonfatalIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onNewNonfatalIssuePublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newNonfatalIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onNewNonfatalIssuePublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newNonfatalIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onRegressionAlertPublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onRegressionAlertPublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.regressionAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onRegressionAlertPublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.regressionAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onRegressionAlertPublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.regressionAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onRegressionAlertPublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.regressionAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onStabilityDigestPublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onStabilityDigestPublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.stabilityDigestAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onStabilityDigestPublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.stabilityDigestAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onStabilityDigestPublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.stabilityDigestAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onStabilityDigestPublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.stabilityDigestAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onVelocityAlertPublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onVelocityAlertPublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.velocityAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onVelocityAlertPublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.velocityAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onVelocityAlertPublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.velocityAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onVelocityAlertPublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.velocityAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onNewAnrIssuePublished', () => { + it('should create a function only handler', () => { + const func = crashlytics.onNewAnrIssuePublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newAnrIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with appId', () => { + const func = crashlytics.onNewAnrIssuePublished(APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newAnrIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onNewAnrIssuePublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newAnrIssueAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts', () => { + const func = crashlytics.onNewAnrIssuePublished( + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: crashlytics.newAnrIssueAlert, + appId: APPID, + }, + retry: false, + }, + }); + }); + }); + + describe('onOperation', () => { + it('should create a function with alertType only', () => { + const func = crashlytics.onOperation(ALERT_TYPE, myHandler, undefined); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: ALERT_TYPE, + }, + retry: false, + }, + }); + }); + + it('should create a function with alertType & appId', () => { + const func = crashlytics.onOperation(ALERT_TYPE, APPID, myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: ALERT_TYPE, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with base opts', () => { + const func = crashlytics.onOperation( + ALERT_TYPE, + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: ALERT_TYPE, + }, + retry: false, + }, + }); + }); + + it('should create a function with appid in opts', () => { + const func = crashlytics.onOperation( + ALERT_TYPE, + { ...BASIC_OPTIONS, appId: APPID }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: ALERT_TYPE, + appId: APPID, + }, + retry: false, + }, + }); + }); + + it('should create a function with a run method', () => { + const func = crashlytics.onOperation( + ALERT_TYPE, + (event) => event, + undefined + ); + + const res = func.run('input' as any); + + expect(res).to.equal('input'); + }); + }); + + describe('getOptsAndApp', () => { + it('should parse a string', () => { + const APPID = '123456789'; + + const [opts, appId] = crashlytics.getOptsAndApp(APPID); + + expect(opts).to.deep.equal({}); + expect(appId).to.equal(APPID); + }); + + it('should parse an options object without appId', () => { + const myOpts: crashlytics.CrashlyticsOptions = { + region: 'us-west1', + }; + + const [opts, appId] = crashlytics.getOptsAndApp(myOpts); + + expect(opts).to.deep.equal({ region: 'us-west1' }); + expect(appId).to.be.undefined; + }); + + it('should parse an options object with appId', () => { + const myOpts: crashlytics.CrashlyticsOptions = { + appId: '123456789', + region: 'us-west1', + }; + + const [opts, appId] = crashlytics.getOptsAndApp(myOpts); + + expect(opts).to.deep.equal({ region: 'us-west1' }); + expect(appId).to.equal(myOpts.appId); + }); + }); +}); diff --git a/src/v2/providers/alerts/crashlytics.ts b/src/v2/providers/alerts/crashlytics.ts new file mode 100644 index 000000000..f3b85035d --- /dev/null +++ b/src/v2/providers/alerts/crashlytics.ts @@ -0,0 +1,319 @@ +import { defineEndpoint, FirebaseAlertData } from '.'; +import { ManifestEndpoint } from '../../../common/manifest'; +import { CloudEvent, CloudFunction } from '../../core'; +import * as options from '../../options'; + +/** Data */ +interface Issue { + id: string; + title: string; + subtitle: string; + appVersion: string; +} +// crashlytics.newFatalIssue +export interface NewFatalIssuePayload { + ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewFatalIssuePayload'; + issue: Issue; +} +// crashlytics.newNonfatalIssue +export interface NewNonfatalIssuePayload { + ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewNonfatalIssuePayload'; + issue: Issue; +} +// crashlytics.regression +export interface RegressionAlertPayload { + ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsRegressionAlertPayload'; + type: string; + issue: Issue; + resolveTime: string; +} +// crashlytics.stabilityDigest +interface TrendingIssueDetails { + type: string; + issue: Issue; + eventCount: number; + userCount: number; +} +export interface StabilityDigestPayload { + ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsStabilityDigestPayload'; + digestDate: string; + trendingIssues: TrendingIssueDetails[]; +} +// crashlytics.velocity +export interface VelocityAlertPayload { + ['@type']: 'com.google.firebase.firebasealerts.VelocityAlertPayload'; + issue: Issue; + createTime: string; + crashCount: number; + crashPercentage: number; + firstVersion: string; +} +// crashlytics.newAnrIssue +export interface NewAnrIssuePayload { + ['@type']: 'com.google.firebase.firebasealerts.NewAnrIssuePayload'; + issue: Issue; +} + +/** Events */ +/** @internal */ +export const newFatalIssueAlert = 'crashlytics.newFatalIssue'; +/** @internal */ +export const newNonfatalIssueAlert = 'crashlytics.newNonfatalIssue'; +/** @internal */ +export const regressionAlert = 'crashlytics.regression'; +/** @internal */ +export const stabilityDigestAlert = 'crashlytics.stabilityDigest'; +/** @internal */ +export const velocityAlert = 'crashlytics.velocity'; +/** @internal */ +export const newAnrIssueAlert = 'crashlytics.newAnrIssue'; + +/** Options */ +export interface CrashlyticsOptions extends options.EventHandlerOptions { + appId?: string; +} + +/** Cloud Event Type */ +// appId will always be defined in Crashlytics events +interface WithAlertTypeAndApp { + alertType: string; // required in the payload + appId: string; // required in the payload +} +export type CrashlyticsEvent = CloudEvent< + FirebaseAlertData, + WithAlertTypeAndApp +>; + +/** Handlers */ +export function onNewFatalIssuePublished( + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewFatalIssuePublished( + appId: string, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewFatalIssuePublished( + opts: CrashlyticsOptions, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewFatalIssuePublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler?: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + newFatalIssueAlert, + appIdOrOptsOrHandler, + handler + ); +} + +export function onNewNonfatalIssuePublished( + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onNewNonfatalIssuePublished( + appId: string, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onNewNonfatalIssuePublished( + opts: CrashlyticsOptions, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onNewNonfatalIssuePublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | (( + event: CrashlyticsEvent + ) => any | Promise), + handler?: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + newNonfatalIssueAlert, + appIdOrOptsOrHandler, + handler + ); +} + +export function onRegressionAlertPublished( + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onRegressionAlertPublished( + appId: string, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onRegressionAlertPublished( + opts: CrashlyticsOptions, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onRegressionAlertPublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler?: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + regressionAlert, + appIdOrOptsOrHandler, + handler + ); +} + +export function onStabilityDigestPublished( + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onStabilityDigestPublished( + appId: string, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onStabilityDigestPublished( + opts: CrashlyticsOptions, + handler: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction>; +export function onStabilityDigestPublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler?: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + stabilityDigestAlert, + appIdOrOptsOrHandler, + handler + ); +} + +export function onVelocityAlertPublished( + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onVelocityAlertPublished( + appId: string, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onVelocityAlertPublished( + opts: CrashlyticsOptions, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onVelocityAlertPublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler?: ( + event: CrashlyticsEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + velocityAlert, + appIdOrOptsOrHandler, + handler + ); +} + +export function onNewAnrIssuePublished( + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewAnrIssuePublished( + appId: string, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewAnrIssuePublished( + opts: CrashlyticsOptions, + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction>; +export function onNewAnrIssuePublished( + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler?: (event: CrashlyticsEvent) => any | Promise +): CloudFunction> { + return onOperation( + newAnrIssueAlert, + appIdOrOptsOrHandler, + handler + ); +} + +/** @internal */ +export function onOperation( + alertType: string, + appIdOrOptsOrHandler: + | string + | CrashlyticsOptions + | ((event: CrashlyticsEvent) => any | Promise), + handler: (event: CrashlyticsEvent) => any | Promise +): CloudFunction> { + if (typeof appIdOrOptsOrHandler === 'function') { + handler = appIdOrOptsOrHandler as ( + event: CrashlyticsEvent + ) => any | Promise; + appIdOrOptsOrHandler = {}; + } + + const [opts, appId] = getOptsAndApp( + appIdOrOptsOrHandler as string | CrashlyticsOptions + ); + + const func = (raw: CloudEvent) => { + return handler(raw as CrashlyticsEvent); + }; + + func.run = handler; + + // TypeScript doesn't recognize defineProperty as adding a property and complains + // that __endpoint doesn't exist. We can either cast to any and lose all type safety + // or we can just assign a meaningless value before calling defineProperty. + func.__trigger = 'silence the transpiler'; + func.__endpoint = {} as ManifestEndpoint; + defineEndpoint(func, opts, alertType, appId); + + return func; +} + +/** @internal */ +export function getOptsAndApp( + appIdOrOpts: string | CrashlyticsOptions +): [options.EventHandlerOptions, string | undefined] { + let opts: options.EventHandlerOptions; + let appId: string | undefined; + if (typeof appIdOrOpts === 'string') { + opts = {}; + appId = appIdOrOpts; + } else { + appId = appIdOrOpts.appId; + opts = { ...appIdOrOpts }; + delete (opts as any).appId; + } + return [opts, appId]; +} diff --git a/v2/alerts/crashlytics.js b/v2/alerts/crashlytics.js new file mode 100644 index 000000000..7d725acc3 --- /dev/null +++ b/v2/alerts/crashlytics.js @@ -0,0 +1,26 @@ +// The MIT License (MIT) +// +// Copyright (c) 2021 Firebase +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// This file is not part of the firebase-functions SDK. It is used to silence the +// imports eslint plugin until it can understand import paths defined by node +// package exports. +// For more information, see github.com/import-js/eslint-plugin-import/issues/1810 From 43f21305a4eba929330c2636f5c1f2df05ace753 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Thu, 20 Jan 2022 07:52:32 -0800 Subject: [PATCH 2/4] comments & adding package refs --- package.json | 6 +++++- src/v2/providers/alerts/crashlytics.ts | 26 ++++++++++++++++---------- src/v2/providers/alerts/index.ts | 4 ++++ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d19a8c5cf..6aef18eeb 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,8 @@ "./v2/params": "./lib/v2/params/index.js", "./v2/pubsub": "./lib/v2/providers/pubsub.js", "./v2/storage": "./lib/v2/providers/storage.js", - "./v2/alerts": "./lib/v2/providers/alerts/index.js" + "./v2/alerts": "./lib/v2/providers/alerts/index.js", + "./v2/alerts/crashlytics": "./lib/v2/providers/alerts/crashlytics.js" }, "typesVersions": { "*": { @@ -118,6 +119,9 @@ ], "v2/alerts": [ "lib/v2/providers/alerts" + ], + "v2/alerts/crashlytics": [ + "lib/v2/providers/alerts/crashlytics" ] } }, diff --git a/src/v2/providers/alerts/crashlytics.ts b/src/v2/providers/alerts/crashlytics.ts index f3b85035d..fc2d11954 100644 --- a/src/v2/providers/alerts/crashlytics.ts +++ b/src/v2/providers/alerts/crashlytics.ts @@ -4,42 +4,44 @@ import { CloudEvent, CloudFunction } from '../../core'; import * as options from '../../options'; /** Data */ +/** Generic issue interface */ interface Issue { id: string; title: string; subtitle: string; appVersion: string; } -// crashlytics.newFatalIssue +/** Payload for a new fatal issue */ export interface NewFatalIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewFatalIssuePayload'; issue: Issue; } -// crashlytics.newNonfatalIssue +/** Payload for a new non-fatal issue */ export interface NewNonfatalIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewNonfatalIssuePayload'; issue: Issue; } -// crashlytics.regression +/** Payload for a regression alert */ export interface RegressionAlertPayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsRegressionAlertPayload'; type: string; issue: Issue; resolveTime: string; } -// crashlytics.stabilityDigest +/** Generic trending issue interface */ interface TrendingIssueDetails { type: string; issue: Issue; eventCount: number; userCount: number; } +/** Payload for a stability digest */ export interface StabilityDigestPayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsStabilityDigestPayload'; digestDate: string; trendingIssues: TrendingIssueDetails[]; } -// crashlytics.velocity +/** Payload for a velocity alert */ export interface VelocityAlertPayload { ['@type']: 'com.google.firebase.firebasealerts.VelocityAlertPayload'; issue: Issue; @@ -48,13 +50,12 @@ export interface VelocityAlertPayload { crashPercentage: number; firstVersion: string; } -// crashlytics.newAnrIssue +/** Payload for a new ANR issue */ export interface NewAnrIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.NewAnrIssuePayload'; issue: Issue; } -/** Events */ /** @internal */ export const newFatalIssueAlert = 'crashlytics.newFatalIssue'; /** @internal */ @@ -74,10 +75,9 @@ export interface CrashlyticsOptions extends options.EventHandlerOptions { } /** Cloud Event Type */ -// appId will always be defined in Crashlytics events interface WithAlertTypeAndApp { - alertType: string; // required in the payload - appId: string; // required in the payload + alertType: string; + appId: string; } export type CrashlyticsEvent = CloudEvent< FirebaseAlertData, @@ -85,6 +85,7 @@ export type CrashlyticsEvent = CloudEvent< >; /** Handlers */ +/** Handle a new fatal issue published */ export function onNewFatalIssuePublished( handler: (event: CrashlyticsEvent) => any | Promise ): CloudFunction>; @@ -112,6 +113,7 @@ export function onNewFatalIssuePublished( ); } +/** Handle a new non-fatal issue published */ export function onNewNonfatalIssuePublished( handler: ( event: CrashlyticsEvent @@ -147,6 +149,7 @@ export function onNewNonfatalIssuePublished( ); } +/** Handle a regression alert published */ export function onRegressionAlertPublished( handler: ( event: CrashlyticsEvent @@ -180,6 +183,7 @@ export function onRegressionAlertPublished( ); } +/** Handle a stability digest published */ export function onStabilityDigestPublished( handler: ( event: CrashlyticsEvent @@ -213,6 +217,7 @@ export function onStabilityDigestPublished( ); } +/** Handle a velocity alert published */ export function onVelocityAlertPublished( handler: (event: CrashlyticsEvent) => any | Promise ): CloudFunction>; @@ -240,6 +245,7 @@ export function onVelocityAlertPublished( ); } +/** Handle a new ANR issue published */ export function onNewAnrIssuePublished( handler: (event: CrashlyticsEvent) => any | Promise ): CloudFunction>; diff --git a/src/v2/providers/alerts/index.ts b/src/v2/providers/alerts/index.ts index c40670cd1..fb604b597 100644 --- a/src/v2/providers/alerts/index.ts +++ b/src/v2/providers/alerts/index.ts @@ -1 +1,5 @@ +import * as crashlytics from './crashlytics'; + +export { crashlytics }; + export * from './alerts'; From e4bf400c2d1789d5534bfdd8e261d7fb95ac1e87 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Mon, 24 Jan 2022 19:37:11 -0800 Subject: [PATCH 3/4] address comments and make doc strings better --- spec/v2/providers/alerts/crashlytics.spec.ts | 58 ++--- src/v2/providers/alerts/crashlytics.ts | 210 ++++++++++--------- src/v2/providers/alerts/index.ts | 4 - 3 files changed, 138 insertions(+), 134 deletions(-) diff --git a/spec/v2/providers/alerts/crashlytics.spec.ts b/spec/v2/providers/alerts/crashlytics.spec.ts index e5c62891b..1d5c1a8b6 100644 --- a/spec/v2/providers/alerts/crashlytics.spec.ts +++ b/spec/v2/providers/alerts/crashlytics.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as alerts from '../../../../src/v2/providers/alerts'; import * as crashlytics from '../../../../src/v2/providers/alerts/crashlytics'; -import { BASIC_ENDPOINT, BASIC_OPTIONS } from '../helpers'; +import { FULL_ENDPOINT, FULL_OPTIONS } from '../helpers'; const ALERT_TYPE = 'new-alert-type'; const APPID = '123456789'; @@ -44,12 +44,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onNewFatalIssuePublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -62,12 +62,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onNewFatalIssuePublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -116,12 +116,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onNewNonfatalIssuePublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -134,12 +134,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onNewNonfatalIssuePublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -188,12 +188,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onRegressionAlertPublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -206,12 +206,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onRegressionAlertPublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -260,12 +260,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onStabilityDigestPublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -278,12 +278,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onStabilityDigestPublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -332,12 +332,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onVelocityAlertPublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -350,12 +350,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onVelocityAlertPublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -404,12 +404,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onNewAnrIssuePublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -422,12 +422,12 @@ describe('crashlytics', () => { it('should create a function with opts', () => { const func = crashlytics.onNewAnrIssuePublished( - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -477,12 +477,12 @@ describe('crashlytics', () => { it('should create a function with base opts', () => { const func = crashlytics.onOperation( ALERT_TYPE, - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -496,12 +496,12 @@ describe('crashlytics', () => { it('should create a function with appid in opts', () => { const func = crashlytics.onOperation( ALERT_TYPE, - { ...BASIC_OPTIONS, appId: APPID }, + { ...FULL_OPTIONS, appId: APPID }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { diff --git a/src/v2/providers/alerts/crashlytics.ts b/src/v2/providers/alerts/crashlytics.ts index fc2d11954..ea47d38c4 100644 --- a/src/v2/providers/alerts/crashlytics.ts +++ b/src/v2/providers/alerts/crashlytics.ts @@ -1,47 +1,66 @@ -import { defineEndpoint, FirebaseAlertData } from '.'; -import { ManifestEndpoint } from '../../../common/manifest'; +import { getEndpointAnnotation, FirebaseAlertData } from '.'; import { CloudEvent, CloudFunction } from '../../core'; import * as options from '../../options'; -/** Data */ -/** Generic issue interface */ +/** Generic crashlytics issue interface */ interface Issue { id: string; title: string; subtitle: string; appVersion: string; } -/** Payload for a new fatal issue */ + +/** + * The internal payload object for a new fatal issue. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface NewFatalIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewFatalIssuePayload'; issue: Issue; } -/** Payload for a new non-fatal issue */ + +/** + * The internal payload object for a new non-fatal issue. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface NewNonfatalIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsNewNonfatalIssuePayload'; issue: Issue; } -/** Payload for a regression alert */ + +/** + * The internal payload object for a regression alert. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface RegressionAlertPayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsRegressionAlertPayload'; type: string; issue: Issue; resolveTime: string; } -/** Generic trending issue interface */ + +/** Generic crashlytics trending issue interface */ interface TrendingIssueDetails { type: string; issue: Issue; eventCount: number; userCount: number; } -/** Payload for a stability digest */ + +/** + * The internal payload object for a stability digest. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface StabilityDigestPayload { ['@type']: 'com.google.firebase.firebasealerts.CrashlyticsStabilityDigestPayload'; digestDate: string; trendingIssues: TrendingIssueDetails[]; } -/** Payload for a velocity alert */ + +/** + * The internal payload object for a velocity alert. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface VelocityAlertPayload { ['@type']: 'com.google.firebase.firebasealerts.VelocityAlertPayload'; issue: Issue; @@ -50,12 +69,28 @@ export interface VelocityAlertPayload { crashPercentage: number; firstVersion: string; } -/** Payload for a new ANR issue */ + +/** + * The internal payload object for a new Application Not Responding issue. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface NewAnrIssuePayload { ['@type']: 'com.google.firebase.firebasealerts.NewAnrIssuePayload'; issue: Issue; } +interface WithAlertTypeAndApp { + alertType: string; + appId: string; +} +/** + * A custom CloudEvent for Firebase Alerts (with custom extension attributes). + */ +export type CrashlyticsEvent = CloudEvent< + FirebaseAlertData, + WithAlertTypeAndApp +>; + /** @internal */ export const newFatalIssueAlert = 'crashlytics.newFatalIssue'; /** @internal */ @@ -69,42 +104,38 @@ export const velocityAlert = 'crashlytics.velocity'; /** @internal */ export const newAnrIssueAlert = 'crashlytics.newAnrIssue'; -/** Options */ +/** + * Configuration for crashlytics functions. + */ export interface CrashlyticsOptions extends options.EventHandlerOptions { appId?: string; } -/** Cloud Event Type */ -interface WithAlertTypeAndApp { - alertType: string; - appId: string; -} -export type CrashlyticsEvent = CloudEvent< - FirebaseAlertData, - WithAlertTypeAndApp ->; +/** @internal */ +type CrashlyticsEventHandler = ( + event: CrashlyticsEvent +) => any | Promise; -/** Handlers */ -/** Handle a new fatal issue published */ +/** + * Declares a function that can handle a new fatal issue published to crashlytics. + */ export function onNewFatalIssuePublished( - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewFatalIssuePublished( appId: string, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewFatalIssuePublished( opts: CrashlyticsOptions, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewFatalIssuePublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler?: ( - event: CrashlyticsEvent - ) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( newFatalIssueAlert, @@ -113,34 +144,26 @@ export function onNewFatalIssuePublished( ); } -/** Handle a new non-fatal issue published */ +/** + * Declares a function that can handle aa new non-fatal issue published to crashlytics. + */ export function onNewNonfatalIssuePublished( - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewNonfatalIssuePublished( appId: string, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewNonfatalIssuePublished( opts: CrashlyticsOptions, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewNonfatalIssuePublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | (( - event: CrashlyticsEvent - ) => any | Promise), - handler?: ( - event: CrashlyticsEvent - ) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( newNonfatalIssueAlert, @@ -149,32 +172,26 @@ export function onNewNonfatalIssuePublished( ); } -/** Handle a regression alert published */ +/** + * Declares a function that can handle a regression alert published to crashlytics. + */ export function onRegressionAlertPublished( - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onRegressionAlertPublished( appId: string, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onRegressionAlertPublished( opts: CrashlyticsOptions, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onRegressionAlertPublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler?: ( - event: CrashlyticsEvent - ) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( regressionAlert, @@ -183,32 +200,26 @@ export function onRegressionAlertPublished( ); } -/** Handle a stability digest published */ +/** + * Declares a function that can handle a stability digest published to crashlytics. + */ export function onStabilityDigestPublished( - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onStabilityDigestPublished( appId: string, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onStabilityDigestPublished( opts: CrashlyticsOptions, - handler: ( - event: CrashlyticsEvent - ) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onStabilityDigestPublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler?: ( - event: CrashlyticsEvent - ) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( stabilityDigestAlert, @@ -217,26 +228,26 @@ export function onStabilityDigestPublished( ); } -/** Handle a velocity alert published */ +/** + * Declares a function that can handle a velocity alert published to crashlytics. + */ export function onVelocityAlertPublished( - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onVelocityAlertPublished( appId: string, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onVelocityAlertPublished( opts: CrashlyticsOptions, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onVelocityAlertPublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler?: ( - event: CrashlyticsEvent - ) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( velocityAlert, @@ -245,24 +256,26 @@ export function onVelocityAlertPublished( ); } -/** Handle a new ANR issue published */ +/** + * Declares a function that can handle a new Application Not Responding issue published to crashlytics. + */ export function onNewAnrIssuePublished( - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewAnrIssuePublished( appId: string, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewAnrIssuePublished( opts: CrashlyticsOptions, - handler: (event: CrashlyticsEvent) => any | Promise + handler: CrashlyticsEventHandler ): CloudFunction>; export function onNewAnrIssuePublished( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler?: (event: CrashlyticsEvent) => any | Promise + | CrashlyticsEventHandler, + handler?: CrashlyticsEventHandler ): CloudFunction> { return onOperation( newAnrIssueAlert, @@ -277,13 +290,11 @@ export function onOperation( appIdOrOptsOrHandler: | string | CrashlyticsOptions - | ((event: CrashlyticsEvent) => any | Promise), - handler: (event: CrashlyticsEvent) => any | Promise + | CrashlyticsEventHandler, + handler: CrashlyticsEventHandler ): CloudFunction> { if (typeof appIdOrOptsOrHandler === 'function') { - handler = appIdOrOptsOrHandler as ( - event: CrashlyticsEvent - ) => any | Promise; + handler = appIdOrOptsOrHandler as CrashlyticsEventHandler; appIdOrOptsOrHandler = {}; } @@ -296,18 +307,15 @@ export function onOperation( }; func.run = handler; - - // TypeScript doesn't recognize defineProperty as adding a property and complains - // that __endpoint doesn't exist. We can either cast to any and lose all type safety - // or we can just assign a meaningless value before calling defineProperty. - func.__trigger = 'silence the transpiler'; - func.__endpoint = {} as ManifestEndpoint; - defineEndpoint(func, opts, alertType, appId); + func.__endpoint = getEndpointAnnotation(opts, alertType, appId); return func; } -/** @internal */ +/** + * @internal + * Helper function to parse the function opts and appId. + */ export function getOptsAndApp( appIdOrOpts: string | CrashlyticsOptions ): [options.EventHandlerOptions, string | undefined] { diff --git a/src/v2/providers/alerts/index.ts b/src/v2/providers/alerts/index.ts index fb604b597..c40670cd1 100644 --- a/src/v2/providers/alerts/index.ts +++ b/src/v2/providers/alerts/index.ts @@ -1,5 +1 @@ -import * as crashlytics from './crashlytics'; - -export { crashlytics }; - export * from './alerts'; From 4565f47f0f54904070b839d767fb6478c58dd209 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Thu, 27 Jan 2022 15:37:33 -0800 Subject: [PATCH 4/4] add opts.retry to event trigger --- src/v2/providers/alerts/alerts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/providers/alerts/alerts.ts b/src/v2/providers/alerts/alerts.ts index 41af22dd7..4b7f0b952 100644 --- a/src/v2/providers/alerts/alerts.ts +++ b/src/v2/providers/alerts/alerts.ts @@ -94,7 +94,7 @@ export function getEndpointAnnotation( eventFilters: { alertType, }, - retry: false, + retry: !!opts.retry, }, }; if (appId) {