From 632bd507fb07ccd13215daf1292298064d2cb059 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Wed, 19 Jan 2022 15:03:25 -0800 Subject: [PATCH 1/7] adding in billing changes --- spec/v2/providers/alerts/billing.spec.ts | 126 +++++++++++++++++++++++ src/v2/providers/alerts/billing.ts | 105 +++++++++++++++++++ v2/alerts/billing.js | 26 +++++ 3 files changed, 257 insertions(+) create mode 100644 spec/v2/providers/alerts/billing.spec.ts create mode 100644 src/v2/providers/alerts/billing.ts create mode 100644 v2/alerts/billing.js diff --git a/spec/v2/providers/alerts/billing.spec.ts b/spec/v2/providers/alerts/billing.spec.ts new file mode 100644 index 000000000..563de7515 --- /dev/null +++ b/spec/v2/providers/alerts/billing.spec.ts @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import * as alerts from '../../../../src/v2/providers/alerts'; +import * as billing from '../../../../src/v2/providers/alerts/billing'; +import { BASIC_ENDPOINT, BASIC_OPTIONS } from '../helpers'; + +const ALERT_TYPE = 'new-alert-type'; +const myHandler = () => 42; + +describe('billing', () => { + describe('onPlanUpdatePublished', () => { + it('should create a function with only handler', () => { + const func = billing.onPlanUpdatePublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: billing.planUpdateAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts & handler', () => { + const func = billing.onPlanUpdatePublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: billing.planUpdateAlert, + }, + retry: false, + }, + }); + }); + }); + + describe('onAutomatedPlanUpdatePublished', () => { + it('should create a function with only handler', () => { + const func = billing.onAutomatedPlanUpdatePublished(myHandler); + + expect(func.__endpoint).to.deep.equal({ + platform: 'gcfv2', + labels: {}, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: billing.automatedPlanUpdateAlert, + }, + retry: false, + }, + }); + }); + + it('should create a function with opts & handler', () => { + const func = billing.onAutomatedPlanUpdatePublished( + { ...BASIC_OPTIONS }, + myHandler + ); + + expect(func.__endpoint).to.deep.equal({ + ...BASIC_ENDPOINT, + eventTrigger: { + eventType: alerts.eventType, + eventFilters: { + alertType: billing.automatedPlanUpdateAlert, + }, + retry: false, + }, + }); + }); + }); + + describe('onOperation', () => { + it('should create a function with alertType only', () => { + const func = billing.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 opts', () => { + const func = billing.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 a run method', () => { + const func = billing.onOperation(ALERT_TYPE, (event) => event, undefined); + + const res = func.run('input' as any); + + expect(res).to.equal('input'); + }); + }); +}); diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts new file mode 100644 index 000000000..6fa3dc56a --- /dev/null +++ b/src/v2/providers/alerts/billing.ts @@ -0,0 +1,105 @@ +import { defineEndpoint, FirebaseAlertData } from '.'; +import { ManifestEndpoint } from '../../../common/manifest'; +import { CloudEvent, CloudFunction } from '../../core'; +import * as options from '../../options'; + +/** Data */ +// billing.planUpdate +export interface PlanUpdatePayload { + ['@type']: 'com.google.firebase.firebasealerts.PlanUpdatePayload'; + billingPlan: string; + principalEmail: string; +} +// billing.automatedPlanUpdate +export interface PlanAutomatedUpdatePayload { + ['@type']: 'com.google.firebase.firebasealerts.PlanAutomatedUpdatePayload'; + billingPlan: string; +} + +/** Events */ +/** @internal */ +export const planUpdateAlert = 'billing.planUpdate'; +/** @internal */ +export const automatedPlanUpdateAlert = 'billing.automatedPlanUpdate'; + +/** Cloud Event Type */ +interface WithAlertType { + alertType: string; +} +export type BillingEvent = CloudEvent, WithAlertType>; + +/** Handlers */ +export function onPlanUpdatePublished( + handler: (event: BillingEvent) => any | Promise +): CloudFunction>; +export function onPlanUpdatePublished( + opts: options.EventHandlerOptions, + handler: (event: BillingEvent) => any | Promise +): CloudFunction>; +export function onPlanUpdatePublished( + optsOrHandler: + | options.EventHandlerOptions + | ((event: BillingEvent) => any | Promise), + handler?: (event: BillingEvent) => any | Promise +): CloudFunction> { + return onOperation( + planUpdateAlert, + optsOrHandler, + handler + ); +} + +export function onAutomatedPlanUpdatePublished( + handler: ( + event: BillingEvent + ) => any | Promise +): CloudFunction>; +export function onAutomatedPlanUpdatePublished( + opts: options.EventHandlerOptions, + handler: ( + event: BillingEvent + ) => any | Promise +): CloudFunction>; +export function onAutomatedPlanUpdatePublished( + optsOrHandler: + | options.EventHandlerOptions + | ((event: BillingEvent) => any | Promise), + handler?: ( + event: BillingEvent + ) => any | Promise +): CloudFunction> { + return onOperation( + automatedPlanUpdateAlert, + optsOrHandler, + handler + ); +} + +/** @internal */ +export function onOperation( + alertType: string, + optsOrHandler: + | options.EventHandlerOptions + | ((event: BillingEvent) => any | Promise), + handler: (event: BillingEvent) => any | Promise +): CloudFunction> { + if (typeof optsOrHandler === 'function') { + handler = optsOrHandler as (event: BillingEvent) => any | Promise; + optsOrHandler = {}; + } + + const func = (raw: CloudEvent) => { + return handler(raw as BillingEvent); + }; + + 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, optsOrHandler, alertType, undefined); + + return func; +} diff --git a/v2/alerts/billing.js b/v2/alerts/billing.js new file mode 100644 index 000000000..7d725acc3 --- /dev/null +++ b/v2/alerts/billing.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 11ee61832bfc7ceae1abcefebd7f28b11851d096 Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Thu, 20 Jan 2022 07:42:16 -0800 Subject: [PATCH 2/7] removing comments & adding package refs --- package.json | 6 +++++- src/v2/providers/alerts/billing.ts | 3 --- src/v2/providers/alerts/index.ts | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d19a8c5cf..13cea04a1 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/billing": "./lib/v2/providers/alerts/billing.js" }, "typesVersions": { "*": { @@ -118,6 +119,9 @@ ], "v2/alerts": [ "lib/v2/providers/alerts" + ], + "v2/alerts/billing": [ + "lib/v2/providers/alerts/billing" ] } }, diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index 6fa3dc56a..3683421ae 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -4,19 +4,16 @@ import { CloudEvent, CloudFunction } from '../../core'; import * as options from '../../options'; /** Data */ -// billing.planUpdate export interface PlanUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanUpdatePayload'; billingPlan: string; principalEmail: string; } -// billing.automatedPlanUpdate export interface PlanAutomatedUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanAutomatedUpdatePayload'; billingPlan: string; } -/** Events */ /** @internal */ export const planUpdateAlert = 'billing.planUpdate'; /** @internal */ diff --git a/src/v2/providers/alerts/index.ts b/src/v2/providers/alerts/index.ts index c40670cd1..7abd89472 100644 --- a/src/v2/providers/alerts/index.ts +++ b/src/v2/providers/alerts/index.ts @@ -1 +1,5 @@ +import * as billing from './billing'; + +export { billing }; + export * from './alerts'; From 480c757fa21cf80b5f696dff4154e735d91a6a5b Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Thu, 20 Jan 2022 07:55:45 -0800 Subject: [PATCH 3/7] jsdoc comments --- src/v2/providers/alerts/billing.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index 3683421ae..3bb7b5ff2 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -4,11 +4,13 @@ import { CloudEvent, CloudFunction } from '../../core'; import * as options from '../../options'; /** Data */ +/** Payload for plan update */ export interface PlanUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanUpdatePayload'; billingPlan: string; principalEmail: string; } +/** Payload for plan automated update */ export interface PlanAutomatedUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanAutomatedUpdatePayload'; billingPlan: string; @@ -26,6 +28,7 @@ interface WithAlertType { export type BillingEvent = CloudEvent, WithAlertType>; /** Handlers */ +/** Handle a plan update published */ export function onPlanUpdatePublished( handler: (event: BillingEvent) => any | Promise ): CloudFunction>; @@ -46,6 +49,7 @@ export function onPlanUpdatePublished( ); } +/** Handle an automated plan update published */ export function onAutomatedPlanUpdatePublished( handler: ( event: BillingEvent From c7df9e71422586f67d91391df78d5a0239fbd34e Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Mon, 24 Jan 2022 18:46:56 -0800 Subject: [PATCH 4/7] addressing pr comments --- spec/v2/providers/alerts/billing.spec.ts | 14 +++--- src/v2/providers/alerts/billing.ts | 60 ++++++++++++------------ src/v2/providers/alerts/index.ts | 4 -- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/spec/v2/providers/alerts/billing.spec.ts b/spec/v2/providers/alerts/billing.spec.ts index 563de7515..a9e4e173d 100644 --- a/spec/v2/providers/alerts/billing.spec.ts +++ b/spec/v2/providers/alerts/billing.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as alerts from '../../../../src/v2/providers/alerts'; import * as billing from '../../../../src/v2/providers/alerts/billing'; -import { BASIC_ENDPOINT, BASIC_OPTIONS } from '../helpers'; +import { FULL_ENDPOINT, FULL_OPTIONS } from '../helpers'; const ALERT_TYPE = 'new-alert-type'; const myHandler = () => 42; @@ -26,12 +26,12 @@ describe('billing', () => { it('should create a function with opts & handler', () => { const func = billing.onPlanUpdatePublished( - { ...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('billing', () => { it('should create a function with opts & handler', () => { const func = billing.onAutomatedPlanUpdatePublished( - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { @@ -99,12 +99,12 @@ describe('billing', () => { it('should create a function with opts', () => { const func = billing.onOperation( ALERT_TYPE, - { ...BASIC_OPTIONS }, + { ...FULL_OPTIONS }, myHandler ); expect(func.__endpoint).to.deep.equal({ - ...BASIC_ENDPOINT, + ...FULL_ENDPOINT, eventTrigger: { eventType: alerts.eventType, eventFilters: { diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index 3bb7b5ff2..ddf86f9e5 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -1,46 +1,56 @@ -import { defineEndpoint, FirebaseAlertData } from '.'; -import { ManifestEndpoint } from '../../../common/manifest'; +import { getEndpointAnnotation, FirebaseAlertData } from '.'; import { CloudEvent, CloudFunction } from '../../core'; import * as options from '../../options'; -/** Data */ -/** Payload for plan update */ +/** + * The internal payload object for billing plan updates. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface PlanUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanUpdatePayload'; billingPlan: string; principalEmail: string; } -/** Payload for plan automated update */ + +/** + * The internal payload object for billing plan automated updates. + * Payload is wrapped inside a FirebaseAlertData object. + */ export interface PlanAutomatedUpdatePayload { ['@type']: 'com.google.firebase.firebasealerts.PlanAutomatedUpdatePayload'; billingPlan: string; } +interface WithAlertType { + alertType: string; +} +/** + * A custom CloudEvent for billing Firebase Alerts (with custom extension attributes). + */ +export type BillingEvent = CloudEvent, WithAlertType>; + /** @internal */ export const planUpdateAlert = 'billing.planUpdate'; /** @internal */ export const automatedPlanUpdateAlert = 'billing.automatedPlanUpdate'; -/** Cloud Event Type */ -interface WithAlertType { - alertType: string; -} -export type BillingEvent = CloudEvent, WithAlertType>; +/** @internal */ +type BillingEventHandler = (event: BillingEvent) => any | Promise; /** Handlers */ /** Handle a plan update published */ export function onPlanUpdatePublished( - handler: (event: BillingEvent) => any | Promise + handler: BillingEventHandler ): CloudFunction>; export function onPlanUpdatePublished( opts: options.EventHandlerOptions, - handler: (event: BillingEvent) => any | Promise + handler: BillingEventHandler ): CloudFunction>; export function onPlanUpdatePublished( optsOrHandler: | options.EventHandlerOptions - | ((event: BillingEvent) => any | Promise), - handler?: (event: BillingEvent) => any | Promise + | BillingEventHandler, + handler?: BillingEventHandler ): CloudFunction> { return onOperation( planUpdateAlert, @@ -51,23 +61,17 @@ export function onPlanUpdatePublished( /** Handle an automated plan update published */ export function onAutomatedPlanUpdatePublished( - handler: ( - event: BillingEvent - ) => any | Promise + handler: BillingEventHandler ): CloudFunction>; export function onAutomatedPlanUpdatePublished( opts: options.EventHandlerOptions, - handler: ( - event: BillingEvent - ) => any | Promise + handler: BillingEventHandler ): CloudFunction>; export function onAutomatedPlanUpdatePublished( optsOrHandler: | options.EventHandlerOptions - | ((event: BillingEvent) => any | Promise), - handler?: ( - event: BillingEvent - ) => any | Promise + | BillingEventHandler, + handler?: BillingEventHandler ): CloudFunction> { return onOperation( automatedPlanUpdateAlert, @@ -94,13 +98,7 @@ 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, optsOrHandler, alertType, undefined); + func.__endpoint = getEndpointAnnotation(optsOrHandler, alertType); return func; } diff --git a/src/v2/providers/alerts/index.ts b/src/v2/providers/alerts/index.ts index 7abd89472..c40670cd1 100644 --- a/src/v2/providers/alerts/index.ts +++ b/src/v2/providers/alerts/index.ts @@ -1,5 +1 @@ -import * as billing from './billing'; - -export { billing }; - export * from './alerts'; From 1749f561141b2551443160d8b8aea1f713dec16c Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Mon, 24 Jan 2022 18:52:50 -0800 Subject: [PATCH 5/7] change handler doc string --- src/v2/providers/alerts/billing.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index ddf86f9e5..f07f8dbbd 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -37,8 +37,9 @@ export const automatedPlanUpdateAlert = 'billing.automatedPlanUpdate'; /** @internal */ type BillingEventHandler = (event: BillingEvent) => any | Promise; -/** Handlers */ -/** Handle a plan update published */ +/** + * Declares a function that can handle a billing plan update event. + */ export function onPlanUpdatePublished( handler: BillingEventHandler ): CloudFunction>; @@ -59,7 +60,9 @@ export function onPlanUpdatePublished( ); } -/** Handle an automated plan update published */ +/** + * Declares a function that can handle an automated billing plan update event. + */ export function onAutomatedPlanUpdatePublished( handler: BillingEventHandler ): CloudFunction>; From 26c62e91f968256b4b0a4b0eeb02093735ea797b Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Mon, 24 Jan 2022 18:57:41 -0800 Subject: [PATCH 6/7] changing to BillingEventHandler type --- src/v2/providers/alerts/billing.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index f07f8dbbd..dfd1bbc5d 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -86,13 +86,11 @@ export function onAutomatedPlanUpdatePublished( /** @internal */ export function onOperation( alertType: string, - optsOrHandler: - | options.EventHandlerOptions - | ((event: BillingEvent) => any | Promise), - handler: (event: BillingEvent) => any | Promise + optsOrHandler: options.EventHandlerOptions | BillingEventHandler, + handler: BillingEventHandler ): CloudFunction> { if (typeof optsOrHandler === 'function') { - handler = optsOrHandler as (event: BillingEvent) => any | Promise; + handler = optsOrHandler as BillingEventHandler; optsOrHandler = {}; } From 71dda6c1c2fd854a53064aa060e31f175ab6a97e Mon Sep 17 00:00:00 2001 From: Cole Rogers Date: Thu, 27 Jan 2022 14:52:25 -0800 Subject: [PATCH 7/7] remove BillingEventHandler type --- src/v2/providers/alerts/billing.ts | 33 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/v2/providers/alerts/billing.ts b/src/v2/providers/alerts/billing.ts index dfd1bbc5d..f2ecd4289 100644 --- a/src/v2/providers/alerts/billing.ts +++ b/src/v2/providers/alerts/billing.ts @@ -34,24 +34,21 @@ export const planUpdateAlert = 'billing.planUpdate'; /** @internal */ export const automatedPlanUpdateAlert = 'billing.automatedPlanUpdate'; -/** @internal */ -type BillingEventHandler = (event: BillingEvent) => any | Promise; - /** * Declares a function that can handle a billing plan update event. */ export function onPlanUpdatePublished( - handler: BillingEventHandler + handler: (event: BillingEvent) => any | Promise ): CloudFunction>; export function onPlanUpdatePublished( opts: options.EventHandlerOptions, - handler: BillingEventHandler + handler: (event: BillingEvent) => any | Promise ): CloudFunction>; export function onPlanUpdatePublished( optsOrHandler: | options.EventHandlerOptions - | BillingEventHandler, - handler?: BillingEventHandler + | ((event: BillingEvent) => any | Promise), + handler?: (event: BillingEvent) => any | Promise ): CloudFunction> { return onOperation( planUpdateAlert, @@ -64,17 +61,23 @@ export function onPlanUpdatePublished( * Declares a function that can handle an automated billing plan update event. */ export function onAutomatedPlanUpdatePublished( - handler: BillingEventHandler + handler: ( + event: BillingEvent + ) => any | Promise ): CloudFunction>; export function onAutomatedPlanUpdatePublished( opts: options.EventHandlerOptions, - handler: BillingEventHandler + handler: ( + event: BillingEvent + ) => any | Promise ): CloudFunction>; export function onAutomatedPlanUpdatePublished( optsOrHandler: | options.EventHandlerOptions - | BillingEventHandler, - handler?: BillingEventHandler + | ((event: BillingEvent) => any | Promise), + handler?: ( + event: BillingEvent + ) => any | Promise ): CloudFunction> { return onOperation( automatedPlanUpdateAlert, @@ -86,11 +89,13 @@ export function onAutomatedPlanUpdatePublished( /** @internal */ export function onOperation( alertType: string, - optsOrHandler: options.EventHandlerOptions | BillingEventHandler, - handler: BillingEventHandler + optsOrHandler: + | options.EventHandlerOptions + | ((event: BillingEvent) => any | Promise), + handler: (event: BillingEvent) => any | Promise ): CloudFunction> { if (typeof optsOrHandler === 'function') { - handler = optsOrHandler as BillingEventHandler; + handler = optsOrHandler as (event: BillingEvent) => any | Promise; optsOrHandler = {}; }