firebase-functions 3.15.5 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/lib/bin/firebase-functions.d.ts +2 -0
  2. package/lib/bin/firebase-functions.js +48 -0
  3. package/lib/cloud-functions.d.ts +14 -8
  4. package/lib/cloud-functions.js +61 -1
  5. package/lib/common/debug.d.ts +1 -0
  6. package/lib/common/debug.js +54 -0
  7. package/lib/common/encoding.js +6 -0
  8. package/lib/common/manifest.d.ts +1 -0
  9. package/lib/common/manifest.js +2 -0
  10. package/lib/common/providers/https.d.ts +92 -47
  11. package/lib/common/providers/https.js +171 -51
  12. package/lib/common/providers/identity.d.ts +29 -0
  13. package/lib/common/providers/identity.js +96 -0
  14. package/lib/function-builder.d.ts +7 -1
  15. package/lib/function-builder.js +8 -0
  16. package/lib/function-configuration.d.ts +1 -0
  17. package/lib/handler-builder.d.ts +19 -15
  18. package/lib/handler-builder.js +32 -15
  19. package/lib/providers/auth.d.ts +2 -21
  20. package/lib/providers/auth.js +5 -66
  21. package/lib/providers/database.js +2 -1
  22. package/lib/providers/https.d.ts +44 -2
  23. package/lib/providers/https.js +65 -2
  24. package/lib/runtime/loader.d.ts +1 -0
  25. package/lib/runtime/loader.js +101 -0
  26. package/lib/runtime/manifest.d.ts +1 -0
  27. package/lib/runtime/manifest.js +2 -0
  28. package/lib/v2/core.d.ts +10 -3
  29. package/lib/v2/index.d.ts +3 -1
  30. package/lib/v2/index.js +5 -1
  31. package/lib/v2/options.d.ts +1 -1
  32. package/lib/v2/options.js +47 -9
  33. package/lib/v2/params/types.d.ts +2 -1
  34. package/lib/v2/params/types.js +2 -0
  35. package/lib/v2/providers/alerts/alerts.d.ts +36 -0
  36. package/lib/v2/providers/alerts/alerts.js +72 -0
  37. package/lib/v2/providers/alerts/appDistribution.d.ts +35 -0
  38. package/lib/v2/providers/alerts/appDistribution.js +39 -0
  39. package/lib/v2/providers/alerts/billing.d.ts +38 -0
  40. package/lib/v2/providers/alerts/billing.js +30 -0
  41. package/lib/v2/providers/alerts/crashlytics.d.ts +123 -0
  42. package/lib/v2/providers/alerts/crashlytics.js +74 -0
  43. package/lib/v2/providers/alerts/index.d.ts +5 -0
  44. package/lib/v2/providers/alerts/index.js +20 -0
  45. package/lib/v2/providers/https.d.ts +24 -4
  46. package/lib/v2/providers/https.js +72 -3
  47. package/lib/v2/providers/pubsub.d.ts +1 -1
  48. package/lib/v2/providers/pubsub.js +19 -4
  49. package/lib/v2/providers/storage.d.ts +170 -0
  50. package/lib/v2/providers/storage.js +137 -0
  51. package/package.json +34 -7
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const express = require("express");
5
+ const loader_1 = require("../runtime/loader");
6
+ function printUsageAndExit() {
7
+ console.error(`
8
+ Usage: firebase-functions [functionsDir]
9
+
10
+ Arguments:
11
+ - functionsDir: Directory containing source code for Firebase Functions.
12
+ `);
13
+ process.exit(1);
14
+ }
15
+ let functionsDir = '.';
16
+ const args = process.argv.slice(2);
17
+ if (args.length > 1) {
18
+ if (args[0] === '-h' || args[0] === '--help') {
19
+ printUsageAndExit();
20
+ }
21
+ functionsDir = args[0];
22
+ }
23
+ let server;
24
+ const app = express();
25
+ async function handleQuitquitquit(req, res) {
26
+ res.send('ok');
27
+ server.close(() => console.log('shutdown requested via /__/quitquitquit'));
28
+ }
29
+ app.get('/__/quitquitquit', handleQuitquitquit);
30
+ app.post('/__/quitquitquit', handleQuitquitquit);
31
+ app.get('/__/stack.yaml', async (req, res) => {
32
+ try {
33
+ const stack = await (0, loader_1.loadStack)(functionsDir);
34
+ res.setHeader('content-type', 'text/yaml');
35
+ res.send(JSON.stringify(stack));
36
+ }
37
+ catch (e) {
38
+ res
39
+ .status(400)
40
+ .send(`Failed to generate manifest from function source: ${e}`);
41
+ }
42
+ });
43
+ let port = 8080;
44
+ if (process.env.STACK_CONTROL_API_PORT) {
45
+ port = Number.parseInt(process.env.STACK_CONTROL_API_PORT);
46
+ }
47
+ console.log('Serving at port', port);
48
+ server = app.listen(port);
@@ -2,6 +2,7 @@ import { Request, Response } from 'express';
2
2
  import { DeploymentOptions, FailurePolicy, Schedule } from './function-configuration';
3
3
  export { Request, Response };
4
4
  import { Duration } from './common/encoding';
5
+ import { ManifestEndpoint, ManifestRequiredAPI } from './common/manifest';
5
6
  /**
6
7
  * @hidden
7
8
  *
@@ -200,6 +201,14 @@ export interface TriggerAnnotated {
200
201
  ingressSettings?: string;
201
202
  };
202
203
  }
204
+ /**
205
+ * @hidden
206
+ * EndpointAnnotated is used to generate the manifest that conforms to the container contract.
207
+ */
208
+ export interface EndpointAnnotated {
209
+ __endpoint: ManifestEndpoint;
210
+ __requiredAPIs?: ManifestRequiredAPI[];
211
+ }
203
212
  /**
204
213
  * A Runnable has a `run` method which directly invokes the user-defined
205
214
  * function - useful for unit testing.
@@ -216,7 +225,7 @@ export interface Runnable<T> {
216
225
  * [`Response`](https://expressjs.com/en/api.html#res) objects as its only
217
226
  * arguments.
218
227
  */
219
- export declare type HttpsFunction = TriggerAnnotated & ((req: Request, resp: Response) => void | Promise<void>);
228
+ export declare type HttpsFunction = TriggerAnnotated & EndpointAnnotated & ((req: Request, resp: Response) => void | Promise<void>);
220
229
  /**
221
230
  * The Cloud Function type for all non-HTTPS triggers. This should be exported
222
231
  * from your JavaScript file to define a Cloud Function.
@@ -224,7 +233,7 @@ export declare type HttpsFunction = TriggerAnnotated & ((req: Request, resp: Res
224
233
  * This type is a special JavaScript function which takes a templated
225
234
  * `Event` object as its only argument.
226
235
  */
227
- export declare type CloudFunction<T> = Runnable<T> & TriggerAnnotated & ((input: any, context?: any) => PromiseLike<any> | any);
236
+ export declare type CloudFunction<T> = Runnable<T> & TriggerAnnotated & EndpointAnnotated & ((input: any, context?: any) => PromiseLike<any> | any);
228
237
  /** @hidden */
229
238
  export interface MakeCloudFunctionArgs<EventData> {
230
239
  after?: (raw: Event) => void;
@@ -233,13 +242,9 @@ export interface MakeCloudFunctionArgs<EventData> {
233
242
  dataConstructor?: (raw: Event) => EventData;
234
243
  eventType: string;
235
244
  handler?: (data: EventData, context: EventContext) => PromiseLike<any> | any;
236
- labels?: {
237
- [key: string]: any;
238
- };
245
+ labels?: Record<string, string>;
239
246
  legacyEventType?: string;
240
- options?: {
241
- [key: string]: any;
242
- };
247
+ options?: DeploymentOptions;
243
248
  provider: string;
244
249
  service: string;
245
250
  triggerResource: () => string;
@@ -248,3 +253,4 @@ export interface MakeCloudFunctionArgs<EventData> {
248
253
  export declare function makeCloudFunction<EventData>({ after, before, contextOnlyHandler, dataConstructor, eventType, handler, labels, legacyEventType, options, provider, service, triggerResource, }: MakeCloudFunctionArgs<EventData>): CloudFunction<EventData>;
249
254
  /** @hidden */
250
255
  export declare function optionsToTrigger(options: DeploymentOptions): any;
256
+ export declare function optionsToEndpoint(options: DeploymentOptions): ManifestEndpoint;
@@ -21,7 +21,7 @@
21
21
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
22
  // SOFTWARE.
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.optionsToTrigger = exports.makeCloudFunction = exports.Change = void 0;
24
+ exports.optionsToEndpoint = exports.optionsToTrigger = exports.makeCloudFunction = exports.Change = void 0;
25
25
  const _ = require("lodash");
26
26
  const function_configuration_1 = require("./function-configuration");
27
27
  const logger_1 = require("./logger");
@@ -165,6 +165,42 @@ function makeCloudFunction({ after = () => { }, before = () => { }, contextOnlyH
165
165
  return trigger;
166
166
  },
167
167
  });
168
+ Object.defineProperty(cloudFunction, '__endpoint', {
169
+ get: () => {
170
+ if (triggerResource() == null) {
171
+ return undefined;
172
+ }
173
+ const endpoint = {
174
+ platform: 'gcfv1',
175
+ ...optionsToEndpoint(options),
176
+ };
177
+ if (options.schedule) {
178
+ endpoint.scheduleTrigger = options.schedule;
179
+ }
180
+ else {
181
+ endpoint.eventTrigger = {
182
+ eventType: legacyEventType || provider + '.' + eventType,
183
+ eventFilters: {
184
+ resource: triggerResource(),
185
+ },
186
+ retry: !!options.failurePolicy,
187
+ };
188
+ }
189
+ // Note: We intentionally don't make use of labels args here.
190
+ // labels is used to pass SDK-defined labels to the trigger, which isn't
191
+ // something we will do in the container contract world.
192
+ endpoint.labels = { ...endpoint.labels };
193
+ return endpoint;
194
+ },
195
+ });
196
+ if (options.schedule) {
197
+ cloudFunction.__requiredAPIs = [
198
+ {
199
+ api: 'cloudscheduler.googleapis.com',
200
+ reason: 'Needed for scheduled functions.',
201
+ },
202
+ ];
203
+ }
168
204
  cloudFunction.run = handler || contextOnlyHandler;
169
205
  return cloudFunction;
170
206
  }
@@ -245,3 +281,27 @@ function optionsToTrigger(options) {
245
281
  return trigger;
246
282
  }
247
283
  exports.optionsToTrigger = optionsToTrigger;
284
+ function optionsToEndpoint(options) {
285
+ const endpoint = {};
286
+ (0, encoding_1.copyIfPresent)(endpoint, options, 'minInstances', 'maxInstances', 'ingressSettings', 'labels', 'timeoutSeconds');
287
+ (0, encoding_1.convertIfPresent)(endpoint, options, 'region', 'regions');
288
+ (0, encoding_1.convertIfPresent)(endpoint, options, 'serviceAccountEmail', 'serviceAccount', (sa) => sa);
289
+ if (options === null || options === void 0 ? void 0 : options.vpcConnector) {
290
+ endpoint.vpc = { connector: options.vpcConnector };
291
+ (0, encoding_1.convertIfPresent)(endpoint.vpc, options, 'egressSettings', 'vpcConnectorEgressSettings');
292
+ }
293
+ (0, encoding_1.convertIfPresent)(endpoint, options, 'availableMemoryMb', 'memory', (mem) => {
294
+ const memoryLookup = {
295
+ '128MB': 128,
296
+ '256MB': 256,
297
+ '512MB': 512,
298
+ '1GB': 1024,
299
+ '2GB': 2048,
300
+ '4GB': 4096,
301
+ '8GB': 8192,
302
+ };
303
+ return memoryLookup[mem];
304
+ });
305
+ return endpoint;
306
+ }
307
+ exports.optionsToEndpoint = optionsToEndpoint;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ // The MIT License (MIT)
3
+ //
4
+ // Copyright (c) 2021 Firebase
5
+ //
6
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ // of this software and associated documentation files (the "Software"), to deal
8
+ // in the Software without restriction, including without limitation the rights
9
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ // copies of the Software, and to permit persons to whom the Software is
11
+ // furnished to do so, subject to the following conditions:
12
+ //
13
+ // The above copyright notice and this permission notice shall be included in all
14
+ // copies or substantial portions of the Software.
15
+ //
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ // SOFTWARE.
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.isDebugFeatureEnabled = exports.debugFeatureValue = void 0;
25
+ // Do NOT turn on a debug feature in production.
26
+ const debugMode = process.env.FIREBASE_DEBUG_MODE === 'true';
27
+ function loadDebugFeatures() {
28
+ if (!debugMode) {
29
+ return {};
30
+ }
31
+ try {
32
+ const obj = JSON.parse(process.env.FIREBASE_DEBUG_FEATURES);
33
+ if (typeof obj !== 'object') {
34
+ return {};
35
+ }
36
+ return obj;
37
+ }
38
+ catch (e) {
39
+ return {};
40
+ }
41
+ }
42
+ /* @internal */
43
+ function debugFeatureValue(feat) {
44
+ if (!debugMode) {
45
+ return;
46
+ }
47
+ return loadDebugFeatures()[feat];
48
+ }
49
+ exports.debugFeatureValue = debugFeatureValue;
50
+ /* @internal */
51
+ function isDebugFeatureEnabled(feat) {
52
+ return debugMode && !!debugFeatureValue(feat);
53
+ }
54
+ exports.isDebugFeatureEnabled = isDebugFeatureEnabled;
@@ -13,6 +13,9 @@ exports.durationFromSeconds = durationFromSeconds;
13
13
  * in A and B, but cannot verify that both Src and Dest have the same type for the same field.
14
14
  */
15
15
  function copyIfPresent(dest, src, ...fields) {
16
+ if (!src) {
17
+ return;
18
+ }
16
19
  for (const field of fields) {
17
20
  if (!Object.prototype.hasOwnProperty.call(src, field)) {
18
21
  continue;
@@ -24,6 +27,9 @@ exports.copyIfPresent = copyIfPresent;
24
27
  function convertIfPresent(dest, src, destField, srcField, converter = (from) => {
25
28
  return from;
26
29
  }) {
30
+ if (!src) {
31
+ return;
32
+ }
27
33
  if (!Object.prototype.hasOwnProperty.call(src, srcField)) {
28
34
  return;
29
35
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,58 +1,58 @@
1
1
  /// <reference types="node" />
2
- import * as cors from 'cors';
3
2
  import * as express from 'express';
4
3
  import * as firebase from 'firebase-admin';
5
4
  /** @hidden */
6
5
  export interface Request extends express.Request {
7
6
  rawBody: Buffer;
8
7
  }
8
+ interface DecodedAppCheckToken {
9
+ /**
10
+ * The issuer identifier for the issuer of the response.
11
+ *
12
+ * This value is a URL with the format
13
+ * `https://firebaseappcheck.googleapis.com/<PROJECT_NUMBER>`, where `<PROJECT_NUMBER>` is the
14
+ * same project number specified in the [`aud`](#aud) property.
15
+ */
16
+ iss: string;
17
+ /**
18
+ * The Firebase App ID corresponding to the app the token belonged to.
19
+ *
20
+ * As a convenience, this value is copied over to the [`app_id`](#app_id) property.
21
+ */
22
+ sub: string;
23
+ /**
24
+ * The audience for which this token is intended.
25
+ *
26
+ * This value is a JSON array of two strings, the first is the project number of your
27
+ * Firebase project, and the second is the project ID of the same project.
28
+ */
29
+ aud: string[];
30
+ /**
31
+ * The App Check token's expiration time, in seconds since the Unix epoch. That is, the
32
+ * time at which this App Check token expires and should no longer be considered valid.
33
+ */
34
+ exp: number;
35
+ /**
36
+ * The App Check token's issued-at time, in seconds since the Unix epoch. That is, the
37
+ * time at which this App Check token was issued and should start to be considered
38
+ * valid.;
39
+ */
40
+ iat: number;
41
+ /**
42
+ * The App ID corresponding to the App the App Check token belonged to.
43
+ *
44
+ * This value is not actually one of the JWT token claims. It is added as a
45
+ * convenience, and is set as the value of the [`sub`](#sub) property.
46
+ */
47
+ app_id: string;
48
+ [key: string]: any;
49
+ }
9
50
  /**
10
51
  * The interface for AppCheck tokens verified in Callable functions
11
52
  */
12
53
  export interface AppCheckData {
13
54
  appId: string;
14
- token: {
15
- /**
16
- * The issuer identifier for the issuer of the response.
17
- *
18
- * This value is a URL with the format
19
- * `https://firebaseappcheck.googleapis.com/<PROJECT_NUMBER>`, where `<PROJECT_NUMBER>` is the
20
- * same project number specified in the [`aud`](#aud) property.
21
- */
22
- iss: string;
23
- /**
24
- * The Firebase App ID corresponding to the app the token belonged to.
25
- *
26
- * As a convenience, this value is copied over to the [`app_id`](#app_id) property.
27
- */
28
- sub: string;
29
- /**
30
- * The audience for which this token is intended.
31
- *
32
- * This value is a JSON array of two strings, the first is the project number of your
33
- * Firebase project, and the second is the project ID of the same project.
34
- */
35
- aud: string[];
36
- /**
37
- * The App Check token's expiration time, in seconds since the Unix epoch. That is, the
38
- * time at which this App Check token expires and should no longer be considered valid.
39
- */
40
- exp: number;
41
- /**
42
- * The App Check token's issued-at time, in seconds since the Unix epoch. That is, the
43
- * time at which this App Check token was issued and should start to be considered
44
- * valid.
45
- */
46
- iat: number;
47
- /**
48
- * The App ID corresponding to the App the App Check token belonged to.
49
- *
50
- * This value is not actually one of the JWT token claims. It is added as a
51
- * convenience, and is set as the value of the [`sub`](#sub) property.
52
- */
53
- app_id: string;
54
- [key: string]: any;
55
- };
55
+ token: DecodedAppCheckToken;
56
56
  }
57
57
  /**
58
58
  * The interface for Auth tokens verified in Callable functions
@@ -107,6 +107,55 @@ export interface CallableRequest<T = any> {
107
107
  */
108
108
  rawRequest: Request;
109
109
  }
110
+ /** How a task should be retried in the event of a non-2xx return. */
111
+ export interface TaskRetryConfig {
112
+ /**
113
+ * Maximum number of times a request should be attempted.
114
+ * If left unspecified, will default to 3.
115
+ */
116
+ maxAttempts?: number;
117
+ /**
118
+ * The maximum amount of time to wait between attempts.
119
+ * If left unspecified will default to 1hr.
120
+ */
121
+ maxBackoffSeconds?: number;
122
+ /**
123
+ * The maximum number of times to double the backoff between
124
+ * retries. If left unspecified will default to 16.
125
+ */
126
+ maxDoublings?: number;
127
+ /**
128
+ * The minimum time to wait between attempts. If left unspecified
129
+ * will default to 100ms.
130
+ */
131
+ minBackoffSeconds?: number;
132
+ }
133
+ /** How congestion control should be applied to the function. */
134
+ export interface TaskRateLimits {
135
+ maxBurstSize?: number;
136
+ maxConcurrentDispatches?: number;
137
+ maxDispatchesPerSecond?: number;
138
+ }
139
+ /** Metadata about a call to a Task Queue function. */
140
+ export interface TaskContext {
141
+ /**
142
+ * The result of decoding and verifying an ODIC token.
143
+ */
144
+ auth?: AuthData;
145
+ }
146
+ /**
147
+ * The request used to call a Task Queue function.
148
+ */
149
+ export interface TaskRequest<T = any> {
150
+ /**
151
+ * The parameters used by a client when calling this function.
152
+ */
153
+ data: T;
154
+ /**
155
+ * The result of decoding and verifying an ODIC token.
156
+ */
157
+ auth?: AuthData;
158
+ }
110
159
  /**
111
160
  * The set of Firebase Functions status codes. The codes are the same at the
112
161
  * ones exposed by gRPC here:
@@ -195,8 +244,4 @@ export declare function encode(data: any): any;
195
244
  */
196
245
  /** @hidden */
197
246
  export declare function decode(data: any): any;
198
- declare type v1Handler = (data: any, context: CallableContext) => any | Promise<any>;
199
- declare type v2Handler<Req, Res> = (request: CallableRequest<Req>) => Res;
200
- /** @hidden */
201
- export declare function onCallHandler<Req = any, Res = any>(options: cors.CorsOptions, handler: v1Handler | v2Handler<Req, Res>): (req: Request, res: express.Response) => Promise<void>;
202
247
  export {};