firebase-tools 10.4.2 → 10.7.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.js +1 -1
- package/lib/command.js +4 -4
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/emulators-start.js +13 -3
- package/lib/commands/ext-configure.js +15 -5
- package/lib/commands/ext-dev-emulators-start.js +5 -1
- package/lib/commands/ext-export.js +6 -5
- package/lib/commands/ext-install.js +28 -44
- package/lib/commands/ext-update.js +9 -1
- package/lib/commands/functions-delete.js +2 -5
- package/lib/commands/functions-secrets-destroy.js +23 -3
- package/lib/commands/functions-secrets-prune.js +15 -12
- package/lib/commands/functions-secrets-set.js +51 -4
- package/lib/commands/hosting-channel-deploy.js +2 -2
- package/lib/deploy/database/deploy.js +4 -0
- package/lib/deploy/database/index.js +1 -0
- package/lib/deploy/extensions/deploy.js +4 -4
- package/lib/deploy/extensions/deploymentSummary.js +8 -5
- package/lib/deploy/extensions/planner.js +36 -9
- package/lib/deploy/extensions/prepare.js +1 -1
- package/lib/deploy/extensions/secrets.js +2 -2
- package/lib/deploy/extensions/tasks.js +60 -21
- package/lib/deploy/functions/backend.js +17 -6
- package/lib/deploy/functions/build.js +162 -0
- package/lib/deploy/functions/checkIam.js +6 -5
- package/lib/deploy/functions/deploy.js +14 -15
- package/lib/deploy/functions/ensure.js +4 -4
- package/lib/deploy/functions/functionsDeployHelper.js +54 -23
- package/lib/deploy/functions/prepare.js +92 -39
- package/lib/deploy/functions/prepareFunctionsUpload.js +16 -21
- package/lib/deploy/functions/pricing.js +6 -3
- package/lib/deploy/functions/prompts.js +1 -7
- package/lib/deploy/functions/release/fabricator.js +44 -5
- package/lib/deploy/functions/release/index.js +31 -6
- package/lib/deploy/functions/release/planner.js +10 -8
- package/lib/deploy/functions/release/reporter.js +14 -11
- package/lib/deploy/functions/runtimes/discovery/parsing.js +12 -6
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +61 -13
- package/lib/deploy/functions/runtimes/node/index.js +1 -1
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +29 -24
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/auth.js +95 -0
- package/lib/deploy/functions/services/index.js +41 -21
- package/lib/deploy/functions/services/storage.js +1 -6
- package/lib/deploy/functions/validate.js +8 -5
- package/lib/deploy/hosting/args.js +2 -0
- package/lib/deploy/hosting/convertConfig.js +37 -8
- package/lib/deploy/hosting/deploy.js +3 -3
- package/lib/deploy/hosting/prepare.js +2 -2
- package/lib/deploy/hosting/release.js +6 -2
- package/lib/deploy/index.js +82 -93
- package/lib/deploy/remoteconfig/deploy.js +4 -0
- package/lib/deploy/remoteconfig/index.js +3 -1
- package/lib/emulator/auth/operations.js +26 -20
- package/lib/emulator/auth/state.js +79 -43
- package/lib/emulator/auth/utils.js +3 -25
- package/lib/emulator/commandUtils.js +72 -2
- package/lib/emulator/controller.js +14 -5
- package/lib/emulator/downloadableEmulators.js +47 -24
- package/lib/emulator/extensions/postinstall.js +41 -0
- package/lib/emulator/extensions/validation.js +2 -2
- package/lib/emulator/extensionsEmulator.js +85 -21
- package/lib/emulator/functionsEmulator.js +79 -7
- package/lib/emulator/functionsEmulatorShared.js +36 -21
- package/lib/emulator/registry.js +34 -12
- package/lib/emulator/shared/request.js +19 -0
- package/lib/emulator/storage/apis/firebase.js +32 -35
- package/lib/emulator/storage/apis/gcloud.js +84 -66
- package/lib/emulator/storage/files.js +56 -52
- package/lib/emulator/storage/index.js +23 -3
- package/lib/emulator/storage/metadata.js +18 -8
- package/lib/emulator/storage/rules/manager.js +7 -17
- package/lib/emulator/storage/rules/utils.js +11 -3
- package/lib/emulator/storage/server.js +38 -12
- package/lib/ensureApiEnabled.js +8 -4
- package/lib/extensions/askUserForParam.js +14 -11
- package/lib/extensions/changelog.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +9 -10
- package/lib/extensions/emulator/specHelper.js +7 -1
- package/lib/extensions/emulator/triggerHelper.js +11 -14
- package/lib/extensions/extensionsApi.js +2 -1
- package/lib/extensions/extensionsHelper.js +30 -24
- package/lib/extensions/manifest.js +28 -8
- package/lib/extensions/paramHelper.js +19 -13
- package/lib/extensions/provisioningHelper.js +2 -2
- package/lib/extensions/warnings.js +3 -3
- package/lib/functions/env.js +10 -2
- package/lib/functions/events/index.js +7 -0
- package/lib/functions/events/v1.js +6 -0
- package/lib/functions/projectConfig.js +24 -3
- package/lib/functions/runtimeConfigExport.js +10 -6
- package/lib/functions/secrets.js +99 -6
- package/lib/gcp/cloudfunctions.js +37 -18
- package/lib/gcp/cloudfunctionsv2.js +41 -25
- package/lib/gcp/cloudtasks.js +5 -3
- package/lib/gcp/identityPlatform.js +44 -0
- package/lib/gcp/secretManager.js +2 -2
- package/lib/metaprogramming.js +2 -0
- package/lib/previews.js +1 -1
- package/lib/serve/hosting.js +25 -12
- package/lib/serve/index.js +6 -0
- package/lib/track.js +15 -21
- package/lib/utils.js +30 -1
- package/npm-shrinkwrap.json +44 -2
- package/package.json +4 -1
- package/schema/firebase-config.json +6 -0
- package/lib/emulator/storage/list.js +0 -18
|
@@ -4,7 +4,7 @@ exports.triggerTag = exports.printAbortedErrors = exports.printErrors = exports.
|
|
|
4
4
|
const backend = require("../backend");
|
|
5
5
|
const clc = require("cli-color");
|
|
6
6
|
const logger_1 = require("../../../logger");
|
|
7
|
-
const
|
|
7
|
+
const track_1 = require("../../../track");
|
|
8
8
|
const utils = require("../../../utils");
|
|
9
9
|
const functionsDeployHelper_1 = require("../functionsDeployHelper");
|
|
10
10
|
class DeploymentError extends Error {
|
|
@@ -36,23 +36,23 @@ async function logAndTrackDeployStats(summary) {
|
|
|
36
36
|
totalTime += result.durationMs;
|
|
37
37
|
if (!result.error) {
|
|
38
38
|
totalSuccesses++;
|
|
39
|
-
reports.push(
|
|
39
|
+
reports.push((0, track_1.track)("function_deploy_success", tag, result.durationMs));
|
|
40
40
|
}
|
|
41
41
|
else if (result.error instanceof AbortedDeploymentError) {
|
|
42
42
|
totalAborts++;
|
|
43
|
-
reports.push(
|
|
43
|
+
reports.push((0, track_1.track)("function_deploy_abort", tag, result.durationMs));
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
46
|
totalErrors++;
|
|
47
|
-
reports.push(
|
|
47
|
+
reports.push((0, track_1.track)("function_deploy_failure", tag, result.durationMs));
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
const regionCountTag = regions.size < 5 ? regions.size.toString() : ">=5";
|
|
51
|
-
reports.push(
|
|
51
|
+
reports.push((0, track_1.track)("functions_region_count", regionCountTag, 1));
|
|
52
52
|
const gcfv1 = summary.results.find((r) => r.endpoint.platform === "gcfv1");
|
|
53
53
|
const gcfv2 = summary.results.find((r) => r.endpoint.platform === "gcfv2");
|
|
54
54
|
const tag = gcfv1 && gcfv2 ? "v1+v2" : gcfv1 ? "v1" : "v2";
|
|
55
|
-
reports.push(
|
|
55
|
+
reports.push((0, track_1.track)("functions_codebase_deploy", tag, summary.results.length));
|
|
56
56
|
const avgTime = totalTime / (totalSuccesses + totalErrors);
|
|
57
57
|
logger_1.logger.debug(`Total Function Deployment time: ${summary.totalTime}`);
|
|
58
58
|
logger_1.logger.debug(`${totalErrors + totalSuccesses + totalAborts} Functions Deployed`);
|
|
@@ -61,15 +61,15 @@ async function logAndTrackDeployStats(summary) {
|
|
|
61
61
|
logger_1.logger.debug(`Average Function Deployment time: ${avgTime}`);
|
|
62
62
|
if (totalErrors + totalSuccesses > 0) {
|
|
63
63
|
if (totalErrors === 0) {
|
|
64
|
-
reports.push(
|
|
64
|
+
reports.push((0, track_1.track)("functions_deploy_result", "success", totalSuccesses));
|
|
65
65
|
}
|
|
66
66
|
else if (totalSuccesses > 0) {
|
|
67
|
-
reports.push(
|
|
68
|
-
reports.push(
|
|
69
|
-
reports.push(
|
|
67
|
+
reports.push((0, track_1.track)("functions_deploy_result", "partial_success", totalSuccesses));
|
|
68
|
+
reports.push((0, track_1.track)("functions_deploy_result", "partial_failure", totalErrors));
|
|
69
|
+
reports.push((0, track_1.track)("functions_deploy_result", "partial_error_ratio", totalErrors / (totalSuccesses + totalErrors)));
|
|
70
70
|
}
|
|
71
71
|
else {
|
|
72
|
-
reports.push(
|
|
72
|
+
reports.push((0, track_1.track)("functions_deploy_result", "failure", totalErrors));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
await utils.allSettled(reports);
|
|
@@ -171,6 +171,9 @@ function triggerTag(endpoint) {
|
|
|
171
171
|
}
|
|
172
172
|
return `${prefix}.https`;
|
|
173
173
|
}
|
|
174
|
+
if (backend.isBlockingTriggered(endpoint)) {
|
|
175
|
+
return `${prefix}.blocking`;
|
|
176
|
+
}
|
|
174
177
|
return endpoint.eventTrigger.eventType;
|
|
175
178
|
}
|
|
176
179
|
exports.triggerTag = triggerTag;
|
|
@@ -19,31 +19,37 @@ function assertKeyTypes(prefix, yaml, schema) {
|
|
|
19
19
|
}
|
|
20
20
|
for (const [keyAsString, value] of Object.entries(yaml)) {
|
|
21
21
|
const key = keyAsString;
|
|
22
|
-
const fullKey = prefix ? prefix
|
|
22
|
+
const fullKey = prefix ? `${prefix}.${keyAsString}` : keyAsString;
|
|
23
23
|
if (!schema[key] || schema[key] === "omit") {
|
|
24
24
|
throw new error_1.FirebaseError(`Unexpected key ${fullKey}. You may need to install a newer version of the Firebase CLI.`);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
const schemaType = schema[key];
|
|
27
|
+
if (typeof schemaType === "function") {
|
|
28
|
+
if (!schemaType(value)) {
|
|
29
|
+
throw new error_1.FirebaseError(`${Array.isArray(value) ? "array" : typeof value} ${fullKey} failed validation`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (schemaType === "string") {
|
|
27
33
|
if (typeof value !== "string") {
|
|
28
34
|
throw new error_1.FirebaseError(`Expected ${fullKey} to be string; was ${typeof value}`);
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
|
-
else if (
|
|
37
|
+
else if (schemaType === "number") {
|
|
32
38
|
if (typeof value !== "number") {
|
|
33
39
|
throw new error_1.FirebaseError(`Expected ${fullKey} to be a number; was ${typeof value}`);
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
|
-
else if (
|
|
42
|
+
else if (schemaType === "boolean") {
|
|
37
43
|
if (typeof value !== "boolean") {
|
|
38
44
|
throw new error_1.FirebaseError(`Expected ${fullKey} to be a boolean; was ${typeof value}`);
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
|
-
else if (
|
|
47
|
+
else if (schemaType === "array") {
|
|
42
48
|
if (!Array.isArray(value)) {
|
|
43
49
|
throw new error_1.FirebaseError(`Expected ${fullKey} to be an array; was ${typeof value}`);
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
|
-
else if (
|
|
52
|
+
else if (schemaType === "object") {
|
|
47
53
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
48
54
|
throw new error_1.FirebaseError(`Expected ${fullKey} to be an object; was ${typeof value}`);
|
|
49
55
|
}
|
|
@@ -5,6 +5,12 @@ const backend = require("../../backend");
|
|
|
5
5
|
const proto_1 = require("../../../../gcp/proto");
|
|
6
6
|
const parsing_1 = require("./parsing");
|
|
7
7
|
const error_1 = require("../../../../error");
|
|
8
|
+
const CHANNEL_NAME_REGEX = new RegExp("(projects\\/" +
|
|
9
|
+
"(?<project>(?:\\d+)|(?:[A-Za-z]+[A-Za-z\\d-]*[A-Za-z\\d]?))\\/)?" +
|
|
10
|
+
"locations\\/" +
|
|
11
|
+
"(?<location>[A-Za-z\\d\\-_]+)\\/" +
|
|
12
|
+
"channels\\/" +
|
|
13
|
+
"(?<channel>[A-Za-z\\d\\-_]+)");
|
|
8
14
|
function backendFromV1Alpha1(yaml, project, region, runtime) {
|
|
9
15
|
const manifest = JSON.parse(JSON.stringify(yaml));
|
|
10
16
|
const bkend = backend.empty();
|
|
@@ -42,17 +48,17 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
42
48
|
const ep = manifest.endpoints[id];
|
|
43
49
|
(0, parsing_1.assertKeyTypes)(prefix, ep, {
|
|
44
50
|
region: "array",
|
|
45
|
-
platform:
|
|
51
|
+
platform: (platform) => backend.AllFunctionsPlatforms.includes(platform),
|
|
46
52
|
entryPoint: "string",
|
|
47
|
-
availableMemoryMb:
|
|
53
|
+
availableMemoryMb: (mem) => backend.AllMemoryOptions.includes(mem),
|
|
48
54
|
maxInstances: "number",
|
|
49
55
|
minInstances: "number",
|
|
50
56
|
concurrency: "number",
|
|
51
57
|
serviceAccountEmail: "string",
|
|
52
|
-
|
|
58
|
+
timeoutSeconds: "number",
|
|
53
59
|
vpc: "object",
|
|
54
60
|
labels: "object",
|
|
55
|
-
ingressSettings:
|
|
61
|
+
ingressSettings: (setting) => backend.AllIngressSettings.includes(setting),
|
|
56
62
|
environmentVariables: "object",
|
|
57
63
|
secretEnvironmentVariables: "array",
|
|
58
64
|
httpsTrigger: "object",
|
|
@@ -60,7 +66,16 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
60
66
|
eventTrigger: "object",
|
|
61
67
|
scheduleTrigger: "object",
|
|
62
68
|
taskQueueTrigger: "object",
|
|
69
|
+
blockingTrigger: "object",
|
|
70
|
+
cpu: (cpu) => typeof cpu === "number" || cpu === "gcf_gen1",
|
|
63
71
|
});
|
|
72
|
+
if (ep.vpc) {
|
|
73
|
+
(0, parsing_1.assertKeyTypes)(prefix + ".vpc", ep.vpc, {
|
|
74
|
+
connector: "string",
|
|
75
|
+
egressSettings: (setting) => backend.AllVpcEgressSettings.includes(setting),
|
|
76
|
+
});
|
|
77
|
+
(0, parsing_1.requireKeys)(prefix + ".vpc", ep.vpc, "connector");
|
|
78
|
+
}
|
|
64
79
|
let triggerCount = 0;
|
|
65
80
|
if (ep.httpsTrigger) {
|
|
66
81
|
triggerCount++;
|
|
@@ -77,6 +92,9 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
77
92
|
if (ep.taskQueueTrigger) {
|
|
78
93
|
triggerCount++;
|
|
79
94
|
}
|
|
95
|
+
if (ep.blockingTrigger) {
|
|
96
|
+
triggerCount++;
|
|
97
|
+
}
|
|
80
98
|
if (!triggerCount) {
|
|
81
99
|
throw new error_1.FirebaseError("Expected trigger in endpoint " + id);
|
|
82
100
|
}
|
|
@@ -88,16 +106,19 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
88
106
|
if (backend.isEventTriggered(ep)) {
|
|
89
107
|
(0, parsing_1.requireKeys)(prefix + ".eventTrigger", ep.eventTrigger, "eventType", "eventFilters");
|
|
90
108
|
(0, parsing_1.assertKeyTypes)(prefix + ".eventTrigger", ep.eventTrigger, {
|
|
91
|
-
eventFilters: "
|
|
109
|
+
eventFilters: "object",
|
|
110
|
+
eventFilterPathPatterns: "object",
|
|
92
111
|
eventType: "string",
|
|
93
112
|
retry: "boolean",
|
|
94
113
|
region: "string",
|
|
95
114
|
serviceAccountEmail: "string",
|
|
115
|
+
channel: "string",
|
|
96
116
|
});
|
|
97
117
|
triggered = { eventTrigger: ep.eventTrigger };
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
(0, proto_1.renameIfPresent)(triggered.eventTrigger, ep.eventTrigger, "channel", "channel", (c) => resolveChannelName(project, c, defaultRegion));
|
|
119
|
+
for (const [k, v] of Object.entries(triggered.eventTrigger.eventFilters)) {
|
|
120
|
+
if (k === "topic" && !v.startsWith("projects/")) {
|
|
121
|
+
triggered.eventTrigger.eventFilters[k] = `projects/${project}/topics/${v}`;
|
|
101
122
|
}
|
|
102
123
|
}
|
|
103
124
|
}
|
|
@@ -134,7 +155,6 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
134
155
|
});
|
|
135
156
|
if (ep.taskQueueTrigger.rateLimits) {
|
|
136
157
|
(0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.rateLimits", ep.taskQueueTrigger.rateLimits, {
|
|
137
|
-
maxBurstSize: "number",
|
|
138
158
|
maxConcurrentDispatches: "number",
|
|
139
159
|
maxDispatchesPerSecond: "number",
|
|
140
160
|
});
|
|
@@ -142,14 +162,22 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
142
162
|
if (ep.taskQueueTrigger.retryConfig) {
|
|
143
163
|
(0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.retryConfig", ep.taskQueueTrigger.retryConfig, {
|
|
144
164
|
maxAttempts: "number",
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
165
|
+
maxRetrySeconds: "number",
|
|
166
|
+
minBackoffSeconds: "number",
|
|
167
|
+
maxBackoffSeconds: "number",
|
|
148
168
|
maxDoublings: "number",
|
|
149
169
|
});
|
|
150
170
|
}
|
|
151
171
|
triggered = { taskQueueTrigger: ep.taskQueueTrigger };
|
|
152
172
|
}
|
|
173
|
+
else if (backend.isBlockingTriggered(ep)) {
|
|
174
|
+
(0, parsing_1.requireKeys)(prefix + ".blockingTrigger", ep.blockingTrigger, "eventType");
|
|
175
|
+
(0, parsing_1.assertKeyTypes)(prefix + ".blockingTrigger", ep.blockingTrigger, {
|
|
176
|
+
eventType: "string",
|
|
177
|
+
options: "object",
|
|
178
|
+
});
|
|
179
|
+
triggered = { blockingTrigger: ep.blockingTrigger };
|
|
180
|
+
}
|
|
153
181
|
else {
|
|
154
182
|
throw new error_1.FirebaseError(`Do not recognize trigger type for endpoint ${id}. Try upgrading ` +
|
|
155
183
|
"firebase-tools with npm install -g firebase-tools@latest");
|
|
@@ -159,8 +187,28 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
|
|
|
159
187
|
region,
|
|
160
188
|
project,
|
|
161
189
|
runtime, entryPoint: ep.entryPoint }, triggered);
|
|
162
|
-
(0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "serviceAccountEmail", "
|
|
190
|
+
(0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "serviceAccountEmail", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables");
|
|
163
191
|
allParsed.push(parsed);
|
|
164
192
|
}
|
|
165
193
|
return allParsed;
|
|
166
194
|
}
|
|
195
|
+
function resolveChannelName(projectId, channel, defaultRegion) {
|
|
196
|
+
if (!channel.includes("/")) {
|
|
197
|
+
const location = defaultRegion;
|
|
198
|
+
const channelId = channel;
|
|
199
|
+
return "projects/" + projectId + "/locations/" + location + "/channels/" + channelId;
|
|
200
|
+
}
|
|
201
|
+
const match = CHANNEL_NAME_REGEX.exec(channel);
|
|
202
|
+
if (!(match === null || match === void 0 ? void 0 : match.groups)) {
|
|
203
|
+
throw new error_1.FirebaseError("Invalid channel name format.");
|
|
204
|
+
}
|
|
205
|
+
const matchedProjectId = match.groups.project;
|
|
206
|
+
const location = match.groups.location;
|
|
207
|
+
const channelId = match.groups.channel;
|
|
208
|
+
if (matchedProjectId) {
|
|
209
|
+
return "projects/" + matchedProjectId + "/locations/" + location + "/channels/" + channelId;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
return "projects/" + projectId + "/locations/" + location + "/channels/" + channelId;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -17,7 +17,7 @@ const discovery = require("../discovery");
|
|
|
17
17
|
const validate = require("./validate");
|
|
18
18
|
const versioning = require("./versioning");
|
|
19
19
|
const parseTriggers = require("./parseTriggers");
|
|
20
|
-
const MIN_FUNCTIONS_SDK_VERSION = "3.
|
|
20
|
+
const MIN_FUNCTIONS_SDK_VERSION = "3.20.0";
|
|
21
21
|
async function tryCreateDelegate(context) {
|
|
22
22
|
const packageJsonPath = path.join(context.sourceDir, "package.json");
|
|
23
23
|
if (!(await (0, util_1.promisify)(fs.exists)(packageJsonPath))) {
|
|
@@ -4,7 +4,7 @@ exports.getRuntimeChoice = exports.DEPRECATED_NODE_VERSION_INFO = exports.UNSUPP
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const clc = require("cli-color");
|
|
6
6
|
const error_1 = require("../../../../error");
|
|
7
|
-
const
|
|
7
|
+
const track_1 = require("../../../../track");
|
|
8
8
|
const runtimes = require("../../runtimes");
|
|
9
9
|
const cjson = require("cjson");
|
|
10
10
|
const ENGINE_RUNTIMES = {
|
|
@@ -46,11 +46,11 @@ function getRuntimeChoice(sourceDir, runtimeFromConfig) {
|
|
|
46
46
|
? exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG
|
|
47
47
|
: exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG) + exports.DEPRECATED_NODE_VERSION_INFO;
|
|
48
48
|
if (!runtime || !ENGINE_RUNTIMES_NAMES.includes(runtime)) {
|
|
49
|
-
void track("functions_runtime_notices", "package_missing_runtime");
|
|
49
|
+
void (0, track_1.track)("functions_runtime_notices", "package_missing_runtime");
|
|
50
50
|
throw new error_1.FirebaseError(errorMessage, { exit: 1 });
|
|
51
51
|
}
|
|
52
52
|
if (runtimes.isDeprecatedRuntime(runtime) || !runtimes.isValidRuntime(runtime)) {
|
|
53
|
-
void track("functions_runtime_notices", `${runtime}_deploy_prohibited`);
|
|
53
|
+
void (0, track_1.track)("functions_runtime_notices", `${runtime}_deploy_prohibited`);
|
|
54
54
|
throw new error_1.FirebaseError(errorMessage, { exit: 1 });
|
|
55
55
|
}
|
|
56
56
|
return runtime;
|
|
@@ -9,7 +9,7 @@ const logger_1 = require("../../../../logger");
|
|
|
9
9
|
const backend = require("../../backend");
|
|
10
10
|
const api = require("../../../../api");
|
|
11
11
|
const proto = require("../../../../gcp/proto");
|
|
12
|
-
const
|
|
12
|
+
const events = require("../../../../functions/events");
|
|
13
13
|
const TRIGGER_PARSER = path.resolve(__dirname, "./triggerParser.js");
|
|
14
14
|
function removeInspectOptions(options) {
|
|
15
15
|
return options.filter((opt) => !opt.startsWith("--inspect"));
|
|
@@ -62,7 +62,9 @@ function mergeRequiredAPIs(backend) {
|
|
|
62
62
|
const apiToReasons = {};
|
|
63
63
|
for (const { api, reason } of backend.requiredAPIs) {
|
|
64
64
|
const reasons = apiToReasons[api] || new Set();
|
|
65
|
-
|
|
65
|
+
if (reason) {
|
|
66
|
+
reasons.add(reason);
|
|
67
|
+
}
|
|
66
68
|
apiToReasons[api] = reasons;
|
|
67
69
|
}
|
|
68
70
|
const merged = [];
|
|
@@ -77,7 +79,10 @@ function addResourcesToBackend(projectId, runtime, annotation, want) {
|
|
|
77
79
|
Object.freeze(annotation);
|
|
78
80
|
for (const region of annotation.regions || [api.functionsDefaultRegion]) {
|
|
79
81
|
let triggered;
|
|
80
|
-
const triggerCount = +!!annotation.httpsTrigger +
|
|
82
|
+
const triggerCount = +!!annotation.httpsTrigger +
|
|
83
|
+
+!!annotation.eventTrigger +
|
|
84
|
+
+!!annotation.taskQueueTrigger +
|
|
85
|
+
+!!annotation.blockingTrigger;
|
|
81
86
|
if (triggerCount !== 1) {
|
|
82
87
|
throw new error_1.FirebaseError("Unexpected annotation generated by the Firebase Functions SDK. This should never happen.");
|
|
83
88
|
}
|
|
@@ -109,35 +114,34 @@ function addResourcesToBackend(projectId, runtime, annotation, want) {
|
|
|
109
114
|
});
|
|
110
115
|
triggered = { scheduleTrigger: annotation.schedule };
|
|
111
116
|
}
|
|
117
|
+
else if (annotation.blockingTrigger) {
|
|
118
|
+
if (events.v1.AUTH_BLOCKING_EVENTS.includes(annotation.blockingTrigger.eventType)) {
|
|
119
|
+
want.requiredAPIs.push({
|
|
120
|
+
api: "identitytoolkit.googleapis.com",
|
|
121
|
+
reason: "Needed for auth blocking functions.",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
triggered = {
|
|
125
|
+
blockingTrigger: {
|
|
126
|
+
eventType: annotation.blockingTrigger.eventType,
|
|
127
|
+
options: annotation.blockingTrigger.options,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
112
131
|
else {
|
|
113
132
|
triggered = {
|
|
114
133
|
eventTrigger: {
|
|
115
134
|
eventType: annotation.eventTrigger.eventType,
|
|
116
|
-
eventFilters:
|
|
117
|
-
{
|
|
118
|
-
attribute: "resource",
|
|
119
|
-
value: annotation.eventTrigger.resource,
|
|
120
|
-
},
|
|
121
|
-
],
|
|
135
|
+
eventFilters: { resource: annotation.eventTrigger.resource },
|
|
122
136
|
retry: !!annotation.failurePolicy,
|
|
123
137
|
},
|
|
124
138
|
};
|
|
125
139
|
if (annotation.platform === "gcfv2") {
|
|
126
|
-
if (annotation.eventTrigger.eventType ===
|
|
127
|
-
triggered.eventTrigger.eventFilters =
|
|
128
|
-
{
|
|
129
|
-
attribute: "topic",
|
|
130
|
-
value: annotation.eventTrigger.resource,
|
|
131
|
-
},
|
|
132
|
-
];
|
|
140
|
+
if (annotation.eventTrigger.eventType === events.v2.PUBSUB_PUBLISH_EVENT) {
|
|
141
|
+
triggered.eventTrigger.eventFilters = { topic: annotation.eventTrigger.resource };
|
|
133
142
|
}
|
|
134
|
-
if (
|
|
135
|
-
triggered.eventTrigger.eventFilters =
|
|
136
|
-
{
|
|
137
|
-
attribute: "bucket",
|
|
138
|
-
value: annotation.eventTrigger.resource,
|
|
139
|
-
},
|
|
140
|
-
];
|
|
143
|
+
if (events.v2.STORAGE_EVENTS.find((event) => { var _a; return event === (((_a = annotation.eventTrigger) === null || _a === void 0 ? void 0 : _a.eventType) || ""); })) {
|
|
144
|
+
triggered.eventTrigger.eventFilters = { bucket: annotation.eventTrigger.resource };
|
|
141
145
|
}
|
|
142
146
|
}
|
|
143
147
|
}
|
|
@@ -162,7 +166,8 @@ function addResourcesToBackend(projectId, runtime, annotation, want) {
|
|
|
162
166
|
}
|
|
163
167
|
endpoint.secretEnvironmentVariables = secretEnvs;
|
|
164
168
|
}
|
|
165
|
-
proto.copyIfPresent(endpoint, annotation, "concurrency", "serviceAccountEmail", "labels", "ingressSettings", "
|
|
169
|
+
proto.copyIfPresent(endpoint, annotation, "concurrency", "serviceAccountEmail", "labels", "ingressSettings", "maxInstances", "minInstances", "availableMemoryMb");
|
|
170
|
+
proto.renameIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
166
171
|
want.endpoints[region] = want.endpoints[region] || {};
|
|
167
172
|
want.endpoints[region][endpoint.id] = endpoint;
|
|
168
173
|
mergeRequiredAPIs(want);
|
|
@@ -7,7 +7,7 @@ const semver = require("semver");
|
|
|
7
7
|
const spawn = require("cross-spawn");
|
|
8
8
|
const utils = require("../../../../utils");
|
|
9
9
|
const logger_1 = require("../../../../logger");
|
|
10
|
-
const
|
|
10
|
+
const track_1 = require("../../../../track");
|
|
11
11
|
const MIN_SDK_VERSION = "2.0.0";
|
|
12
12
|
exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING = clc.bold.yellow("functions: ") +
|
|
13
13
|
"You must have a " +
|
|
@@ -52,7 +52,7 @@ exports.getLatestSDKVersion = getLatestSDKVersion;
|
|
|
52
52
|
function checkFunctionsSDKVersion(currentVersion) {
|
|
53
53
|
try {
|
|
54
54
|
if (semver.lt(currentVersion, MIN_SDK_VERSION)) {
|
|
55
|
-
void track("functions_runtime_notices", "functions_sdk_too_old");
|
|
55
|
+
void (0, track_1.track)("functions_runtime_notices", "functions_sdk_too_old");
|
|
56
56
|
utils.logWarning(exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING);
|
|
57
57
|
}
|
|
58
58
|
const latest = exports.getLatestSDKVersion();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthBlockingService = void 0;
|
|
4
|
+
const backend = require("../backend");
|
|
5
|
+
const identityPlatform = require("../../../gcp/identityPlatform");
|
|
6
|
+
const events = require("../../../functions/events");
|
|
7
|
+
const error_1 = require("../../../error");
|
|
8
|
+
const utils_1 = require("../../../utils");
|
|
9
|
+
const index_1 = require("./index");
|
|
10
|
+
class AuthBlockingService {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.name = "authblocking";
|
|
13
|
+
this.api = "identitytoolkit.googleapis.com";
|
|
14
|
+
this.triggerQueue = Promise.resolve();
|
|
15
|
+
this.ensureTriggerRegion = index_1.noop;
|
|
16
|
+
}
|
|
17
|
+
validateTrigger(endpoint, wantBackend) {
|
|
18
|
+
if (!backend.isBlockingTriggered(endpoint)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const blockingEndpoints = backend
|
|
22
|
+
.allEndpoints(wantBackend)
|
|
23
|
+
.filter((ep) => backend.isBlockingTriggered(ep));
|
|
24
|
+
if (blockingEndpoints.find((ep) => ep.blockingTrigger.eventType === endpoint.blockingTrigger.eventType &&
|
|
25
|
+
ep.id !== endpoint.id)) {
|
|
26
|
+
throw new error_1.FirebaseError(`Can only create at most one Auth Blocking Trigger for ${endpoint.blockingTrigger.eventType} events`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
configChanged(newConfig, config) {
|
|
30
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
31
|
+
if (((_b = (_a = newConfig.triggers) === null || _a === void 0 ? void 0 : _a.beforeCreate) === null || _b === void 0 ? void 0 : _b.functionUri) !==
|
|
32
|
+
((_d = (_c = config.triggers) === null || _c === void 0 ? void 0 : _c.beforeCreate) === null || _d === void 0 ? void 0 : _d.functionUri) ||
|
|
33
|
+
((_f = (_e = newConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeSignIn) === null || _f === void 0 ? void 0 : _f.functionUri) !== ((_h = (_g = config.triggers) === null || _g === void 0 ? void 0 : _g.beforeSignIn) === null || _h === void 0 ? void 0 : _h.functionUri)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (!!((_j = newConfig.forwardInboundCredentials) === null || _j === void 0 ? void 0 : _j.accessToken) !==
|
|
37
|
+
!!((_k = config.forwardInboundCredentials) === null || _k === void 0 ? void 0 : _k.accessToken) ||
|
|
38
|
+
!!((_l = newConfig.forwardInboundCredentials) === null || _l === void 0 ? void 0 : _l.idToken) !==
|
|
39
|
+
!!((_m = config.forwardInboundCredentials) === null || _m === void 0 ? void 0 : _m.idToken) ||
|
|
40
|
+
!!((_o = newConfig.forwardInboundCredentials) === null || _o === void 0 ? void 0 : _o.refreshToken) !==
|
|
41
|
+
!!((_p = config.forwardInboundCredentials) === null || _p === void 0 ? void 0 : _p.refreshToken)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
async registerTriggerLocked(endpoint) {
|
|
47
|
+
const newBlockingConfig = await identityPlatform.getBlockingFunctionsConfig(endpoint.project);
|
|
48
|
+
const oldBlockingConfig = (0, utils_1.cloneDeep)(newBlockingConfig);
|
|
49
|
+
if (endpoint.blockingTrigger.eventType === events.v1.BEFORE_CREATE_EVENT) {
|
|
50
|
+
newBlockingConfig.triggers = Object.assign(Object.assign({}, newBlockingConfig.triggers), { beforeCreate: {
|
|
51
|
+
functionUri: endpoint.uri,
|
|
52
|
+
} });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
newBlockingConfig.triggers = Object.assign(Object.assign({}, newBlockingConfig.triggers), { beforeSignIn: {
|
|
56
|
+
functionUri: endpoint.uri,
|
|
57
|
+
} });
|
|
58
|
+
}
|
|
59
|
+
newBlockingConfig.forwardInboundCredentials = Object.assign(Object.assign({}, oldBlockingConfig.forwardInboundCredentials), endpoint.blockingTrigger.options);
|
|
60
|
+
if (!this.configChanged(newBlockingConfig, oldBlockingConfig)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await identityPlatform.setBlockingFunctionsConfig(endpoint.project, newBlockingConfig);
|
|
64
|
+
}
|
|
65
|
+
registerTrigger(ep) {
|
|
66
|
+
if (!backend.isBlockingTriggered(ep)) {
|
|
67
|
+
return Promise.resolve();
|
|
68
|
+
}
|
|
69
|
+
this.triggerQueue = this.triggerQueue.then(() => this.registerTriggerLocked(ep));
|
|
70
|
+
return this.triggerQueue;
|
|
71
|
+
}
|
|
72
|
+
async unregisterTriggerLocked(endpoint) {
|
|
73
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
74
|
+
const blockingConfig = await identityPlatform.getBlockingFunctionsConfig(endpoint.project);
|
|
75
|
+
if (endpoint.uri !== ((_b = (_a = blockingConfig.triggers) === null || _a === void 0 ? void 0 : _a.beforeCreate) === null || _b === void 0 ? void 0 : _b.functionUri) &&
|
|
76
|
+
endpoint.uri !== ((_d = (_c = blockingConfig.triggers) === null || _c === void 0 ? void 0 : _c.beforeSignIn) === null || _d === void 0 ? void 0 : _d.functionUri)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (endpoint.uri === ((_f = (_e = blockingConfig.triggers) === null || _e === void 0 ? void 0 : _e.beforeCreate) === null || _f === void 0 ? void 0 : _f.functionUri)) {
|
|
80
|
+
(_g = blockingConfig.triggers) === null || _g === void 0 ? true : delete _g.beforeCreate;
|
|
81
|
+
}
|
|
82
|
+
if (endpoint.uri === ((_j = (_h = blockingConfig.triggers) === null || _h === void 0 ? void 0 : _h.beforeSignIn) === null || _j === void 0 ? void 0 : _j.functionUri)) {
|
|
83
|
+
(_k = blockingConfig.triggers) === null || _k === void 0 ? true : delete _k.beforeSignIn;
|
|
84
|
+
}
|
|
85
|
+
await identityPlatform.setBlockingFunctionsConfig(endpoint.project, blockingConfig);
|
|
86
|
+
}
|
|
87
|
+
unregisterTrigger(ep) {
|
|
88
|
+
if (!backend.isBlockingTriggered(ep)) {
|
|
89
|
+
return Promise.resolve();
|
|
90
|
+
}
|
|
91
|
+
this.triggerQueue = this.triggerQueue.then(() => this.unregisterTriggerLocked(ep));
|
|
92
|
+
return this.triggerQueue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.AuthBlockingService = AuthBlockingService;
|
|
@@ -1,47 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.serviceForEndpoint = exports.
|
|
3
|
+
exports.serviceForEndpoint = exports.noopProjectBindings = exports.noop = void 0;
|
|
4
4
|
const backend = require("../backend");
|
|
5
|
+
const auth_1 = require("./auth");
|
|
5
6
|
const storage_1 = require("./storage");
|
|
6
7
|
const firebaseAlerts_1 = require("./firebaseAlerts");
|
|
7
8
|
const noop = () => Promise.resolve();
|
|
9
|
+
exports.noop = noop;
|
|
8
10
|
const noopProjectBindings = () => Promise.resolve([]);
|
|
9
|
-
exports.
|
|
11
|
+
exports.noopProjectBindings = noopProjectBindings;
|
|
12
|
+
const noOpService = {
|
|
10
13
|
name: "noop",
|
|
11
14
|
api: "",
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
ensureTriggerRegion: exports.noop,
|
|
16
|
+
validateTrigger: exports.noop,
|
|
17
|
+
registerTrigger: exports.noop,
|
|
18
|
+
unregisterTrigger: exports.noop,
|
|
14
19
|
};
|
|
15
|
-
|
|
20
|
+
const pubSubService = {
|
|
16
21
|
name: "pubsub",
|
|
17
22
|
api: "pubsub.googleapis.com",
|
|
18
|
-
requiredProjectBindings:
|
|
19
|
-
ensureTriggerRegion: noop,
|
|
23
|
+
requiredProjectBindings: exports.noopProjectBindings,
|
|
24
|
+
ensureTriggerRegion: exports.noop,
|
|
25
|
+
validateTrigger: exports.noop,
|
|
26
|
+
registerTrigger: exports.noop,
|
|
27
|
+
unregisterTrigger: exports.noop,
|
|
20
28
|
};
|
|
21
|
-
|
|
29
|
+
const storageService = {
|
|
22
30
|
name: "storage",
|
|
23
31
|
api: "storage.googleapis.com",
|
|
24
32
|
requiredProjectBindings: storage_1.obtainStorageBindings,
|
|
25
33
|
ensureTriggerRegion: storage_1.ensureStorageTriggerRegion,
|
|
34
|
+
validateTrigger: exports.noop,
|
|
35
|
+
registerTrigger: exports.noop,
|
|
36
|
+
unregisterTrigger: exports.noop,
|
|
26
37
|
};
|
|
27
|
-
|
|
38
|
+
const firebaseAlertsService = {
|
|
28
39
|
name: "firebasealerts",
|
|
29
|
-
api: "
|
|
30
|
-
requiredProjectBindings: noopProjectBindings,
|
|
40
|
+
api: "firebasealerts.googleapis.com",
|
|
41
|
+
requiredProjectBindings: exports.noopProjectBindings,
|
|
31
42
|
ensureTriggerRegion: firebaseAlerts_1.ensureFirebaseAlertsTriggerRegion,
|
|
43
|
+
validateTrigger: exports.noop,
|
|
44
|
+
registerTrigger: exports.noop,
|
|
45
|
+
unregisterTrigger: exports.noop,
|
|
32
46
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"google.cloud.
|
|
36
|
-
"google.cloud.storage.object.v1.
|
|
37
|
-
"google.cloud.storage.object.v1.
|
|
38
|
-
"google.cloud.storage.object.v1.
|
|
39
|
-
"google.
|
|
47
|
+
const authBlockingService = new auth_1.AuthBlockingService();
|
|
48
|
+
const EVENT_SERVICE_MAPPING = {
|
|
49
|
+
"google.cloud.pubsub.topic.v1.messagePublished": pubSubService,
|
|
50
|
+
"google.cloud.storage.object.v1.finalized": storageService,
|
|
51
|
+
"google.cloud.storage.object.v1.archived": storageService,
|
|
52
|
+
"google.cloud.storage.object.v1.deleted": storageService,
|
|
53
|
+
"google.cloud.storage.object.v1.metadataUpdated": storageService,
|
|
54
|
+
"google.firebase.firebasealerts.alerts.v1.published": firebaseAlertsService,
|
|
55
|
+
"providers/cloud.auth/eventTypes/user.beforeCreate": authBlockingService,
|
|
56
|
+
"providers/cloud.auth/eventTypes/user.beforeSignIn": authBlockingService,
|
|
40
57
|
};
|
|
41
58
|
function serviceForEndpoint(endpoint) {
|
|
42
|
-
if (
|
|
43
|
-
return
|
|
59
|
+
if (backend.isEventTriggered(endpoint)) {
|
|
60
|
+
return EVENT_SERVICE_MAPPING[endpoint.eventTrigger.eventType] || noOpService;
|
|
44
61
|
}
|
|
45
|
-
|
|
62
|
+
if (backend.isBlockingTriggered(endpoint)) {
|
|
63
|
+
return EVENT_SERVICE_MAPPING[endpoint.blockingTrigger.eventType] || noOpService;
|
|
64
|
+
}
|
|
65
|
+
return noOpService;
|
|
46
66
|
}
|
|
47
67
|
exports.serviceForEndpoint = serviceForEndpoint;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ensureStorageTriggerRegion = exports.obtainStorageBindings = void 0;
|
|
4
4
|
const storage = require("../../../gcp/storage");
|
|
5
|
-
const backend = require("../backend");
|
|
6
5
|
const logger_1 = require("../../../logger");
|
|
7
6
|
const error_1 = require("../../../error");
|
|
8
7
|
const location_1 = require("../../../gcp/location");
|
|
@@ -27,12 +26,8 @@ async function ensureStorageTriggerRegion(endpoint) {
|
|
|
27
26
|
const { eventTrigger } = endpoint;
|
|
28
27
|
if (!eventTrigger.region) {
|
|
29
28
|
logger_1.logger.debug("Looking up bucket region for the storage event trigger");
|
|
30
|
-
const bucketFilter = backend.findEventFilter(endpoint, "bucket");
|
|
31
|
-
if (!bucketFilter) {
|
|
32
|
-
throw new error_1.FirebaseError("Storage event trigger unexpectedly missing event filter with bucket attribute.");
|
|
33
|
-
}
|
|
34
29
|
try {
|
|
35
|
-
const bucket = await storage.getBucket(
|
|
30
|
+
const bucket = await storage.getBucket(eventTrigger.eventFilters.bucket);
|
|
36
31
|
eventTrigger.region = bucket.location.toLowerCase();
|
|
37
32
|
logger_1.logger.debug("Setting the event trigger region to", eventTrigger.region, ".");
|
|
38
33
|
}
|
|
@@ -10,18 +10,21 @@ const fsutils = require("../../fsutils");
|
|
|
10
10
|
const backend = require("./backend");
|
|
11
11
|
const utils = require("../../utils");
|
|
12
12
|
const secrets = require("../../functions/secrets");
|
|
13
|
+
const services_1 = require("./services");
|
|
13
14
|
function endpointsAreValid(wantBackend) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const endpoints = backend.allEndpoints(wantBackend);
|
|
16
|
+
functionIdsAreValid(endpoints);
|
|
17
|
+
for (const ep of endpoints) {
|
|
18
|
+
(0, services_1.serviceForEndpoint)(ep).validateTrigger(ep, wantBackend);
|
|
19
|
+
}
|
|
20
|
+
const gcfV1WithConcurrency = endpoints
|
|
17
21
|
.filter((endpoint) => (endpoint.concurrency || 1) !== 1 && endpoint.platform === "gcfv1")
|
|
18
22
|
.map((endpoint) => endpoint.id);
|
|
19
23
|
if (gcfV1WithConcurrency.length) {
|
|
20
24
|
const msg = `Cannot set concurrency on the functions ${gcfV1WithConcurrency.join(",")} because they are GCF gen 1`;
|
|
21
25
|
throw new error_1.FirebaseError(msg);
|
|
22
26
|
}
|
|
23
|
-
const tooSmallForConcurrency =
|
|
24
|
-
.allEndpoints(wantBackend)
|
|
27
|
+
const tooSmallForConcurrency = endpoints
|
|
25
28
|
.filter((endpoint) => {
|
|
26
29
|
if ((endpoint.concurrency || 1) === 1) {
|
|
27
30
|
return false;
|