Skip to content

Commit 42d37bf

Browse files
committed
Merge branch 'master' of https://github.com/firebase/firebase-functions into launch.next
2 parents 77f905e + cf27ac6 commit 42d37bf

File tree

13 files changed

+486
-16
lines changed

13 files changed

+486
-16
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/runtime/manifest.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { stackToWire, ManifestStack } from "../../src/runtime/manifest";
21
import { expect } from "chai";
2+
import { stackToWire, ManifestStack } from "../../src/runtime/manifest";
33
import * as params from "../../src/params";
44

55
describe("stackToWire", () => {

spec/v2/providers/alerts/alerts.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { expect } from "chai";
2+
import { CloudEvent } from "../../../../src/v2";
23
import * as options from "../../../../src/v2/options";
34
import * as alerts from "../../../../src/v2/providers/alerts";
45
import { FULL_ENDPOINT, FULL_OPTIONS } from "../fixtures";
@@ -166,4 +167,41 @@ describe("alerts", () => {
166167
expect(appId).to.be.equal(myOpts.appId);
167168
});
168169
});
170+
171+
describe('convertAlertAndApp', () => {
172+
const event: CloudEvent<string> = {
173+
specversion: '1.0',
174+
id: 'id',
175+
source: 'source',
176+
type: 'type',
177+
time: 'now',
178+
data: 'data',
179+
};
180+
181+
it('should leave event unchanged if alerttype & appid are missing', () => {
182+
const raw = { ...event };
183+
184+
const converted = alerts.convertAlertAndApp(raw);
185+
186+
expect(raw).to.deep.eq(converted);
187+
});
188+
189+
it('should convert alerttype & appid when present', () => {
190+
const raw = {
191+
...event,
192+
alerttype: 'my-alert',
193+
appid: 'my-app',
194+
};
195+
196+
const converted = alerts.convertAlertAndApp(raw);
197+
198+
expect(converted).to.deep.eq({
199+
...event,
200+
alerttype: 'my-alert',
201+
appid: 'my-app',
202+
alertType: 'my-alert',
203+
appId: 'my-app',
204+
});
205+
});
206+
});
169207
});
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { expect } from 'chai';
2+
import * as alerts from '../../../../src/v2/providers/alerts';
3+
import * as performance from '../../../../src/v2/providers/alerts/performance';
4+
import { FULL_ENDPOINT, FULL_OPTIONS } from '../fixtures';
5+
6+
const APPID = '123456789';
7+
const myHandler = () => 42;
8+
9+
const APP_EVENT_FILTER = {
10+
appid: APPID,
11+
};
12+
13+
describe('performance', () => {
14+
describe('onThresholdAlertPublished', () => {
15+
it('should create a function with alertType & appId', () => {
16+
const func = performance.onThresholdAlertPublished(APPID, myHandler);
17+
18+
expect(func.__endpoint).to.deep.equal({
19+
platform: 'gcfv2',
20+
labels: {},
21+
eventTrigger: {
22+
eventType: alerts.eventType,
23+
eventFilters: {
24+
...APP_EVENT_FILTER,
25+
alerttype: performance.thresholdAlert,
26+
},
27+
retry: false,
28+
},
29+
});
30+
});
31+
32+
it('should create a function with opts', () => {
33+
const func = performance.onThresholdAlertPublished(
34+
{ ...FULL_OPTIONS },
35+
myHandler
36+
);
37+
38+
expect(func.__endpoint).to.deep.equal({
39+
...FULL_ENDPOINT,
40+
eventTrigger: {
41+
eventType: alerts.eventType,
42+
eventFilters: {
43+
alerttype: performance.thresholdAlert,
44+
},
45+
retry: false,
46+
},
47+
});
48+
});
49+
50+
it('should create a function with appid in opts', () => {
51+
const func = performance.onThresholdAlertPublished(
52+
{ ...FULL_OPTIONS, appId: APPID },
53+
myHandler
54+
);
55+
56+
expect(func.__endpoint).to.deep.equal({
57+
...FULL_ENDPOINT,
58+
eventTrigger: {
59+
eventType: alerts.eventType,
60+
eventFilters: {
61+
...APP_EVENT_FILTER,
62+
alerttype: performance.thresholdAlert,
63+
},
64+
retry: false,
65+
},
66+
});
67+
});
68+
69+
it('should create a function without opts or appId', () => {
70+
const func = performance.onThresholdAlertPublished(myHandler);
71+
72+
expect(func.__endpoint).to.deep.equal({
73+
platform: 'gcfv2',
74+
labels: {},
75+
eventTrigger: {
76+
eventType: alerts.eventType,
77+
eventFilters: {
78+
alerttype: performance.thresholdAlert,
79+
},
80+
retry: false,
81+
},
82+
});
83+
});
84+
85+
it('should create a function with a run method', () => {
86+
const func = performance.onThresholdAlertPublished(
87+
APPID,
88+
(event) => event
89+
);
90+
91+
const res = func.run('input' as any);
92+
93+
expect(res).to.equal('input');
94+
});
95+
});
96+
97+
describe('getOptsAndApp', () => {
98+
it('should parse a string', () => {
99+
const [opts, appId] = performance.getOptsAndApp(APPID);
100+
101+
expect(opts).to.deep.equal({});
102+
expect(appId).to.equal(APPID);
103+
});
104+
105+
it('should parse an options object without appId', () => {
106+
const myOpts: performance.PerformanceOptions = {
107+
region: 'us-west1',
108+
};
109+
110+
const [opts, appId] = performance.getOptsAndApp(myOpts);
111+
112+
expect(opts).to.deep.equal({ region: 'us-west1' });
113+
expect(appId).to.be.undefined;
114+
});
115+
116+
it('should parse an options object with appId', () => {
117+
const myOpts: performance.PerformanceOptions = {
118+
appId: APPID,
119+
region: 'us-west1',
120+
};
121+
122+
const [opts, appId] = performance.getOptsAndApp(myOpts);
123+
124+
expect(opts).to.deep.equal({ region: 'us-west1' });
125+
expect(appId).to.equal(APPID);
126+
});
127+
});
128+
129+
describe('convertPayload', () => {
130+
it('should return the same payload', () => {
131+
const payload = {
132+
a: 'b',
133+
conditionPercentile: 23,
134+
appVersion: '3',
135+
};
136+
137+
const convertedPayload = performance.convertPayload(payload as any);
138+
139+
expect(convertedPayload).to.deep.eq(payload);
140+
});
141+
142+
it('should return the same payload if the fields are undefined', () => {
143+
const payload = {
144+
a: 'b',
145+
};
146+
147+
const convertedPayload = performance.convertPayload(payload as any);
148+
149+
expect(convertedPayload).to.deep.eq({
150+
a: 'b',
151+
});
152+
});
153+
154+
it('should remove fields', () => {
155+
const payload = {
156+
a: 'b',
157+
conditionPercentile: 0,
158+
appVersion: '',
159+
};
160+
161+
const convertedPayload = performance.convertPayload(payload as any);
162+
163+
expect(convertedPayload).to.deep.eq({
164+
a: 'b',
165+
});
166+
});
167+
});
168+
});

src/params/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727

2828
import {
2929
BooleanParam,
30+
Expression,
3031
FloatParam,
3132
IntParam,
3233
ListParam,
3334
Param,
3435
ParamOptions,
35-
StringParam,
3636
SecretParam,
37-
Expression,
37+
StringParam,
3838
} from "./types";
3939

4040
export { ParamOptions, Expression };

src/params/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ export interface SelectOptions<T = unknown> {
179179
value: T;
180180
}
181181

182-
export type ParamSpec<T extends string | number | boolean | string[]> = {
182+
export interface ParamSpec<T = unknown> {
183183
name: string;
184184
default?: T | Expression<T>;
185185
label?: string;
186186
description?: string;
187187
type: ParamValueType;
188188
input?: ParamInput<T>;
189-
};
189+
}
190190

191191
// N.B: a WireParamSpec is just a ParamSpec with default expressions converted into a CEL literal
192192
export type WireParamSpec<T extends string | number | boolean | string[]> = {
@@ -266,8 +266,8 @@ export abstract class Param<T extends string | number | boolean | string[]> exte
266266
}
267267

268268
export class SecretParam {
269-
name: string;
270269
static type: ParamValueType = "secret";
270+
name: string;
271271

272272
constructor(name: string) {
273273
this.name = name;

src/v2/providers/alerts/alerts.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export type AlertType =
7171
| "billing.automatedPlanUpdate"
7272
| "appDistribution.newTesterIosDevice"
7373
| "appDistribution.inAppFeedback"
74+
| "performance.threshold"
7475
| string;
7576

7677
/**
@@ -207,7 +208,7 @@ export function onAlertPublished<T extends { ["@type"]: string } = any>(
207208
const [opts, alertType, appId] = getOptsAndAlertTypeAndApp(alertTypeOrOpts);
208209

209210
const func = (raw: CloudEvent<unknown>) => {
210-
return wrapTraceContext(handler)(raw as AlertEvent<T>);
211+
return wrapTraceContext(handler(convertAlertAndApp(raw) as AlertEvent<T>));
211212
};
212213

213214
func.run = handler;
@@ -271,3 +272,22 @@ export function getOptsAndAlertTypeAndApp(
271272
}
272273
return [opts, alertType, appId];
273274
}
275+
276+
/**
277+
* Helper function to covert alert type & app id in the CloudEvent to camel case.
278+
* @internal
279+
*/
280+
export function convertAlertAndApp(
281+
raw: CloudEvent<unknown>
282+
): CloudEvent<unknown> {
283+
const event = { ...raw };
284+
285+
if ('alerttype' in event) {
286+
(event as any).alertType = (event as any).alerttype;
287+
}
288+
if ('appid' in event) {
289+
(event as any).appId = (event as any).appid;
290+
}
291+
292+
return event;
293+
}

src/v2/providers/alerts/appDistribution.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727

2828
import { CloudEvent, CloudFunction } from "../../core";
2929
import * as options from "../../options";
30+
import { Expression } from "../../params";
3031
import { wrapTraceContext } from "../../trace";
31-
import { FirebaseAlertData, getEndpointAnnotation } from "./alerts";
32+
import { convertAlertAndApp, FirebaseAlertData, getEndpointAnnotation } from "./alerts";
3233
import { Expression } from "../../../params";
3334

3435
/**
@@ -243,7 +244,9 @@ export function onNewTesterIosDevicePublished(
243244
const [opts, appId] = getOptsAndApp(appIdOrOptsOrHandler);
244245

245246
const func = (raw: CloudEvent<unknown>) => {
246-
return handler(raw as AppDistributionEvent<NewTesterDevicePayload>);
247+
return handler(
248+
convertAlertAndApp(raw) as AppDistributionEvent<NewTesterDevicePayload>
249+
);
247250
};
248251

249252
func.run = handler;
@@ -306,7 +309,9 @@ export function onInAppFeedbackPublished(
306309
const [opts, appId] = getOptsAndApp(appIdOrOptsOrHandler);
307310

308311
const func = (raw: CloudEvent<unknown>) => {
309-
return wrapTraceContext(handler)(raw as AppDistributionEvent<InAppFeedbackPayload>);
312+
return wrapTraceContext(handler(
313+
convertAlertAndApp(raw) as AppDistributionEvent<InAppFeedbackPayload>
314+
));
310315
};
311316

312317
func.run = handler;

src/v2/providers/alerts/billing.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
import { FirebaseAlertData, getEndpointAnnotation } from ".";
2929
import { CloudEvent, CloudFunction } from "../../core";
3030
import { wrapTraceContext } from "../../trace";
31+
import {
32+
convertAlertAndApp,
33+
FirebaseAlertData,
34+
getEndpointAnnotation,
35+
} from "./alerts";
3136
import * as options from "../../options";
3237

3338
/**
@@ -152,7 +157,7 @@ export function onOperation<T>(
152157
}
153158

154159
const func = (raw: CloudEvent<unknown>) => {
155-
return wrapTraceContext(handler)(raw as BillingEvent<T>);
160+
return wrapTraceContext(handler(convertAlertAndApp(raw) as BillingEvent<T>));
156161
};
157162

158163
func.run = handler;

0 commit comments

Comments
 (0)