firebase-functions 4.4.1 → 4.6.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.
- package/lib/bin/firebase-functions.js +2 -1
- package/lib/common/change.d.ts +5 -5
- package/lib/common/change.js +4 -4
- package/lib/common/providers/identity.d.ts +18 -11
- package/lib/common/providers/identity.js +37 -21
- package/lib/common/providers/tasks.d.ts +50 -7
- package/lib/common/providers/tasks.js +22 -1
- package/lib/v1/function-configuration.d.ts +6 -5
- package/lib/v2/core.d.ts +8 -8
- package/lib/v2/core.js +1 -1
- package/lib/v2/index.d.ts +4 -4
- package/lib/v2/index.js +4 -4
- package/lib/v2/options.d.ts +24 -21
- package/lib/v2/options.js +1 -1
- package/lib/v2/providers/firestore.js +2 -1
- package/lib/v2/providers/https.js +7 -3
- package/lib/v2/providers/tasks.js +2 -0
- package/package.json +3 -3
|
@@ -46,7 +46,7 @@ let server = undefined;
|
|
|
46
46
|
const app = express();
|
|
47
47
|
function handleQuitquitquit(req, res) {
|
|
48
48
|
res.send("ok");
|
|
49
|
-
server.close(
|
|
49
|
+
server.close();
|
|
50
50
|
}
|
|
51
51
|
app.get("/__/quitquitquit", handleQuitquitquit);
|
|
52
52
|
app.post("/__/quitquitquit", handleQuitquitquit);
|
|
@@ -58,6 +58,7 @@ if (process.env.FUNCTIONS_CONTROL_API === "true") {
|
|
|
58
58
|
res.send(JSON.stringify((0, manifest_1.stackToWire)(stack)));
|
|
59
59
|
}
|
|
60
60
|
catch (e) {
|
|
61
|
+
console.error(e);
|
|
61
62
|
res.status(400).send(`Failed to generate manifest from function source: ${e}`);
|
|
62
63
|
}
|
|
63
64
|
});
|
package/lib/common/change.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ChangeJson` is the JSON format used to construct a Change object.
|
|
2
|
+
* `ChangeJson` is the JSON format used to construct a `Change` object.
|
|
3
3
|
*/
|
|
4
4
|
export interface ChangeJson {
|
|
5
5
|
/**
|
|
@@ -17,8 +17,8 @@ export interface ChangeJson {
|
|
|
17
17
|
fieldMask?: string;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* The Functions interface for events that change state, such as
|
|
21
|
-
* Realtime Database or Cloud Firestore `onWrite` and `onUpdate
|
|
20
|
+
* The Cloud Functions interface for events that change state, such as
|
|
21
|
+
* Realtime Database or Cloud Firestore `onWrite` and `onUpdate` events.
|
|
22
22
|
*
|
|
23
23
|
* For more information about the format used to construct `Change` objects, see
|
|
24
24
|
* {@link ChangeJson} below.
|
|
@@ -28,12 +28,12 @@ export declare class Change<T> {
|
|
|
28
28
|
before: T;
|
|
29
29
|
after: T;
|
|
30
30
|
/**
|
|
31
|
-
* Factory method for creating a Change from a `before` object and an `after`
|
|
31
|
+
* Factory method for creating a `Change` from a `before` object and an `after`
|
|
32
32
|
* object.
|
|
33
33
|
*/
|
|
34
34
|
static fromObjects<T>(before: T, after: T): Change<T>;
|
|
35
35
|
/**
|
|
36
|
-
* Factory method for creating a Change from
|
|
36
|
+
* Factory method for creating a `Change` from JSON and an optional customizer
|
|
37
37
|
* function to be applied to both the `before` and the `after` fields.
|
|
38
38
|
*/
|
|
39
39
|
static fromJSON<T>(json: ChangeJson, customizer?: (x: any) => T): Change<T>;
|
package/lib/common/change.js
CHANGED
|
@@ -46,8 +46,8 @@ function applyFieldMask(sparseBefore, after, fieldMask) {
|
|
|
46
46
|
}
|
|
47
47
|
exports.applyFieldMask = applyFieldMask;
|
|
48
48
|
/**
|
|
49
|
-
* The Functions interface for events that change state, such as
|
|
50
|
-
* Realtime Database or Cloud Firestore `onWrite` and `onUpdate
|
|
49
|
+
* The Cloud Functions interface for events that change state, such as
|
|
50
|
+
* Realtime Database or Cloud Firestore `onWrite` and `onUpdate` events.
|
|
51
51
|
*
|
|
52
52
|
* For more information about the format used to construct `Change` objects, see
|
|
53
53
|
* {@link ChangeJson} below.
|
|
@@ -55,14 +55,14 @@ exports.applyFieldMask = applyFieldMask;
|
|
|
55
55
|
*/
|
|
56
56
|
class Change {
|
|
57
57
|
/**
|
|
58
|
-
* Factory method for creating a Change from a `before` object and an `after`
|
|
58
|
+
* Factory method for creating a `Change` from a `before` object and an `after`
|
|
59
59
|
* object.
|
|
60
60
|
*/
|
|
61
61
|
static fromObjects(before, after) {
|
|
62
62
|
return new Change(before, after);
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* Factory method for creating a Change from
|
|
65
|
+
* Factory method for creating a `Change` from JSON and an optional customizer
|
|
66
66
|
* function to be applied to both the `before` and the `after` fields.
|
|
67
67
|
*/
|
|
68
68
|
static fromJSON(json, customizer = (x) => x) {
|
|
@@ -9,16 +9,17 @@ export { HttpsError };
|
|
|
9
9
|
*/
|
|
10
10
|
export type AuthBlockingEventType = "beforeCreate" | "beforeSignIn";
|
|
11
11
|
/**
|
|
12
|
-
* The UserRecord passed to Cloud Functions is the same
|
|
13
|
-
*
|
|
12
|
+
* The `UserRecord` passed to Cloud Functions is the same
|
|
13
|
+
* {@link https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth.userrecord | UserRecord}
|
|
14
|
+
* that is returned by the Firebase Admin SDK.
|
|
14
15
|
*/
|
|
15
16
|
export type UserRecord = auth.UserRecord;
|
|
16
17
|
/**
|
|
17
|
-
* UserInfo that is part of the UserRecord
|
|
18
|
+
* `UserInfo` that is part of the `UserRecord`.
|
|
18
19
|
*/
|
|
19
20
|
export type UserInfo = auth.UserInfo;
|
|
20
21
|
/**
|
|
21
|
-
* Helper class to create the user metadata in a UserRecord object
|
|
22
|
+
* Helper class to create the user metadata in a `UserRecord` object.
|
|
22
23
|
*/
|
|
23
24
|
export declare class UserRecordMetadata implements auth.UserMetadata {
|
|
24
25
|
creationTime: string;
|
|
@@ -28,13 +29,13 @@ export declare class UserRecordMetadata implements auth.UserMetadata {
|
|
|
28
29
|
toJSON(): AuthUserMetadata;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
|
-
* Helper function that creates a UserRecord
|
|
32
|
+
* Helper function that creates a `UserRecord` class from data sent over the wire.
|
|
32
33
|
* @param wireData data sent over the wire
|
|
33
|
-
* @returns an instance of UserRecord with correct toJSON functions
|
|
34
|
+
* @returns an instance of `UserRecord` with correct toJSON functions
|
|
34
35
|
*/
|
|
35
36
|
export declare function userRecordConstructor(wireData: Record<string, unknown>): UserRecord;
|
|
36
37
|
/**
|
|
37
|
-
* User info that is part of the AuthUserRecord
|
|
38
|
+
* User info that is part of the `AuthUserRecord`.
|
|
38
39
|
*/
|
|
39
40
|
export interface AuthUserInfo {
|
|
40
41
|
/**
|
|
@@ -110,7 +111,7 @@ export interface AuthMultiFactorSettings {
|
|
|
110
111
|
enrolledFactors: AuthMultiFactorInfo[];
|
|
111
112
|
}
|
|
112
113
|
/**
|
|
113
|
-
* The UserRecord passed to auth blocking
|
|
114
|
+
* The `UserRecord` passed to auth blocking functions from the identity platform.
|
|
114
115
|
*/
|
|
115
116
|
export interface AuthUserRecord {
|
|
116
117
|
/**
|
|
@@ -182,6 +183,7 @@ export interface AdditionalUserInfo {
|
|
|
182
183
|
profile?: any;
|
|
183
184
|
username?: string;
|
|
184
185
|
isNewUser: boolean;
|
|
186
|
+
recaptchaScore?: number;
|
|
185
187
|
}
|
|
186
188
|
/** The credential component of the auth event context */
|
|
187
189
|
export interface Credential {
|
|
@@ -204,19 +206,24 @@ export interface AuthEventContext extends EventContext {
|
|
|
204
206
|
additionalUserInfo?: AdditionalUserInfo;
|
|
205
207
|
credential?: Credential;
|
|
206
208
|
}
|
|
207
|
-
/** Defines the auth event for
|
|
209
|
+
/** Defines the auth event for 2nd gen blocking events */
|
|
208
210
|
export interface AuthBlockingEvent extends AuthEventContext {
|
|
209
211
|
data: AuthUserRecord;
|
|
210
212
|
}
|
|
211
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* The reCAPTCHA action options.
|
|
215
|
+
*/
|
|
216
|
+
export type RecaptchaActionOptions = "ALLOW" | "BLOCK";
|
|
217
|
+
/** The handler response type for `beforeCreate` blocking events */
|
|
212
218
|
export interface BeforeCreateResponse {
|
|
213
219
|
displayName?: string;
|
|
214
220
|
disabled?: boolean;
|
|
215
221
|
emailVerified?: boolean;
|
|
216
222
|
photoURL?: string;
|
|
217
223
|
customClaims?: object;
|
|
224
|
+
recaptchaActionOverride?: RecaptchaActionOptions;
|
|
218
225
|
}
|
|
219
|
-
/** The handler response type for beforeSignIn blocking events */
|
|
226
|
+
/** The handler response type for `beforeSignIn` blocking events */
|
|
220
227
|
export interface BeforeSignInResponse extends BeforeCreateResponse {
|
|
221
228
|
sessionClaims?: object;
|
|
222
229
|
}
|
|
@@ -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.wrapHandler = exports.getUpdateMask = exports.validateAuthResponse = exports.parseAuthEventContext = exports.parseAuthUserRecord = exports.parseMultiFactor = exports.parseDate = exports.parseProviderData = exports.parseMetadata = exports.isValidRequest = exports.userRecordConstructor = exports.UserRecordMetadata = exports.HttpsError = void 0;
|
|
24
|
+
exports.wrapHandler = exports.getUpdateMask = exports.validateAuthResponse = exports.parseAuthEventContext = exports.generateResponsePayload = exports.parseAuthUserRecord = exports.parseMultiFactor = exports.parseDate = exports.parseProviderData = exports.parseMetadata = exports.isValidRequest = exports.userRecordConstructor = exports.UserRecordMetadata = exports.HttpsError = void 0;
|
|
25
25
|
const auth = require("firebase-admin/auth");
|
|
26
26
|
const logger = require("../../logger");
|
|
27
27
|
const app_1 = require("../app");
|
|
@@ -51,7 +51,7 @@ const EVENT_MAPPING = {
|
|
|
51
51
|
beforeSignIn: "providers/cloud.auth/eventTypes/user.beforeSignIn",
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
|
-
* Helper class to create the user metadata in a UserRecord object
|
|
54
|
+
* Helper class to create the user metadata in a `UserRecord` object.
|
|
55
55
|
*/
|
|
56
56
|
class UserRecordMetadata {
|
|
57
57
|
constructor(creationTime, lastSignInTime) {
|
|
@@ -68,9 +68,9 @@ class UserRecordMetadata {
|
|
|
68
68
|
}
|
|
69
69
|
exports.UserRecordMetadata = UserRecordMetadata;
|
|
70
70
|
/**
|
|
71
|
-
* Helper function that creates a UserRecord
|
|
71
|
+
* Helper function that creates a `UserRecord` class from data sent over the wire.
|
|
72
72
|
* @param wireData data sent over the wire
|
|
73
|
-
* @returns an instance of UserRecord with correct toJSON functions
|
|
73
|
+
* @returns an instance of `UserRecord` with correct toJSON functions
|
|
74
74
|
*/
|
|
75
75
|
function userRecordConstructor(wireData) {
|
|
76
76
|
// Falsey values from the wire format proto get lost when converted to JSON, this adds them back.
|
|
@@ -122,7 +122,7 @@ function userRecordConstructor(wireData) {
|
|
|
122
122
|
}
|
|
123
123
|
exports.userRecordConstructor = userRecordConstructor;
|
|
124
124
|
/**
|
|
125
|
-
* Checks for a valid identity platform web request, otherwise throws an HttpsError
|
|
125
|
+
* Checks for a valid identity platform web request, otherwise throws an HttpsError.
|
|
126
126
|
* @internal
|
|
127
127
|
*/
|
|
128
128
|
function isValidRequest(req) {
|
|
@@ -156,15 +156,15 @@ function unsafeDecodeAuthBlockingToken(token) {
|
|
|
156
156
|
return decoded;
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* Helper function to parse the decoded metadata object into a UserMetaData object
|
|
159
|
+
* Helper function to parse the decoded metadata object into a `UserMetaData` object
|
|
160
160
|
* @internal
|
|
161
161
|
*/
|
|
162
162
|
function parseMetadata(metadata) {
|
|
163
163
|
const creationTime = (metadata === null || metadata === void 0 ? void 0 : metadata.creation_time)
|
|
164
|
-
? new Date(metadata.creation_time
|
|
164
|
+
? new Date(metadata.creation_time).toUTCString()
|
|
165
165
|
: null;
|
|
166
166
|
const lastSignInTime = (metadata === null || metadata === void 0 ? void 0 : metadata.last_sign_in_time)
|
|
167
|
-
? new Date(metadata.last_sign_in_time
|
|
167
|
+
? new Date(metadata.last_sign_in_time).toUTCString()
|
|
168
168
|
: null;
|
|
169
169
|
return {
|
|
170
170
|
creationTime,
|
|
@@ -173,7 +173,7 @@ function parseMetadata(metadata) {
|
|
|
173
173
|
}
|
|
174
174
|
exports.parseMetadata = parseMetadata;
|
|
175
175
|
/**
|
|
176
|
-
* Helper function to parse the decoded user info array into an AuthUserInfo array
|
|
176
|
+
* Helper function to parse the decoded user info array into an `AuthUserInfo` array.
|
|
177
177
|
* @internal
|
|
178
178
|
*/
|
|
179
179
|
function parseProviderData(providerData) {
|
|
@@ -192,7 +192,7 @@ function parseProviderData(providerData) {
|
|
|
192
192
|
}
|
|
193
193
|
exports.parseProviderData = parseProviderData;
|
|
194
194
|
/**
|
|
195
|
-
* Helper function to parse the date into a UTC string
|
|
195
|
+
* Helper function to parse the date into a UTC string.
|
|
196
196
|
* @internal
|
|
197
197
|
*/
|
|
198
198
|
function parseDate(tokensValidAfterTime) {
|
|
@@ -276,7 +276,7 @@ function parseAuthUserRecord(decodedJWTUserRecord) {
|
|
|
276
276
|
};
|
|
277
277
|
}
|
|
278
278
|
exports.parseAuthUserRecord = parseAuthUserRecord;
|
|
279
|
-
/** Helper to get the AdditionalUserInfo from the decoded
|
|
279
|
+
/** Helper to get the `AdditionalUserInfo` from the decoded JWT */
|
|
280
280
|
function parseAdditionalUserInfo(decodedJWT) {
|
|
281
281
|
let profile;
|
|
282
282
|
let username;
|
|
@@ -301,9 +301,33 @@ function parseAdditionalUserInfo(decodedJWT) {
|
|
|
301
301
|
profile,
|
|
302
302
|
username,
|
|
303
303
|
isNewUser: decodedJWT.event_type === "beforeCreate" ? true : false,
|
|
304
|
+
recaptchaScore: decodedJWT.recaptcha_score,
|
|
304
305
|
};
|
|
305
306
|
}
|
|
306
|
-
/**
|
|
307
|
+
/**
|
|
308
|
+
* Helper to generate a response from the blocking function to the Firebase Auth backend.
|
|
309
|
+
* @internal
|
|
310
|
+
*/
|
|
311
|
+
function generateResponsePayload(authResponse) {
|
|
312
|
+
if (!authResponse) {
|
|
313
|
+
return {};
|
|
314
|
+
}
|
|
315
|
+
const { recaptchaActionOverride, ...formattedAuthResponse } = authResponse;
|
|
316
|
+
const result = {};
|
|
317
|
+
const updateMask = getUpdateMask(formattedAuthResponse);
|
|
318
|
+
if (updateMask.length !== 0) {
|
|
319
|
+
result.userRecord = {
|
|
320
|
+
...formattedAuthResponse,
|
|
321
|
+
updateMask,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
if (recaptchaActionOverride !== undefined) {
|
|
325
|
+
result.recaptchaActionOverride = recaptchaActionOverride;
|
|
326
|
+
}
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
exports.generateResponsePayload = generateResponsePayload;
|
|
330
|
+
/** Helper to get the Credential from the decoded JWT */
|
|
307
331
|
function parseAuthCredential(decodedJWT, time) {
|
|
308
332
|
if (!decodedJWT.sign_in_attributes &&
|
|
309
333
|
!decodedJWT.oauth_id_token &&
|
|
@@ -437,15 +461,7 @@ function wrapHandler(eventType, handler) {
|
|
|
437
461
|
})) || undefined;
|
|
438
462
|
}
|
|
439
463
|
validateAuthResponse(eventType, authResponse);
|
|
440
|
-
const
|
|
441
|
-
const result = updateMask.length === 0
|
|
442
|
-
? {}
|
|
443
|
-
: {
|
|
444
|
-
userRecord: {
|
|
445
|
-
...authResponse,
|
|
446
|
-
updateMask,
|
|
447
|
-
},
|
|
448
|
-
};
|
|
464
|
+
const result = generateResponsePayload(authResponse);
|
|
449
465
|
res.status(200);
|
|
450
466
|
res.setHeader("Content-Type", "application/json");
|
|
451
467
|
res.send(JSON.stringify(result));
|
|
@@ -53,17 +53,60 @@ export interface TaskContext {
|
|
|
53
53
|
* The result of decoding and verifying an ODIC token.
|
|
54
54
|
*/
|
|
55
55
|
auth?: AuthData;
|
|
56
|
+
/**
|
|
57
|
+
* The name of the queue.
|
|
58
|
+
* Populated via the `X-CloudTasks-QueueName` header.
|
|
59
|
+
*/
|
|
60
|
+
queueName: string;
|
|
61
|
+
/**
|
|
62
|
+
* The "short" name of the task, or, if no name was specified at creation, a unique
|
|
63
|
+
* system-generated id.
|
|
64
|
+
* This is the "my-task-id" value in the complete task name, such as "task_name =
|
|
65
|
+
* projects/my-project-id/locations/my-location/queues/my-queue-id/tasks/my-task-id."
|
|
66
|
+
* Populated via the `X-CloudTasks-TaskName` header.
|
|
67
|
+
*/
|
|
68
|
+
id: string;
|
|
69
|
+
/**
|
|
70
|
+
* The number of times this task has been retried.
|
|
71
|
+
* For the first attempt, this value is 0. This number includes attempts where the task failed
|
|
72
|
+
* due to 5XX error codes and never reached the execution phase.
|
|
73
|
+
* Populated via the `X-CloudTasks-TaskRetryCount` header.
|
|
74
|
+
*/
|
|
75
|
+
retryCount: number;
|
|
76
|
+
/**
|
|
77
|
+
* The total number of times that the task has received a response from the handler.
|
|
78
|
+
* Since Cloud Tasks deletes the task once a successful response has been received, all
|
|
79
|
+
* previous handler responses were failures. This number does not include failures due to 5XX
|
|
80
|
+
* error codes.
|
|
81
|
+
* Populated via the `X-CloudTasks-TaskExecutionCount` header.
|
|
82
|
+
*/
|
|
83
|
+
executionCount: number;
|
|
84
|
+
/**
|
|
85
|
+
* The schedule time of the task, as an RFC 3339 string in UTC time zone.
|
|
86
|
+
* Populated via the `X-CloudTasks-TaskETA` header, which uses seconds since January 1 1970.
|
|
87
|
+
*/
|
|
88
|
+
scheduledTime: string;
|
|
89
|
+
/**
|
|
90
|
+
* The HTTP response code from the previous retry.
|
|
91
|
+
* Populated via the `X-CloudTasks-TaskPreviousResponse` header
|
|
92
|
+
*/
|
|
93
|
+
previousResponse?: number;
|
|
94
|
+
/**
|
|
95
|
+
* The reason for retrying the task.
|
|
96
|
+
* Populated via the `X-CloudTasks-TaskRetryReason` header.
|
|
97
|
+
*/
|
|
98
|
+
retryReason?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Raw request headers.
|
|
101
|
+
*/
|
|
102
|
+
headers?: Record<string, string>;
|
|
56
103
|
}
|
|
57
104
|
/**
|
|
58
|
-
* The request used to call a
|
|
105
|
+
* The request used to call a task queue function.
|
|
59
106
|
*/
|
|
60
|
-
export
|
|
107
|
+
export type Request<T = any> = TaskContext & {
|
|
61
108
|
/**
|
|
62
109
|
* The parameters used by a client when calling this function.
|
|
63
110
|
*/
|
|
64
111
|
data: T;
|
|
65
|
-
|
|
66
|
-
* The result of decoding and verifying an ODIC token.
|
|
67
|
-
*/
|
|
68
|
-
auth?: AuthData;
|
|
69
|
-
}
|
|
112
|
+
};
|
|
@@ -33,7 +33,28 @@ function onDispatchHandler(handler) {
|
|
|
33
33
|
logger.error("Invalid request, unable to process.");
|
|
34
34
|
throw new https.HttpsError("invalid-argument", "Bad Request");
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const headers = {};
|
|
37
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
38
|
+
if (!Array.isArray(value)) {
|
|
39
|
+
headers[key] = value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const context = {
|
|
43
|
+
queueName: req.header("X-CloudTasks-QueueName"),
|
|
44
|
+
id: req.header("X-CloudTasks-TaskName"),
|
|
45
|
+
retryCount: req.header("X-CloudTasks-TaskRetryCount")
|
|
46
|
+
? Number(req.header("X-CloudTasks-TaskRetryCount"))
|
|
47
|
+
: undefined,
|
|
48
|
+
executionCount: req.header("X-CloudTasks-TaskExecutionCount")
|
|
49
|
+
? Number(req.header("X-CloudTasks-TaskExecutionCount"))
|
|
50
|
+
: undefined,
|
|
51
|
+
scheduledTime: req.header("X-CloudTasks-TaskETA"),
|
|
52
|
+
previousResponse: req.header("X-CloudTasks-TaskPreviousResponse")
|
|
53
|
+
? Number(req.header("X-CloudTasks-TaskPreviousResponse"))
|
|
54
|
+
: undefined,
|
|
55
|
+
retryReason: req.header("X-CloudTasks-TaskRetryReason"),
|
|
56
|
+
headers,
|
|
57
|
+
};
|
|
37
58
|
if (!process.env.FUNCTIONS_EMULATOR) {
|
|
38
59
|
const authHeader = req.header("Authorization") || "";
|
|
39
60
|
const token = (_a = authHeader.match(/^Bearer (.*)$/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
@@ -177,7 +177,8 @@ export interface RuntimeOptions {
|
|
|
177
177
|
*
|
|
178
178
|
* @remarks
|
|
179
179
|
* Set this to true to enable the App Check replay protection feature by consuming the App Check token on callable
|
|
180
|
-
* request. Tokens that are found to be already consumed will have request.app.alreadyConsumed property set
|
|
180
|
+
* request. Tokens that are found to be already consumed will have the `request.app.alreadyConsumed` property set
|
|
181
|
+
* to true.
|
|
181
182
|
*
|
|
182
183
|
*
|
|
183
184
|
* Tokens are only considered to be consumed if it is sent to the App Check service by setting this option to true.
|
|
@@ -188,10 +189,10 @@ export interface RuntimeOptions {
|
|
|
188
189
|
* performance and can potentially deplete your attestation providers' quotas faster. Use this feature only for
|
|
189
190
|
* protecting low volume, security critical, or expensive operations.
|
|
190
191
|
*
|
|
191
|
-
* This option does not affect the enforceAppCheck option. Setting the latter to true will cause the callable function
|
|
192
|
-
* to automatically respond with a 401 Unauthorized status code when request includes an invalid App Check token.
|
|
193
|
-
* When request includes valid but consumed App Check tokens, requests will not be automatically rejected. Instead,
|
|
194
|
-
* the request.app.alreadyConsumed property will be set to true and pass the execution to the handler code for making
|
|
192
|
+
* This option does not affect the `enforceAppCheck` option. Setting the latter to true will cause the callable function
|
|
193
|
+
* to automatically respond with a 401 Unauthorized status code when the request includes an invalid App Check token.
|
|
194
|
+
* When the request includes valid but consumed App Check tokens, requests will not be automatically rejected. Instead,
|
|
195
|
+
* the `request.app.alreadyConsumed` property will be set to true and pass the execution to the handler code for making
|
|
195
196
|
* further decisions, such as requiring additional security checks or rejecting the request.
|
|
196
197
|
*/
|
|
197
198
|
consumeAppCheckToken?: boolean;
|
package/lib/v2/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Core functionality of the
|
|
2
|
+
* Core functionality of the Cloud Functions for Firebase 2nd gen SDK.
|
|
3
3
|
* @packageDocumentation
|
|
4
4
|
*/
|
|
5
5
|
import { Change } from "../common/change";
|
|
@@ -7,8 +7,8 @@ import { ManifestEndpoint } from "../runtime/manifest";
|
|
|
7
7
|
export { Change };
|
|
8
8
|
export { ParamsOf } from "../common/params";
|
|
9
9
|
/**
|
|
10
|
-
* A CloudEventBase is the base of a cross-platform format for encoding a serverless event.
|
|
11
|
-
*
|
|
10
|
+
* A `CloudEventBase` is the base of a cross-platform format for encoding a serverless event.
|
|
11
|
+
* For more information, see https://github.com/cloudevents/spec.
|
|
12
12
|
* @typeParam T - The type of the event data.
|
|
13
13
|
* @beta
|
|
14
14
|
*/
|
|
@@ -17,9 +17,9 @@ export interface CloudEvent<T> {
|
|
|
17
17
|
readonly specversion: "1.0";
|
|
18
18
|
/** A globally unique ID for this event. */
|
|
19
19
|
id: string;
|
|
20
|
-
/** The resource
|
|
20
|
+
/** The resource that published this event. */
|
|
21
21
|
source: string;
|
|
22
|
-
/** The resource, provided by source, that this event relates to */
|
|
22
|
+
/** The resource, provided by source, that this event relates to. */
|
|
23
23
|
subject?: string;
|
|
24
24
|
/** The type of event that this represents. */
|
|
25
25
|
type: string;
|
|
@@ -41,10 +41,10 @@ export interface CloudFunction<EventType extends CloudEvent<unknown>> {
|
|
|
41
41
|
/** @alpha */
|
|
42
42
|
__endpoint: ManifestEndpoint;
|
|
43
43
|
/**
|
|
44
|
-
* The callback passed to the CloudFunction constructor.
|
|
45
|
-
* Use run to test a
|
|
44
|
+
* The callback passed to the `CloudFunction` constructor.
|
|
45
|
+
* Use `run` to test a function.
|
|
46
46
|
* @param event - The parsed event to handle.
|
|
47
|
-
* @returns Any return value.
|
|
47
|
+
* @returns Any return value. Cloud Functions awaits any promise
|
|
48
48
|
* before shutting down your function. Resolved return values
|
|
49
49
|
* are only used for unit testing purposes.
|
|
50
50
|
* @beta
|
package/lib/v2/core.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.Change = void 0;
|
|
25
25
|
/**
|
|
26
|
-
* Core functionality of the
|
|
26
|
+
* Core functionality of the Cloud Functions for Firebase 2nd gen SDK.
|
|
27
27
|
* @packageDocumentation
|
|
28
28
|
*/
|
|
29
29
|
const change_1 = require("../common/change");
|
package/lib/v2/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
* This SDK
|
|
4
|
-
*
|
|
5
|
-
* from
|
|
2
|
+
* The 2nd gen API for Cloud Functions for Firebase.
|
|
3
|
+
* This SDK supports deep imports. For example, the namespace
|
|
4
|
+
* `pubsub` is available at `firebase-functions/v2` or is directly importable
|
|
5
|
+
* from `firebase-functions/v2/pubsub`.
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
8
|
import * as logger from "../logger";
|
package/lib/v2/index.js
CHANGED
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.params = exports.Change = exports.setGlobalOptions = exports.firestore = exports.testLab = exports.remoteConfig = exports.scheduler = exports.eventarc = exports.tasks = exports.logger = exports.pubsub = exports.identity = exports.https = exports.storage = exports.database = exports.alerts = void 0;
|
|
25
25
|
/**
|
|
26
|
-
* The
|
|
27
|
-
* This SDK
|
|
28
|
-
*
|
|
29
|
-
* from
|
|
26
|
+
* The 2nd gen API for Cloud Functions for Firebase.
|
|
27
|
+
* This SDK supports deep imports. For example, the namespace
|
|
28
|
+
* `pubsub` is available at `firebase-functions/v2` or is directly importable
|
|
29
|
+
* from `firebase-functions/v2/pubsub`.
|
|
30
30
|
* @packageDocumentation
|
|
31
31
|
*/
|
|
32
32
|
const logger = require("../logger");
|
package/lib/v2/options.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Expression } from "../params";
|
|
|
3
3
|
import { ParamSpec, SecretParam } from "../params/types";
|
|
4
4
|
export { RESET_VALUE } from "../common/options";
|
|
5
5
|
/**
|
|
6
|
-
* List of all regions supported by Cloud Functions
|
|
6
|
+
* List of all regions supported by Cloud Functions (2nd gen).
|
|
7
7
|
*/
|
|
8
8
|
export type SupportedRegion = "asia-east1" | "asia-northeast1" | "asia-northeast2" | "europe-north1" | "europe-west1" | "europe-west4" | "us-central1" | "us-east1" | "us-east4" | "us-west1" | "asia-east2" | "asia-northeast3" | "asia-southeast1" | "asia-southeast2" | "asia-south1" | "australia-southeast1" | "europe-central2" | "europe-west2" | "europe-west3" | "europe-west6" | "northamerica-northeast1" | "southamerica-east1" | "us-west2" | "us-west3" | "us-west4";
|
|
9
9
|
/**
|
|
@@ -11,16 +11,16 @@ export type SupportedRegion = "asia-east1" | "asia-northeast1" | "asia-northeast
|
|
|
11
11
|
*/
|
|
12
12
|
export type MemoryOption = "128MiB" | "256MiB" | "512MiB" | "1GiB" | "2GiB" | "4GiB" | "8GiB" | "16GiB" | "32GiB";
|
|
13
13
|
/**
|
|
14
|
-
* List of available options for VpcConnectorEgressSettings
|
|
14
|
+
* List of available options for `VpcConnectorEgressSettings`.
|
|
15
15
|
*/
|
|
16
16
|
export type VpcEgressSetting = "PRIVATE_RANGES_ONLY" | "ALL_TRAFFIC";
|
|
17
17
|
/**
|
|
18
|
-
* List of available options for IngressSettings
|
|
18
|
+
* List of available options for `IngressSettings`.
|
|
19
19
|
*/
|
|
20
20
|
export type IngressSetting = "ALLOW_ALL" | "ALLOW_INTERNAL_ONLY" | "ALLOW_INTERNAL_AND_GCLB";
|
|
21
21
|
/**
|
|
22
|
-
* GlobalOptions are options that can be set across an entire project.
|
|
23
|
-
* These options are common to HTTPS and
|
|
22
|
+
* `GlobalOptions` are options that can be set across an entire project.
|
|
23
|
+
* These options are common to HTTPS and event handling functions.
|
|
24
24
|
*/
|
|
25
25
|
export interface GlobalOptions {
|
|
26
26
|
/**
|
|
@@ -40,30 +40,30 @@ export interface GlobalOptions {
|
|
|
40
40
|
* HTTPS functions can specify a higher timeout.
|
|
41
41
|
*
|
|
42
42
|
* @remarks
|
|
43
|
-
* The minimum timeout for a gen
|
|
43
|
+
* The minimum timeout for a 2nd gen function is 1s. The maximum timeout for a
|
|
44
44
|
* function depends on the type of function: Event handling functions have a
|
|
45
45
|
* maximum timeout of 540s (9 minutes). HTTPS and callable functions have a
|
|
46
46
|
* maximum timeout of 36,00s (1 hour). Task queue functions have a maximum
|
|
47
|
-
* timeout of 1,800s (30 minutes)
|
|
47
|
+
* timeout of 1,800s (30 minutes).
|
|
48
48
|
*/
|
|
49
49
|
timeoutSeconds?: number | Expression<number> | ResetValue;
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* Minimum number of actual instances to be running at a given time.
|
|
52
52
|
*
|
|
53
53
|
* @remarks
|
|
54
|
-
* Instances
|
|
54
|
+
* Instances are billed for memory allocation and 10% of CPU allocation
|
|
55
55
|
* while idle.
|
|
56
56
|
*/
|
|
57
57
|
minInstances?: number | Expression<number> | ResetValue;
|
|
58
58
|
/**
|
|
59
|
-
* Max number of instances
|
|
59
|
+
* Max number of instances that can be running in parallel.
|
|
60
60
|
*/
|
|
61
61
|
maxInstances?: number | Expression<number> | ResetValue;
|
|
62
62
|
/**
|
|
63
63
|
* Number of requests a function can serve at once.
|
|
64
64
|
*
|
|
65
65
|
* @remarks
|
|
66
|
-
* Can
|
|
66
|
+
* Can be applied only to functions running on Cloud Functions (2nd gen)).
|
|
67
67
|
* A value of null restores the default concurrency (80 when CPU >= 1, 1 otherwise).
|
|
68
68
|
* Concurrency cannot be set to any value other than 1 if `cpu` is less than 1.
|
|
69
69
|
* The maximum value for concurrency is 1,000.
|
|
@@ -75,13 +75,13 @@ export interface GlobalOptions {
|
|
|
75
75
|
* @remarks
|
|
76
76
|
* Defaults to 1 for functions with <= 2GB RAM and increases for larger memory sizes.
|
|
77
77
|
* This is different from the defaults when using the gcloud utility and is different from
|
|
78
|
-
* the fixed amount assigned in
|
|
79
|
-
* To revert to the CPU amounts used in gcloud or in Cloud Functions
|
|
78
|
+
* the fixed amount assigned in Cloud Functions (1st gen).
|
|
79
|
+
* To revert to the CPU amounts used in gcloud or in Cloud Functions (1st gen), set this
|
|
80
80
|
* to the value "gcf_gen1"
|
|
81
81
|
*/
|
|
82
82
|
cpu?: number | "gcf_gen1";
|
|
83
83
|
/**
|
|
84
|
-
* Connect
|
|
84
|
+
* Connect a function to a specified VPC connector.
|
|
85
85
|
*/
|
|
86
86
|
vpcConnector?: string | Expression<string> | ResetValue;
|
|
87
87
|
/**
|
|
@@ -97,7 +97,7 @@ export interface GlobalOptions {
|
|
|
97
97
|
*/
|
|
98
98
|
ingressSettings?: IngressSetting | ResetValue;
|
|
99
99
|
/**
|
|
100
|
-
* Invoker to set access control on
|
|
100
|
+
* Invoker to set access control on HTTPS functions.
|
|
101
101
|
*/
|
|
102
102
|
invoker?: "public" | "private" | string | string[];
|
|
103
103
|
/**
|
|
@@ -106,36 +106,39 @@ export interface GlobalOptions {
|
|
|
106
106
|
labels?: Record<string, string>;
|
|
107
107
|
secrets?: (string | SecretParam)[];
|
|
108
108
|
/**
|
|
109
|
-
* Determines whether Firebase
|
|
109
|
+
* Determines whether Firebase App Check is enforced. Defaults to false.
|
|
110
110
|
*
|
|
111
111
|
* @remarks
|
|
112
112
|
* When true, requests with invalid tokens autorespond with a 401
|
|
113
113
|
* (Unauthorized) error.
|
|
114
|
-
* When false, requests with invalid tokens set event.app to undefined
|
|
114
|
+
* When false, requests with invalid tokens set `event.app` to `undefined`.
|
|
115
115
|
*/
|
|
116
116
|
enforceAppCheck?: boolean;
|
|
117
117
|
/**
|
|
118
118
|
* Controls whether function configuration modified outside of function source is preserved. Defaults to false.
|
|
119
119
|
*
|
|
120
120
|
* @remarks
|
|
121
|
-
* When setting configuration available in
|
|
122
|
-
*
|
|
121
|
+
* When setting configuration available in an underlying platform that is not yet available in the Firebase SDK
|
|
122
|
+
* for Cloud Functions, we recommend setting `preserveExternalChanges` to `true`. Otherwise, when Google releases
|
|
123
123
|
* a new version of the SDK with support for the missing configuration, your function's manually configured setting
|
|
124
124
|
* may inadvertently be wiped out.
|
|
125
125
|
*/
|
|
126
126
|
preserveExternalChanges?: boolean;
|
|
127
127
|
}
|
|
128
128
|
/**
|
|
129
|
-
* Sets default options for all functions written using the
|
|
129
|
+
* Sets default options for all functions written using the 2nd gen SDK.
|
|
130
130
|
* @param options Options to set as default
|
|
131
131
|
*/
|
|
132
132
|
export declare function setGlobalOptions(options: GlobalOptions): void;
|
|
133
133
|
/**
|
|
134
|
-
* Additional fields that can be set on any event-handling
|
|
134
|
+
* Additional fields that can be set on any event-handling function.
|
|
135
135
|
*/
|
|
136
136
|
export interface EventHandlerOptions extends Omit<GlobalOptions, "enforceAppCheck"> {
|
|
137
|
+
/** Type of the event. Valid values are TODO */
|
|
137
138
|
eventType?: string;
|
|
139
|
+
/** TODO */
|
|
138
140
|
eventFilters?: Record<string, string | Expression<string>>;
|
|
141
|
+
/** TODO */
|
|
139
142
|
eventFilterPathPatterns?: Record<string, string | Expression<string>>;
|
|
140
143
|
/** Whether failed executions should be delivered again. */
|
|
141
144
|
retry?: boolean | Expression<boolean> | ResetValue;
|
package/lib/v2/options.js
CHANGED
|
@@ -46,7 +46,7 @@ const MemoryOptionToMB = {
|
|
|
46
46
|
};
|
|
47
47
|
let globalOptions;
|
|
48
48
|
/**
|
|
49
|
-
* Sets default options for all functions written using the
|
|
49
|
+
* Sets default options for all functions written using the 2nd gen SDK.
|
|
50
50
|
* @param options Options to set as default
|
|
51
51
|
*/
|
|
52
52
|
function setGlobalOptions(options) {
|
|
@@ -30,6 +30,7 @@ const core_1 = require("../core");
|
|
|
30
30
|
Object.defineProperty(exports, "Change", { enumerable: true, get: function () { return core_1.Change; } });
|
|
31
31
|
const options_1 = require("../options");
|
|
32
32
|
const firestore_1 = require("../../common/providers/firestore");
|
|
33
|
+
const trace_1 = require("../trace");
|
|
33
34
|
/** @internal */
|
|
34
35
|
exports.writtenEventType = "google.cloud.firestore.document.v1.written";
|
|
35
36
|
/** @internal */
|
|
@@ -219,7 +220,7 @@ function onOperation(eventType, documentOrOpts, handler) {
|
|
|
219
220
|
const event = raw;
|
|
220
221
|
const params = makeParams(event.document, documentPattern);
|
|
221
222
|
const firestoreEvent = makeFirestoreEvent(eventType, event, params);
|
|
222
|
-
return handler(firestoreEvent);
|
|
223
|
+
return (0, trace_1.wrapTraceContext)(handler)(firestoreEvent);
|
|
223
224
|
};
|
|
224
225
|
func.run = handler;
|
|
225
226
|
func.__endpoint = makeEndpoint(eventType, opts, documentPattern, database, namespace);
|
|
@@ -78,16 +78,18 @@ function onRequest(optsOrHandler, handler) {
|
|
|
78
78
|
allowInsecure: false,
|
|
79
79
|
},
|
|
80
80
|
};
|
|
81
|
+
(0, encoding_1.convertIfPresent)(trigger.httpsTrigger, options.getGlobalOptions(), "invoker", "invoker", encoding_1.convertInvoker);
|
|
81
82
|
(0, encoding_1.convertIfPresent)(trigger.httpsTrigger, opts, "invoker", "invoker", encoding_1.convertInvoker);
|
|
82
83
|
return trigger;
|
|
83
84
|
},
|
|
84
85
|
});
|
|
85
|
-
const
|
|
86
|
+
const globalOpts = options.getGlobalOptions();
|
|
87
|
+
const baseOpts = options.optionsToEndpoint(globalOpts);
|
|
86
88
|
// global options calls region a scalar and https allows it to be an array,
|
|
87
89
|
// but optionsToTriggerAnnotations handles both cases.
|
|
88
90
|
const specificOpts = options.optionsToEndpoint(opts);
|
|
89
91
|
const endpoint = {
|
|
90
|
-
...(0, manifest_1.initV2Endpoint)(
|
|
92
|
+
...(0, manifest_1.initV2Endpoint)(globalOpts, opts),
|
|
91
93
|
platform: "gcfv2",
|
|
92
94
|
...baseOpts,
|
|
93
95
|
...specificOpts,
|
|
@@ -97,6 +99,7 @@ function onRequest(optsOrHandler, handler) {
|
|
|
97
99
|
},
|
|
98
100
|
httpsTrigger: {},
|
|
99
101
|
};
|
|
102
|
+
(0, encoding_1.convertIfPresent)(endpoint.httpsTrigger, globalOpts, "invoker", "invoker", encoding_1.convertInvoker);
|
|
100
103
|
(0, encoding_1.convertIfPresent)(endpoint.httpsTrigger, opts, "invoker", "invoker", encoding_1.convertInvoker);
|
|
101
104
|
handler.__endpoint = endpoint;
|
|
102
105
|
return handler;
|
|
@@ -116,11 +119,12 @@ function onCall(optsOrHandler, handler) {
|
|
|
116
119
|
// onCallHandler sniffs the function length to determine which API to present.
|
|
117
120
|
// fix the length to prevent api versions from being mismatched.
|
|
118
121
|
const fixedLen = (req) => handler(req);
|
|
119
|
-
|
|
122
|
+
let func = (0, https_1.onCallHandler)({
|
|
120
123
|
cors: { origin, methods: "POST" },
|
|
121
124
|
enforceAppCheck: (_a = opts.enforceAppCheck) !== null && _a !== void 0 ? _a : options.getGlobalOptions().enforceAppCheck,
|
|
122
125
|
consumeAppCheckToken: opts.consumeAppCheckToken,
|
|
123
126
|
}, fixedLen);
|
|
127
|
+
func = (0, trace_1.wrapTraceContext)(func);
|
|
124
128
|
Object.defineProperty(func, "__trigger", {
|
|
125
129
|
get: () => {
|
|
126
130
|
const baseOpts = options.optionsToTriggerAnnotations(options.getGlobalOptions());
|
|
@@ -52,6 +52,7 @@ function onTaskDispatched(optsOrHandler, handler) {
|
|
|
52
52
|
const specificOpts = options.optionsToTriggerAnnotations(opts);
|
|
53
53
|
const taskQueueTrigger = {};
|
|
54
54
|
(0, encoding_1.copyIfPresent)(taskQueueTrigger, opts, "retryConfig", "rateLimits");
|
|
55
|
+
(0, encoding_1.convertIfPresent)(taskQueueTrigger, options.getGlobalOptions(), "invoker", "invoker", encoding_1.convertInvoker);
|
|
55
56
|
(0, encoding_1.convertIfPresent)(taskQueueTrigger, opts, "invoker", "invoker", encoding_1.convertInvoker);
|
|
56
57
|
return {
|
|
57
58
|
platform: "gcfv2",
|
|
@@ -82,6 +83,7 @@ function onTaskDispatched(optsOrHandler, handler) {
|
|
|
82
83
|
};
|
|
83
84
|
(0, encoding_1.copyIfPresent)(func.__endpoint.taskQueueTrigger.retryConfig, opts.retryConfig, "maxAttempts", "maxBackoffSeconds", "maxDoublings", "maxRetrySeconds", "minBackoffSeconds");
|
|
84
85
|
(0, encoding_1.copyIfPresent)(func.__endpoint.taskQueueTrigger.rateLimits, opts.rateLimits, "maxConcurrentDispatches", "maxDispatchesPerSecond");
|
|
86
|
+
(0, encoding_1.convertIfPresent)(func.__endpoint.taskQueueTrigger, options.getGlobalOptions(), "invoker", "invoker", encoding_1.convertInvoker);
|
|
85
87
|
(0, encoding_1.convertIfPresent)(func.__endpoint.taskQueueTrigger, opts, "invoker", "invoker", encoding_1.convertInvoker);
|
|
86
88
|
func.__requiredAPIs = [
|
|
87
89
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-functions",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "Firebase SDK for Cloud Functions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"firebase",
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
"eslint-config-prettier": "^8.3.0",
|
|
226
226
|
"eslint-plugin-jsdoc": "^39.2.9",
|
|
227
227
|
"eslint-plugin-prettier": "^4.0.0",
|
|
228
|
-
"firebase-admin": "^
|
|
228
|
+
"firebase-admin": "^12.0.0",
|
|
229
229
|
"js-yaml": "^3.13.1",
|
|
230
230
|
"jsdom": "^16.2.1",
|
|
231
231
|
"jsonwebtoken": "^9.0.0",
|
|
@@ -245,7 +245,7 @@
|
|
|
245
245
|
"yargs": "^15.3.1"
|
|
246
246
|
},
|
|
247
247
|
"peerDependencies": {
|
|
248
|
-
"firebase-admin": "^10.0.0 || ^11.0.0"
|
|
248
|
+
"firebase-admin": "^10.0.0 || ^11.0.0 || ^12.0.0"
|
|
249
249
|
},
|
|
250
250
|
"engines": {
|
|
251
251
|
"node": ">=14.10.0"
|