firebase-functions 7.2.5 → 7.3.0-rc.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/common/api.d.ts +7 -0
- package/lib/common/api.js +34 -0
- package/lib/common/providers/https.d.ts +7 -0
- package/lib/common/providers/https.js +40 -1
- package/lib/esm/common/api.mjs +31 -0
- package/lib/esm/common/providers/https.mjs +40 -2
- package/lib/esm/lifecycle/index.mjs +55 -0
- package/lib/esm/runtime/loader.mjs +12 -2
- package/lib/esm/runtime/manifest.mjs +0 -1
- package/lib/esm/security/roles.mjs +17 -0
- package/lib/esm/v1/cloud-functions.mjs +2 -1
- package/lib/esm/v1/function-builder.mjs +15 -1
- package/lib/esm/v1/index.mjs +2 -1
- package/lib/esm/v1/providers/https.mjs +28 -4
- package/lib/esm/v2/index.doc.mjs +4 -1
- package/lib/esm/v2/index.mjs +4 -1
- package/lib/esm/v2/options.mjs +79 -3
- package/lib/esm/v2/providers/ai/index.mjs +2 -2
- package/lib/esm/v2/providers/alerts/alerts.mjs +1 -1
- package/lib/esm/v2/providers/database.mjs +19 -6
- package/lib/esm/v2/providers/dataconnect/graphql.mjs +1 -1
- package/lib/esm/v2/providers/dataconnect/index.mjs +1 -1
- package/lib/esm/v2/providers/eventarc.mjs +1 -1
- package/lib/esm/v2/providers/firestore.mjs +1 -1
- package/lib/esm/v2/providers/https.mjs +9 -23
- package/lib/esm/v2/providers/identity.mjs +89 -4
- package/lib/esm/v2/providers/pubsub.mjs +4 -4
- package/lib/esm/v2/providers/remoteConfig.mjs +1 -1
- package/lib/esm/v2/providers/scheduler.mjs +1 -1
- package/lib/esm/v2/providers/storage.mjs +2 -2
- package/lib/esm/v2/providers/tasks.mjs +2 -2
- package/lib/esm/v2/providers/testLab.mjs +1 -1
- package/lib/esm/v2/security.mjs +19 -0
- package/lib/lifecycle/index.d.ts +44 -0
- package/lib/lifecycle/index.js +59 -0
- package/lib/logger/common.d.ts +20 -5
- package/lib/params/types.d.ts +9 -3
- package/lib/runtime/loader.js +12 -2
- package/lib/runtime/manifest.d.ts +24 -3
- package/lib/runtime/manifest.js +0 -1
- package/lib/security/roles.d.ts +5 -0
- package/lib/security/roles.js +19 -0
- package/lib/v1/cloud-functions.d.ts +8 -5
- package/lib/v1/cloud-functions.js +2 -1
- package/lib/v1/function-builder.d.ts +2 -2
- package/lib/v1/function-builder.js +15 -1
- package/lib/v1/index.d.ts +1 -0
- package/lib/v1/index.js +2 -0
- package/lib/v1/providers/https.d.ts +11 -3
- package/lib/v1/providers/https.js +28 -3
- package/lib/v2/index.d.ts +4 -2
- package/lib/v2/index.doc.js +7 -0
- package/lib/v2/index.js +7 -0
- package/lib/v2/options.d.ts +6 -2
- package/lib/v2/options.js +84 -2
- package/lib/v2/providers/ai/index.js +2 -2
- package/lib/v2/providers/alerts/alerts.js +1 -1
- package/lib/v2/providers/database.d.ts +1 -1
- package/lib/v2/providers/database.js +19 -6
- package/lib/v2/providers/dataconnect/graphql.js +1 -1
- package/lib/v2/providers/dataconnect/index.js +1 -1
- package/lib/v2/providers/eventarc.js +1 -1
- package/lib/v2/providers/firestore.js +1 -1
- package/lib/v2/providers/https.js +8 -22
- package/lib/v2/providers/identity.d.ts +71 -1
- package/lib/v2/providers/identity.js +91 -3
- package/lib/v2/providers/pubsub.d.ts +3 -3
- package/lib/v2/providers/pubsub.js +4 -4
- package/lib/v2/providers/remoteConfig.js +1 -1
- package/lib/v2/providers/scheduler.js +1 -1
- package/lib/v2/providers/storage.js +2 -2
- package/lib/v2/providers/tasks.js +2 -2
- package/lib/v2/providers/testLab.js +1 -1
- package/lib/v2/security.d.ts +11 -0
- package/lib/v2/security.js +19 -0
- package/package.json +17 -13
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { __export } from "../../_virtual/rolldown_runtime.mjs";
|
|
2
|
+
import { Expression } from "../../params/types.mjs";
|
|
3
|
+
import "../../params/index.mjs";
|
|
2
4
|
import { initV2Endpoint } from "../../runtime/manifest.mjs";
|
|
3
5
|
import { getApp } from "../../common/app.mjs";
|
|
4
6
|
import { withInit } from "../../common/onInit.mjs";
|
|
@@ -163,10 +165,12 @@ function makeV1Context(eventType, databaseEvent) {
|
|
|
163
165
|
/** @internal */
|
|
164
166
|
function makeEndpoint(eventType, opts, path, instance) {
|
|
165
167
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
166
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
168
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
167
169
|
const eventFilters = {};
|
|
168
170
|
const eventFilterPathPatterns = { ref: path.getValue() };
|
|
169
|
-
if (instance
|
|
171
|
+
if (instance instanceof Expression) {
|
|
172
|
+
eventFilterPathPatterns.instance = instance;
|
|
173
|
+
} else if (instance.hasWildcards()) {
|
|
170
174
|
eventFilterPathPatterns.instance = instance.getValue();
|
|
171
175
|
} else {
|
|
172
176
|
eventFilters.instance = instance.getValue();
|
|
@@ -188,15 +192,24 @@ function makeEndpoint(eventType, opts, path, instance) {
|
|
|
188
192
|
}
|
|
189
193
|
};
|
|
190
194
|
}
|
|
195
|
+
function resolveInstancePattern(instance) {
|
|
196
|
+
return instance instanceof Expression ? new PathPattern(instance.value()) : instance;
|
|
197
|
+
}
|
|
198
|
+
function makeInstancePattern(instance) {
|
|
199
|
+
return instance instanceof Expression ? instance : new PathPattern(instance);
|
|
200
|
+
}
|
|
201
|
+
function makeTypedParams(event, pathPattern, instancePattern) {
|
|
202
|
+
return makeParams(event, pathPattern, resolveInstancePattern(instancePattern));
|
|
203
|
+
}
|
|
191
204
|
/** @internal */
|
|
192
205
|
function onChangedOperation(eventType, referenceOrOpts, handler) {
|
|
193
206
|
const { path, instance, opts } = getOpts(referenceOrOpts);
|
|
194
207
|
const pathPattern = new PathPattern(path);
|
|
195
|
-
const instancePattern =
|
|
208
|
+
const instancePattern = makeInstancePattern(instance);
|
|
196
209
|
const func = (raw) => {
|
|
197
210
|
const event = raw;
|
|
198
211
|
const instanceUrl = getInstance(event);
|
|
199
|
-
const params =
|
|
212
|
+
const params = makeTypedParams(event, pathPattern, instancePattern);
|
|
200
213
|
const databaseEvent = makeChangedDatabaseEvent(event, instanceUrl, params);
|
|
201
214
|
const compatEvent = addV1Compat(databaseEvent, {
|
|
202
215
|
context: () => makeV1Context(eventType, databaseEvent),
|
|
@@ -212,11 +225,11 @@ function onChangedOperation(eventType, referenceOrOpts, handler) {
|
|
|
212
225
|
function onOperation(eventType, referenceOrOpts, handler) {
|
|
213
226
|
const { path, instance, opts } = getOpts(referenceOrOpts);
|
|
214
227
|
const pathPattern = new PathPattern(path);
|
|
215
|
-
const instancePattern =
|
|
228
|
+
const instancePattern = makeInstancePattern(instance);
|
|
216
229
|
const func = (raw) => {
|
|
217
230
|
const event = raw;
|
|
218
231
|
const instanceUrl = getInstance(event);
|
|
219
|
-
const params =
|
|
232
|
+
const params = makeTypedParams(event, pathPattern, instancePattern);
|
|
220
233
|
const data = eventType === deletedEventType ? event.data.data : event.data.delta;
|
|
221
234
|
const databaseEvent = makeDatabaseEvent(event, data, instanceUrl, params);
|
|
222
235
|
const compatEvent = addV1Compat(databaseEvent, {
|
|
@@ -78,7 +78,7 @@ function onGraphRequest(opts) {
|
|
|
78
78
|
})));
|
|
79
79
|
const globalOpts = getGlobalOptions();
|
|
80
80
|
const baseOpts = optionsToEndpoint(globalOpts);
|
|
81
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
81
|
+
const specificOpts = optionsToEndpoint(opts, "https");
|
|
82
82
|
const endpoint = {
|
|
83
83
|
...initV2Endpoint(globalOpts, opts),
|
|
84
84
|
platform: "gcfv2",
|
|
@@ -56,7 +56,7 @@ function getOpts(mutationOrOpts) {
|
|
|
56
56
|
}
|
|
57
57
|
function makeEndpoint(eventType, opts, service, connector, operation) {
|
|
58
58
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
59
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
59
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
60
60
|
const eventFilters = {};
|
|
61
61
|
const eventFilterPathPatterns = {};
|
|
62
62
|
if (service) {
|
|
@@ -20,7 +20,7 @@ function onCustomEventPublished(eventTypeOrOpts, handler) {
|
|
|
20
20
|
func.run = handler;
|
|
21
21
|
const channel = opts.channel ?? "locations/us-central1/channels/firebase";
|
|
22
22
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
23
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
23
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
24
24
|
const endpoint = {
|
|
25
25
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
26
26
|
platform: "gcfv2",
|
|
@@ -234,7 +234,7 @@ function makeChangedFirestoreEvent(event, params) {
|
|
|
234
234
|
/** @internal */
|
|
235
235
|
function makeEndpoint(eventType, opts, document, database, namespace) {
|
|
236
236
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
237
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
237
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
238
238
|
const eventFilters = {
|
|
239
239
|
database,
|
|
240
240
|
namespace
|
|
@@ -6,7 +6,7 @@ import { initV2Endpoint } from "../../runtime/manifest.mjs";
|
|
|
6
6
|
import { isDebugFeatureEnabled } from "../../common/debug.mjs";
|
|
7
7
|
import { convertIfPresent, convertInvoker, copyIfPresent } from "../../common/encoding.mjs";
|
|
8
8
|
import { withInit } from "../../common/onInit.mjs";
|
|
9
|
-
import { HttpsError, onCallHandler, withErrorHandler } from "../../common/providers/https.mjs";
|
|
9
|
+
import { HttpsError, onCallHandler, resolveCorsOrigin, withErrorHandler } from "../../common/providers/https.mjs";
|
|
10
10
|
import { wrapTraceContext } from "../trace.mjs";
|
|
11
11
|
import { getGlobalOptions, optionsToEndpoint, optionsToTriggerAnnotations } from "../options.mjs";
|
|
12
12
|
import cors from "cors";
|
|
@@ -50,18 +50,12 @@ function onRequest(optsOrHandler, handler) {
|
|
|
50
50
|
}
|
|
51
51
|
handler = withErrorHandler(handler);
|
|
52
52
|
if (isDebugFeatureEnabled("enableCors") || "cors" in opts) {
|
|
53
|
-
let origin = opts.cors instanceof Expression ? opts.cors.value() : opts.cors;
|
|
54
|
-
if (isDebugFeatureEnabled("enableCors")) {
|
|
55
|
-
origin = opts.cors === false ? false : true;
|
|
56
|
-
}
|
|
57
|
-
if (Array.isArray(origin) && origin.length === 1) {
|
|
58
|
-
origin = origin[0];
|
|
59
|
-
}
|
|
60
|
-
const middleware = cors({ origin });
|
|
61
53
|
const userProvidedHandler = handler;
|
|
62
54
|
handler = (req, res) => {
|
|
63
55
|
return new Promise((resolve) => {
|
|
64
56
|
res.on("finish", resolve);
|
|
57
|
+
const origin = resolveCorsOrigin(opts.cors);
|
|
58
|
+
const middleware = cors({ origin });
|
|
65
59
|
middleware(req, res, () => {
|
|
66
60
|
resolve(userProvidedHandler(req, res));
|
|
67
61
|
});
|
|
@@ -71,7 +65,7 @@ function onRequest(optsOrHandler, handler) {
|
|
|
71
65
|
handler = wrapTraceContext(withInit(handler));
|
|
72
66
|
Object.defineProperty(handler, "__trigger", { get: () => {
|
|
73
67
|
const baseOpts$1 = optionsToTriggerAnnotations(getGlobalOptions());
|
|
74
|
-
const specificOpts$1 = optionsToTriggerAnnotations(opts);
|
|
68
|
+
const specificOpts$1 = optionsToTriggerAnnotations(opts, "https");
|
|
75
69
|
const trigger = {
|
|
76
70
|
platform: "gcfv2",
|
|
77
71
|
...baseOpts$1,
|
|
@@ -88,7 +82,7 @@ function onRequest(optsOrHandler, handler) {
|
|
|
88
82
|
} });
|
|
89
83
|
const globalOpts = getGlobalOptions();
|
|
90
84
|
const baseOpts = optionsToEndpoint(globalOpts);
|
|
91
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
85
|
+
const specificOpts = optionsToEndpoint(opts, "https");
|
|
92
86
|
const endpoint = {
|
|
93
87
|
...initV2Endpoint(globalOpts, opts),
|
|
94
88
|
platform: "gcfv2",
|
|
@@ -115,18 +109,10 @@ function onCall(optsOrHandler, handler) {
|
|
|
115
109
|
}
|
|
116
110
|
let cors$1;
|
|
117
111
|
if ("cors" in opts) {
|
|
118
|
-
|
|
119
|
-
cors$1 = opts.cors.value();
|
|
120
|
-
} else {
|
|
121
|
-
cors$1 = opts.cors;
|
|
122
|
-
}
|
|
112
|
+
cors$1 = opts.cors;
|
|
123
113
|
} else {
|
|
124
114
|
cors$1 = true;
|
|
125
115
|
}
|
|
126
|
-
let origin = isDebugFeatureEnabled("enableCors") ? true : cors$1;
|
|
127
|
-
if (Array.isArray(origin) && origin.length === 1) {
|
|
128
|
-
origin = origin[0];
|
|
129
|
-
}
|
|
130
116
|
const fixedLen = (req, resp) => handler(req, resp);
|
|
131
117
|
let enforceAppCheck = opts.enforceAppCheck ?? getGlobalOptions().enforceAppCheck;
|
|
132
118
|
if (enforceAppCheck instanceof Expression) {
|
|
@@ -138,7 +124,7 @@ function onCall(optsOrHandler, handler) {
|
|
|
138
124
|
}
|
|
139
125
|
let func = onCallHandler({
|
|
140
126
|
cors: {
|
|
141
|
-
origin,
|
|
127
|
+
origin: cors$1,
|
|
142
128
|
methods: "POST"
|
|
143
129
|
},
|
|
144
130
|
enforceAppCheck,
|
|
@@ -149,7 +135,7 @@ function onCall(optsOrHandler, handler) {
|
|
|
149
135
|
func = wrapTraceContext(withInit(func));
|
|
150
136
|
Object.defineProperty(func, "__trigger", { get: () => {
|
|
151
137
|
const baseOpts$1 = optionsToTriggerAnnotations(getGlobalOptions());
|
|
152
|
-
const specificOpts$1 = optionsToTriggerAnnotations(opts);
|
|
138
|
+
const specificOpts$1 = optionsToTriggerAnnotations(opts, "https");
|
|
153
139
|
return {
|
|
154
140
|
platform: "gcfv2",
|
|
155
141
|
...baseOpts$1,
|
|
@@ -163,7 +149,7 @@ function onCall(optsOrHandler, handler) {
|
|
|
163
149
|
};
|
|
164
150
|
} });
|
|
165
151
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
166
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
152
|
+
const specificOpts = optionsToEndpoint(opts, "https");
|
|
167
153
|
func.__endpoint = {
|
|
168
154
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
169
155
|
platform: "gcfv2",
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { __export } from "../../_virtual/rolldown_runtime.mjs";
|
|
2
|
+
import { RESET_VALUE } from "../../common/options.mjs";
|
|
2
3
|
import { initV2Endpoint } from "../../runtime/manifest.mjs";
|
|
3
4
|
import { withInit } from "../../common/onInit.mjs";
|
|
4
5
|
import { HttpsError } from "../../common/providers/https.mjs";
|
|
5
|
-
import { wrapHandler } from "../../common/providers/identity.mjs";
|
|
6
|
+
import { userRecordConstructor, wrapHandler } from "../../common/providers/identity.mjs";
|
|
6
7
|
import { wrapTraceContext } from "../trace.mjs";
|
|
7
8
|
import { getGlobalOptions, optionsToEndpoint } from "../options.mjs";
|
|
8
9
|
|
|
9
10
|
//#region src/v2/providers/identity.ts
|
|
10
11
|
var identity_exports = /* @__PURE__ */ __export({
|
|
11
12
|
HttpsError: () => HttpsError,
|
|
13
|
+
IS_NOT_TENANT: () => IS_NOT_TENANT,
|
|
12
14
|
beforeEmailSent: () => beforeEmailSent,
|
|
13
15
|
beforeOperation: () => beforeOperation,
|
|
14
16
|
beforeSmsSent: () => beforeSmsSent,
|
|
15
17
|
beforeUserCreated: () => beforeUserCreated,
|
|
16
18
|
beforeUserSignedIn: () => beforeUserSignedIn,
|
|
17
|
-
getOpts: () => getOpts
|
|
19
|
+
getOpts: () => getOpts,
|
|
20
|
+
onUserCreated: () => onUserCreated,
|
|
21
|
+
onUserDeleted: () => onUserDeleted
|
|
18
22
|
});
|
|
19
23
|
/**
|
|
20
24
|
* Handles an event that is triggered before a user is created.
|
|
@@ -60,7 +64,7 @@ function beforeOperation(eventType, optsOrHandler, handler) {
|
|
|
60
64
|
const legacyEventType = `providers/cloud.auth/eventTypes/user.${eventType}`;
|
|
61
65
|
/** Endpoint */
|
|
62
66
|
const baseOptsEndpoint = optionsToEndpoint(getGlobalOptions());
|
|
63
|
-
const specificOptsEndpoint = optionsToEndpoint(opts);
|
|
67
|
+
const specificOptsEndpoint = optionsToEndpoint(opts, "identity");
|
|
64
68
|
func.__endpoint = {
|
|
65
69
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
66
70
|
platform: "gcfv2",
|
|
@@ -98,6 +102,87 @@ function getOpts(blockingOptions) {
|
|
|
98
102
|
refreshToken
|
|
99
103
|
};
|
|
100
104
|
}
|
|
105
|
+
const IS_NOT_TENANT = RESET_VALUE;
|
|
106
|
+
function getOptsAndHandler(optsOrHandler, handler) {
|
|
107
|
+
if (typeof optsOrHandler === "function") {
|
|
108
|
+
return {
|
|
109
|
+
opts: {},
|
|
110
|
+
handler: optsOrHandler
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
opts: optsOrHandler,
|
|
115
|
+
handler
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const PROJECT_ID_REGEX = /(?:^|\/)projects\/([^\/]+)/;
|
|
119
|
+
/** @hidden */
|
|
120
|
+
function getAuthEvent(raw) {
|
|
121
|
+
const event = { ...raw };
|
|
122
|
+
if (raw.data) {
|
|
123
|
+
event.data = userRecordConstructor(raw.data);
|
|
124
|
+
}
|
|
125
|
+
const rawAny = raw;
|
|
126
|
+
const tenantId = rawAny.tenantid || rawAny.tenantId;
|
|
127
|
+
if (tenantId) {
|
|
128
|
+
event.tenantId = tenantId;
|
|
129
|
+
}
|
|
130
|
+
if (raw.source) {
|
|
131
|
+
const match = raw.source.match(PROJECT_ID_REGEX);
|
|
132
|
+
if (match) {
|
|
133
|
+
event.project = match[1];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return event;
|
|
137
|
+
}
|
|
138
|
+
/** @hidden */
|
|
139
|
+
function makeAuthTrigger(eventType, optsOrHandler, handler) {
|
|
140
|
+
const { opts, handler: handlerFunc } = getOptsAndHandler(optsOrHandler, handler);
|
|
141
|
+
if (typeof handlerFunc !== "function") {
|
|
142
|
+
throw new Error("The handler must be a function.");
|
|
143
|
+
}
|
|
144
|
+
const wrappedHandler = wrapTraceContext(withInit(handlerFunc));
|
|
145
|
+
const func = ((raw) => {
|
|
146
|
+
const event = getAuthEvent(raw);
|
|
147
|
+
return wrappedHandler(event);
|
|
148
|
+
});
|
|
149
|
+
func.run = handlerFunc;
|
|
150
|
+
const baseOptsEndpoint = optionsToEndpoint(getGlobalOptions());
|
|
151
|
+
const specificOptsEndpoint = optionsToEndpoint(opts);
|
|
152
|
+
const endpoint = {
|
|
153
|
+
...initV2Endpoint(getGlobalOptions(), opts),
|
|
154
|
+
platform: "gcfv2",
|
|
155
|
+
...baseOptsEndpoint,
|
|
156
|
+
...specificOptsEndpoint,
|
|
157
|
+
labels: {
|
|
158
|
+
...baseOptsEndpoint?.labels,
|
|
159
|
+
...specificOptsEndpoint?.labels
|
|
160
|
+
},
|
|
161
|
+
eventTrigger: {
|
|
162
|
+
eventType,
|
|
163
|
+
eventFilters: {},
|
|
164
|
+
retry: opts.retry ?? false,
|
|
165
|
+
region: "global"
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
if (opts.tenantId !== undefined) {
|
|
169
|
+
if (opts.tenantId === IS_NOT_TENANT) {
|
|
170
|
+
endpoint.eventTrigger.eventFilters["tenantid"] = "";
|
|
171
|
+
} else {
|
|
172
|
+
endpoint.eventTrigger.eventFilters["tenantid"] = opts.tenantId;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
func.__endpoint = endpoint;
|
|
176
|
+
return func;
|
|
177
|
+
}
|
|
178
|
+
const USER_CREATED_EVENT = "google.firebase.auth.user.v2.created";
|
|
179
|
+
function onUserCreated(optsOrHandler, handler) {
|
|
180
|
+
return makeAuthTrigger(USER_CREATED_EVENT, optsOrHandler, handler);
|
|
181
|
+
}
|
|
182
|
+
const USER_DELETED_EVENT = "google.firebase.auth.user.v2.deleted";
|
|
183
|
+
function onUserDeleted(optsOrHandler, handler) {
|
|
184
|
+
return makeAuthTrigger(USER_DELETED_EVENT, optsOrHandler, handler);
|
|
185
|
+
}
|
|
101
186
|
|
|
102
187
|
//#endregion
|
|
103
|
-
export { HttpsError, beforeEmailSent, beforeOperation, beforeSmsSent, beforeUserCreated, beforeUserSignedIn, getOpts, identity_exports };
|
|
188
|
+
export { HttpsError, IS_NOT_TENANT, beforeEmailSent, beforeOperation, beforeSmsSent, beforeUserCreated, beforeUserSignedIn, getOpts, identity_exports, onUserCreated, onUserDeleted };
|
|
@@ -90,7 +90,7 @@ var Message = class {
|
|
|
90
90
|
function onMessagePublished(topicOrOptions, handler) {
|
|
91
91
|
let topic;
|
|
92
92
|
let opts;
|
|
93
|
-
if (typeof topicOrOptions === "string") {
|
|
93
|
+
if (typeof topicOrOptions === "string" || "value" in topicOrOptions) {
|
|
94
94
|
topic = topicOrOptions;
|
|
95
95
|
opts = {};
|
|
96
96
|
} else {
|
|
@@ -145,7 +145,7 @@ function onMessagePublished(topicOrOptions, handler) {
|
|
|
145
145
|
func.run = handler;
|
|
146
146
|
Object.defineProperty(func, "__trigger", { get: () => {
|
|
147
147
|
const baseOpts$1 = optionsToTriggerAnnotations(getGlobalOptions());
|
|
148
|
-
const specificOpts$1 = optionsToTriggerAnnotations(opts);
|
|
148
|
+
const specificOpts$1 = optionsToTriggerAnnotations(opts, "event");
|
|
149
149
|
return {
|
|
150
150
|
platform: "gcfv2",
|
|
151
151
|
...baseOpts$1,
|
|
@@ -156,12 +156,12 @@ function onMessagePublished(topicOrOptions, handler) {
|
|
|
156
156
|
},
|
|
157
157
|
eventTrigger: {
|
|
158
158
|
eventType: "google.cloud.pubsub.topic.v1.messagePublished",
|
|
159
|
-
resource: `projects/${process.env.GCLOUD_PROJECT}/topics/${topic}`
|
|
159
|
+
...typeof topic === "string" && { resource: `projects/${process.env.GCLOUD_PROJECT}/topics/${topic}` }
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
162
|
} });
|
|
163
163
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
164
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
164
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
165
165
|
const endpoint = {
|
|
166
166
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
167
167
|
platform: "gcfv2",
|
|
@@ -25,7 +25,7 @@ function onConfigUpdated(optsOrHandler, handler) {
|
|
|
25
25
|
optsOrHandler = {};
|
|
26
26
|
}
|
|
27
27
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
28
|
-
const specificOpts = optionsToEndpoint(optsOrHandler);
|
|
28
|
+
const specificOpts = optionsToEndpoint(optsOrHandler, "event");
|
|
29
29
|
const func = wrapTraceContext(withInit((raw) => {
|
|
30
30
|
const event = raw;
|
|
31
31
|
const patchedEvent = addV1Compat(event, {
|
|
@@ -70,7 +70,7 @@ function onSchedule(args, handler) {
|
|
|
70
70
|
func.run = handler;
|
|
71
71
|
const globalOpts = getGlobalOptions();
|
|
72
72
|
const baseOptsEndpoint = optionsToEndpoint(globalOpts);
|
|
73
|
-
const specificOptsEndpoint = optionsToEndpoint(separatedOpts.opts);
|
|
73
|
+
const specificOptsEndpoint = optionsToEndpoint(separatedOpts.opts, "event");
|
|
74
74
|
const ep = {
|
|
75
75
|
...initV2Endpoint(globalOpts, separatedOpts.opts),
|
|
76
76
|
platform: "gcfv2",
|
|
@@ -114,7 +114,7 @@ function onOperation(eventType, bucketOrOptsOrHandler, handler) {
|
|
|
114
114
|
func.run = handler;
|
|
115
115
|
Object.defineProperty(func, "__trigger", { get: () => {
|
|
116
116
|
const baseOpts = optionsToTriggerAnnotations(getGlobalOptions());
|
|
117
|
-
const specificOpts = optionsToTriggerAnnotations(opts);
|
|
117
|
+
const specificOpts = optionsToTriggerAnnotations(opts, "event");
|
|
118
118
|
return {
|
|
119
119
|
platform: "gcfv2",
|
|
120
120
|
...baseOpts,
|
|
@@ -132,7 +132,7 @@ function onOperation(eventType, bucketOrOptsOrHandler, handler) {
|
|
|
132
132
|
func.__endpoint = {};
|
|
133
133
|
Object.defineProperty(func, "__endpoint", { get: () => {
|
|
134
134
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
135
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
135
|
+
const specificOpts = optionsToEndpoint(opts, "event");
|
|
136
136
|
const endpoint = {
|
|
137
137
|
platform: "gcfv2",
|
|
138
138
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
@@ -20,7 +20,7 @@ function onTaskDispatched(optsOrHandler, handler) {
|
|
|
20
20
|
const func = wrapTraceContext(withInit(onDispatchHandler(fixedLen)));
|
|
21
21
|
Object.defineProperty(func, "__trigger", { get: () => {
|
|
22
22
|
const baseOpts$1 = optionsToTriggerAnnotations(getGlobalOptions());
|
|
23
|
-
const specificOpts$1 = optionsToTriggerAnnotations(opts);
|
|
23
|
+
const specificOpts$1 = optionsToTriggerAnnotations(opts, "task");
|
|
24
24
|
const taskQueueTrigger = {};
|
|
25
25
|
copyIfPresent(taskQueueTrigger, opts, "retryConfig", "rateLimits");
|
|
26
26
|
convertIfPresent(taskQueueTrigger, getGlobalOptions(), "invoker", "invoker", convertInvoker);
|
|
@@ -37,7 +37,7 @@ function onTaskDispatched(optsOrHandler, handler) {
|
|
|
37
37
|
};
|
|
38
38
|
} });
|
|
39
39
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
40
|
-
const specificOpts = optionsToEndpoint(opts);
|
|
40
|
+
const specificOpts = optionsToEndpoint(opts, "task");
|
|
41
41
|
func.__endpoint = {
|
|
42
42
|
platform: "gcfv2",
|
|
43
43
|
...initV2Endpoint(getGlobalOptions(), opts),
|
|
@@ -25,7 +25,7 @@ function onTestMatrixCompleted(optsOrHandler, handler) {
|
|
|
25
25
|
optsOrHandler = {};
|
|
26
26
|
}
|
|
27
27
|
const baseOpts = optionsToEndpoint(getGlobalOptions());
|
|
28
|
-
const specificOpts = optionsToEndpoint(optsOrHandler);
|
|
28
|
+
const specificOpts = optionsToEndpoint(optsOrHandler, "event");
|
|
29
29
|
const func = (raw) => {
|
|
30
30
|
return wrapTraceContext(withInit(handler))(raw);
|
|
31
31
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { registerRole } from "../security/roles.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/v2/security.ts
|
|
4
|
+
/**
|
|
5
|
+
* Declares that this codebase requires the specified IAM role to operate.
|
|
6
|
+
* When deployed, the Firebase CLI will automatically provision a managed service account
|
|
7
|
+
* with this role and attach it to all functions in this codebase.
|
|
8
|
+
* @param role The IAM role required (e.g. "roles/bigquery.dataEditor")
|
|
9
|
+
*/
|
|
10
|
+
function requiresRole(role) {
|
|
11
|
+
const roleRegex = /^(roles\/[a-zA-Z0-9_.-]+|projects\/[a-zA-Z0-9_-]+\/roles\/[a-zA-Z0-9_.-]+|organizations\/[a-zA-Z0-9_-]+\/roles\/[a-zA-Z0-9_.-]+)$/;
|
|
12
|
+
if (!roleRegex.test(role)) {
|
|
13
|
+
throw new Error(`Invalid role: "${role}". Role must be a valid GCP IAM role format (e.g., "roles/viewer", "projects/<project-id>/roles/<custom-role>", or "organizations/<org-id>/roles/<custom-role>").`);
|
|
14
|
+
}
|
|
15
|
+
registerRole(role);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { requiresRole };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface TaskAction {
|
|
2
|
+
function: string;
|
|
3
|
+
body?: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
export interface CallAction {
|
|
6
|
+
function: string;
|
|
7
|
+
params?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export type HttpAction = ({
|
|
10
|
+
function: string;
|
|
11
|
+
} | {
|
|
12
|
+
url: string;
|
|
13
|
+
}) & {
|
|
14
|
+
method?: "GET" | "POST" | "PUT" | "DELETE";
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
body?: unknown;
|
|
17
|
+
};
|
|
18
|
+
export type LifecycleAction = {
|
|
19
|
+
task: TaskAction;
|
|
20
|
+
call?: never;
|
|
21
|
+
http?: never;
|
|
22
|
+
} | {
|
|
23
|
+
call: CallAction;
|
|
24
|
+
task?: never;
|
|
25
|
+
http?: never;
|
|
26
|
+
} | {
|
|
27
|
+
http: HttpAction;
|
|
28
|
+
task?: never;
|
|
29
|
+
call?: never;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Registers an action to be executed automatically post-deployment when resources in this codebase
|
|
33
|
+
* are deployed for the first time.
|
|
34
|
+
*
|
|
35
|
+
* @param action The lifecycle action to execute.
|
|
36
|
+
*/
|
|
37
|
+
export declare function afterFirstDeploy(action: LifecycleAction): void;
|
|
38
|
+
/**
|
|
39
|
+
* Registers an action to be executed automatically post-deployment when resources in this codebase
|
|
40
|
+
* are updated.
|
|
41
|
+
*
|
|
42
|
+
* @param action The lifecycle action to execute.
|
|
43
|
+
*/
|
|
44
|
+
export declare function afterRedeploy(action: LifecycleAction): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/lifecycle/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Use a global singleton to manage the list of declared lifecycle hooks.
|
|
5
|
+
*
|
|
6
|
+
* This ensures that lifecycle hooks are shared between CJS and ESM builds,
|
|
7
|
+
* avoiding the "dual-package hazard" where the src/bin/firebase-functions.ts (CJS) sees
|
|
8
|
+
* an empty list while the user's code (ESM) populates a different list.
|
|
9
|
+
*/
|
|
10
|
+
const majorVersion = typeof "7" !== "undefined" ? "7" : "0";
|
|
11
|
+
const GLOBAL_SYMBOL = Symbol.for(`firebase-functions:lifecycle:declaredHooks:v${majorVersion}`);
|
|
12
|
+
const globalSymbols = globalThis;
|
|
13
|
+
if (!globalSymbols[GLOBAL_SYMBOL]) {
|
|
14
|
+
globalSymbols[GLOBAL_SYMBOL] = {};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Singleton dictionary of declared lifecycle hooks.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
const declaredLifecycleHooks = globalSymbols[GLOBAL_SYMBOL];
|
|
21
|
+
/**
|
|
22
|
+
* Registers an action to be executed automatically post-deployment when resources in this codebase
|
|
23
|
+
* are deployed for the first time.
|
|
24
|
+
*
|
|
25
|
+
* @param action The lifecycle action to execute.
|
|
26
|
+
*/
|
|
27
|
+
function afterFirstDeploy(action) {
|
|
28
|
+
if (declaredLifecycleHooks.afterFirstDeploy) {
|
|
29
|
+
throw new Error("Only one afterFirstDeploy lifecycle hook is allowed per codebase.");
|
|
30
|
+
}
|
|
31
|
+
declaredLifecycleHooks.afterFirstDeploy = action;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Registers an action to be executed automatically post-deployment when resources in this codebase
|
|
35
|
+
* are updated.
|
|
36
|
+
*
|
|
37
|
+
* @param action The lifecycle action to execute.
|
|
38
|
+
*/
|
|
39
|
+
function afterRedeploy(action) {
|
|
40
|
+
if (declaredLifecycleHooks.afterRedeploy) {
|
|
41
|
+
throw new Error("Only one afterRedeploy lifecycle hook is allowed per codebase.");
|
|
42
|
+
}
|
|
43
|
+
declaredLifecycleHooks.afterRedeploy = action;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Helper to clear declared lifecycle hooks.
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
function clearDeclaredLifecycleHooks() {
|
|
50
|
+
for (const key of Object.keys(declaredLifecycleHooks)) {
|
|
51
|
+
delete declaredLifecycleHooks[key];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
exports.afterFirstDeploy = afterFirstDeploy;
|
|
57
|
+
exports.afterRedeploy = afterRedeploy;
|
|
58
|
+
exports.clearDeclaredLifecycleHooks = clearDeclaredLifecycleHooks;
|
|
59
|
+
exports.declaredLifecycleHooks = declaredLifecycleHooks;
|
package/lib/logger/common.d.ts
CHANGED
|
@@ -4,9 +4,24 @@ export declare const CONSOLE_SEVERITY: {
|
|
|
4
4
|
};
|
|
5
5
|
/** @hidden */
|
|
6
6
|
export declare const UNPATCHED_CONSOLE: {
|
|
7
|
-
debug:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
debug: {
|
|
8
|
+
(...data: any[]): void;
|
|
9
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
10
|
+
};
|
|
11
|
+
info: {
|
|
12
|
+
(...data: any[]): void;
|
|
13
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
14
|
+
};
|
|
15
|
+
log: {
|
|
16
|
+
(...data: any[]): void;
|
|
17
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
18
|
+
};
|
|
19
|
+
warn: {
|
|
20
|
+
(...data: any[]): void;
|
|
21
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
22
|
+
};
|
|
23
|
+
error: {
|
|
24
|
+
(...data: any[]): void;
|
|
25
|
+
(message?: any, ...optionalParams: any[]): void;
|
|
26
|
+
};
|
|
12
27
|
};
|
package/lib/params/types.d.ts
CHANGED
|
@@ -84,7 +84,9 @@ export interface TextInput<T = unknown> {
|
|
|
84
84
|
* failing to conform to the validationRegex,
|
|
85
85
|
*/
|
|
86
86
|
validationErrorMessage?: string;
|
|
87
|
-
}
|
|
87
|
+
} & (T extends string | string[] ? {
|
|
88
|
+
nonEmpty?: boolean;
|
|
89
|
+
} : {});
|
|
88
90
|
}
|
|
89
91
|
/**
|
|
90
92
|
* Specifies that a parameter's value should be determined by having the user
|
|
@@ -117,6 +119,12 @@ export interface SelectInput<T = unknown> {
|
|
|
117
119
|
export interface MultiSelectInput {
|
|
118
120
|
multiSelect: {
|
|
119
121
|
options: Array<SelectOptions<string>>;
|
|
122
|
+
/**
|
|
123
|
+
* If set on an input for a string or string list param, nonEmpty prevents
|
|
124
|
+
* the prompt from accepting the empty string or empty list as valid input.
|
|
125
|
+
* Syntactic sugar over setting validationRegex to /.+/
|
|
126
|
+
*/
|
|
127
|
+
nonEmpty?: boolean;
|
|
120
128
|
};
|
|
121
129
|
}
|
|
122
130
|
/**
|
|
@@ -144,10 +152,8 @@ export type ParamSpec<T extends string | number | boolean | string[]> = {
|
|
|
144
152
|
};
|
|
145
153
|
/**
|
|
146
154
|
* Representation of parameters for the stack over the wire.
|
|
147
|
-
*
|
|
148
155
|
* @remarks
|
|
149
156
|
* N.B: a WireParamSpec is just a ParamSpec with default expressions converted into a CEL literal
|
|
150
|
-
*
|
|
151
157
|
* @alpha
|
|
152
158
|
*/
|
|
153
159
|
export type WireParamSpec<T extends string | number | boolean | string[]> = {
|
package/lib/runtime/loader.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
2
2
|
const require_params_index = require('../params/index.js');
|
|
3
|
+
const require_security_roles = require('../security/roles.js');
|
|
4
|
+
const require_common_api = require('../common/api.js');
|
|
5
|
+
const require_lifecycle_index = require('../lifecycle/index.js');
|
|
3
6
|
let path = require("path");
|
|
4
7
|
path = require_rolldown_runtime.__toESM(path);
|
|
5
8
|
let url = require("url");
|
|
@@ -9,9 +12,7 @@ url = require_rolldown_runtime.__toESM(url);
|
|
|
9
12
|
/**
|
|
10
13
|
* Dynamically load import function to prevent TypeScript from
|
|
11
14
|
* transpiling into a require.
|
|
12
|
-
*
|
|
13
15
|
* See https://github.com/microsoft/TypeScript/issues/43329.
|
|
14
|
-
*
|
|
15
16
|
*/
|
|
16
17
|
const dynamicImport = new Function("modulePath", "return import(modulePath)");
|
|
17
18
|
async function loadModule(functionsDir) {
|
|
@@ -118,6 +119,8 @@ async function loadStack(functionsDir) {
|
|
|
118
119
|
const extensions = {};
|
|
119
120
|
const mod = await loadModule(functionsDir);
|
|
120
121
|
extractStack(mod, endpoints, requiredAPIs, extensions);
|
|
122
|
+
requiredAPIs.push(...require_common_api.getGlobalRequiredAPIs());
|
|
123
|
+
require_common_api.clearGlobalRequiredAPIs();
|
|
121
124
|
const stack = {
|
|
122
125
|
endpoints,
|
|
123
126
|
specVersion: "v1alpha1",
|
|
@@ -127,6 +130,13 @@ async function loadStack(functionsDir) {
|
|
|
127
130
|
if (require_params_index.declaredParams.length > 0) {
|
|
128
131
|
stack.params = require_params_index.declaredParams.map((p) => p.toSpec());
|
|
129
132
|
}
|
|
133
|
+
if (require_security_roles.declaredRoles.size > 0) {
|
|
134
|
+
stack.requiredRoles = Array.from(require_security_roles.declaredRoles);
|
|
135
|
+
}
|
|
136
|
+
if (Object.keys(require_lifecycle_index.declaredLifecycleHooks).length > 0) {
|
|
137
|
+
stack.lifecycleHooks = { ...require_lifecycle_index.declaredLifecycleHooks };
|
|
138
|
+
}
|
|
139
|
+
require_lifecycle_index.clearDeclaredLifecycleHooks();
|
|
130
140
|
return stack;
|
|
131
141
|
}
|
|
132
142
|
|