firebase-tools 11.4.1 → 11.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.
Files changed (203) hide show
  1. package/lib/accountImporter.js +1 -1
  2. package/lib/auth.js +3 -4
  3. package/lib/bin/firebase.js +4 -4
  4. package/lib/command.js +35 -10
  5. package/lib/commands/apps-android-sha-create.js +1 -1
  6. package/lib/commands/apps-android-sha-delete.js +1 -1
  7. package/lib/commands/apps-create.js +1 -1
  8. package/lib/commands/apps-list.js +1 -1
  9. package/lib/commands/auth-export.js +1 -1
  10. package/lib/commands/auth-import.js +1 -1
  11. package/lib/commands/database-instances-list.js +1 -1
  12. package/lib/commands/database-push.js +1 -1
  13. package/lib/commands/database-remove.js +1 -1
  14. package/lib/commands/database-set.js +1 -1
  15. package/lib/commands/database-update.js +1 -1
  16. package/lib/commands/emulators-exec.js +4 -1
  17. package/lib/commands/emulators-export.js +5 -2
  18. package/lib/commands/emulators-start.js +24 -18
  19. package/lib/commands/ext-dev-deprecate.js +1 -1
  20. package/lib/commands/ext-dev-emulators-exec.js +1 -1
  21. package/lib/commands/ext-dev-emulators-start.js +1 -1
  22. package/lib/commands/ext-dev-extension-delete.js +1 -1
  23. package/lib/commands/ext-dev-list.js +1 -1
  24. package/lib/commands/ext-dev-publish.js +4 -1
  25. package/lib/commands/ext-dev-register.js +1 -1
  26. package/lib/commands/ext-dev-undeprecate.js +1 -1
  27. package/lib/commands/ext-dev-unpublish.js +1 -1
  28. package/lib/commands/ext-dev-usage.js +1 -1
  29. package/lib/commands/ext-info.js +1 -1
  30. package/lib/commands/ext-install.js +2 -2
  31. package/lib/commands/ext-update.js +1 -1
  32. package/lib/commands/ext.js +1 -1
  33. package/lib/commands/firestore-delete.js +2 -2
  34. package/lib/commands/firestore-indexes-list.js +3 -3
  35. package/lib/commands/functions-config-clone.js +1 -1
  36. package/lib/commands/functions-config-export.js +1 -1
  37. package/lib/commands/functions-config-set.js +1 -1
  38. package/lib/commands/functions-config-unset.js +1 -1
  39. package/lib/commands/functions-delete.js +1 -1
  40. package/lib/commands/functions-secrets-set.js +1 -1
  41. package/lib/commands/help.js +1 -1
  42. package/lib/commands/hosting-channel-create.js +5 -5
  43. package/lib/commands/hosting-channel-delete.js +3 -3
  44. package/lib/commands/hosting-channel-deploy.js +6 -6
  45. package/lib/commands/hosting-channel-list.js +2 -2
  46. package/lib/commands/hosting-channel-open.js +2 -2
  47. package/lib/commands/hosting-clone.js +8 -8
  48. package/lib/commands/hosting-disable.js +1 -1
  49. package/lib/commands/hosting-sites-create.js +4 -4
  50. package/lib/commands/hosting-sites-delete.js +4 -4
  51. package/lib/commands/hosting-sites-list.js +2 -2
  52. package/lib/commands/init.js +5 -5
  53. package/lib/commands/login-add.js +1 -1
  54. package/lib/commands/login-ci.js +2 -2
  55. package/lib/commands/login-list.js +1 -1
  56. package/lib/commands/login-use.js +1 -1
  57. package/lib/commands/login.js +3 -3
  58. package/lib/commands/logout.js +1 -1
  59. package/lib/commands/open.js +3 -3
  60. package/lib/commands/projects-list.js +2 -2
  61. package/lib/commands/serve.js +1 -1
  62. package/lib/commands/target-apply.js +1 -1
  63. package/lib/commands/target-clear.js +1 -1
  64. package/lib/commands/target-remove.js +1 -1
  65. package/lib/commands/target.js +1 -1
  66. package/lib/commands/use.js +7 -7
  67. package/lib/config.js +1 -1
  68. package/lib/deploy/database/prepare.js +3 -3
  69. package/lib/deploy/database/release.js +3 -3
  70. package/lib/deploy/extensions/deploymentSummary.js +1 -1
  71. package/lib/deploy/extensions/errors.js +1 -1
  72. package/lib/deploy/extensions/secrets.js +1 -1
  73. package/lib/deploy/extensions/tasks.js +2 -2
  74. package/lib/deploy/firestore/deploy.js +2 -2
  75. package/lib/deploy/firestore/prepare.js +2 -2
  76. package/lib/deploy/functions/backend.js +7 -5
  77. package/lib/deploy/functions/build.js +110 -95
  78. package/lib/deploy/functions/checkIam.js +3 -3
  79. package/lib/deploy/functions/containerCleaner.js +2 -2
  80. package/lib/deploy/functions/deploy.js +2 -2
  81. package/lib/deploy/functions/ensure.js +2 -2
  82. package/lib/deploy/functions/params.js +5 -2
  83. package/lib/deploy/functions/prepare.js +4 -4
  84. package/lib/deploy/functions/prepareFunctionsUpload.js +2 -2
  85. package/lib/deploy/functions/pricing.js +3 -2
  86. package/lib/deploy/functions/prompts.js +2 -2
  87. package/lib/deploy/functions/release/fabricator.js +10 -9
  88. package/lib/deploy/functions/release/index.js +1 -1
  89. package/lib/deploy/functions/release/reporter.js +1 -1
  90. package/lib/deploy/functions/runtimes/discovery/parsing.js +19 -8
  91. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +112 -107
  92. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +1 -1
  93. package/lib/deploy/functions/runtimes/node/parseTriggers.js +54 -26
  94. package/lib/deploy/functions/runtimes/node/versioning.js +4 -4
  95. package/lib/deploy/functions/services/storage.js +6 -0
  96. package/lib/deploy/functions/validate.js +1 -1
  97. package/lib/deploy/hosting/convertConfig.js +8 -1
  98. package/lib/deploy/hosting/deploy.js +10 -9
  99. package/lib/deploy/hosting/uploader.js +2 -2
  100. package/lib/deploy/hosting/validate.js +2 -2
  101. package/lib/deploy/index.js +7 -7
  102. package/lib/deploy/lifecycleHooks.js +5 -2
  103. package/lib/deploy/storage/prepare.js +5 -3
  104. package/lib/deploy/storage/release.js +7 -6
  105. package/lib/emulator/auth/index.js +7 -2
  106. package/lib/emulator/auth/operations.js +10 -10
  107. package/lib/emulator/commandUtils.js +33 -16
  108. package/lib/emulator/constants.js +14 -6
  109. package/lib/emulator/controller.js +55 -18
  110. package/lib/emulator/databaseEmulator.js +1 -1
  111. package/lib/emulator/downloadableEmulators.js +8 -8
  112. package/lib/emulator/emulatorLogger.js +1 -1
  113. package/lib/emulator/eventarcEmulator.js +148 -0
  114. package/lib/emulator/extensionsEmulator.js +5 -3
  115. package/lib/emulator/firestoreEmulator.js +1 -1
  116. package/lib/emulator/functionsEmulator.js +66 -14
  117. package/lib/emulator/functionsEmulatorShared.js +12 -12
  118. package/lib/emulator/hub.js +7 -3
  119. package/lib/emulator/hubClient.js +2 -2
  120. package/lib/emulator/hubExport.js +22 -2
  121. package/lib/emulator/loggingEmulator.js +2 -2
  122. package/lib/emulator/registry.js +1 -0
  123. package/lib/emulator/storage/apis/firebase.js +13 -1
  124. package/lib/emulator/storage/apis/gcloud.js +15 -8
  125. package/lib/emulator/storage/files.js +25 -4
  126. package/lib/emulator/storage/metadata.js +6 -6
  127. package/lib/emulator/storage/multipart.js +4 -3
  128. package/lib/emulator/storage/rules/runtime.js +3 -3
  129. package/lib/emulator/storage/rules/utils.js +4 -2
  130. package/lib/emulator/storage/server.js +2 -1
  131. package/lib/emulator/storage/upload.js +1 -0
  132. package/lib/emulator/types.js +4 -0
  133. package/lib/emulator/ui.js +7 -2
  134. package/lib/ensureApiEnabled.js +7 -7
  135. package/lib/extensions/askUserForConsent.js +1 -1
  136. package/lib/extensions/askUserForEventsConfig.js +1 -1
  137. package/lib/extensions/askUserForParam.js +1 -1
  138. package/lib/extensions/changelog.js +2 -2
  139. package/lib/extensions/checkProjectBilling.js +2 -2
  140. package/lib/extensions/displayExtensionInfo.js +2 -102
  141. package/lib/extensions/emulator/triggerHelper.js +2 -2
  142. package/lib/extensions/extensionsApi.js +3 -2
  143. package/lib/extensions/extensionsHelper.js +30 -2
  144. package/lib/extensions/listExtensions.js +1 -1
  145. package/lib/extensions/manifest.js +1 -1
  146. package/lib/extensions/metricsUtils.js +1 -1
  147. package/lib/extensions/paramHelper.js +1 -1
  148. package/lib/extensions/updateHelper.js +3 -9
  149. package/lib/extensions/warnings.js +2 -2
  150. package/lib/fetchMOTD.js +1 -1
  151. package/lib/firestore/delete.js +1 -1
  152. package/lib/firestore/indexes.js +2 -2
  153. package/lib/firestore/validator.js +1 -1
  154. package/lib/functional.js +16 -1
  155. package/lib/functions/env.js +3 -3
  156. package/lib/functions/runtimeConfigExport.js +1 -1
  157. package/lib/functionsConfig.js +1 -1
  158. package/lib/functionsConfigClone.js +1 -1
  159. package/lib/functionsShellCommandAction.js +1 -1
  160. package/lib/gcp/cloudfunctions.js +24 -11
  161. package/lib/gcp/cloudfunctionsv2.js +48 -24
  162. package/lib/gcp/cloudscheduler.js +58 -22
  163. package/lib/gcp/cloudtasks.js +21 -4
  164. package/lib/gcp/proto.js +18 -6
  165. package/lib/gcp/resourceManager.js +25 -3
  166. package/lib/gcp/serviceusage.js +2 -2
  167. package/lib/handlePreviewToggles.js +4 -4
  168. package/lib/hosting/implicitInit.js +1 -1
  169. package/lib/hosting/normalizedHostingConfigs.js +3 -3
  170. package/lib/index.js +2 -2
  171. package/lib/init/features/database.js +1 -1
  172. package/lib/init/features/emulators.js +1 -1
  173. package/lib/init/features/firestore/index.js +2 -2
  174. package/lib/init/features/firestore/indexes.js +1 -1
  175. package/lib/init/features/firestore/rules.js +1 -1
  176. package/lib/init/features/functions/golang.js +1 -1
  177. package/lib/init/features/functions/index.js +8 -1
  178. package/lib/init/features/hosting/github.js +9 -9
  179. package/lib/init/features/hosting/index.js +1 -1
  180. package/lib/init/features/project.js +1 -1
  181. package/lib/init/features/remoteconfig.js +1 -1
  182. package/lib/init/features/storage.js +1 -1
  183. package/lib/init/index.js +1 -1
  184. package/lib/logError.js +3 -3
  185. package/lib/management/projects.js +1 -1
  186. package/lib/parseBoltRules.js +1 -1
  187. package/lib/previews.js +1 -1
  188. package/lib/profileReport.js +2 -2
  189. package/lib/projectUtils.js +1 -1
  190. package/lib/rc.js +1 -1
  191. package/lib/requireAuth.js +1 -1
  192. package/lib/requireDatabaseInstance.js +2 -2
  193. package/lib/requirePermissions.js +2 -2
  194. package/lib/rulesDeploy.js +49 -13
  195. package/lib/serve/hosting.js +2 -1
  196. package/lib/serve/index.js +15 -0
  197. package/lib/track.js +119 -3
  198. package/lib/utils.js +24 -11
  199. package/npm-shrinkwrap.json +14 -294
  200. package/package.json +5 -4
  201. package/schema/firebase-config.json +12 -0
  202. package/templates/extensions/CHANGELOG.md +1 -7
  203. package/templates/hosting/init.js +6 -2
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.serviceIsResolved = exports.Fabricator = void 0;
4
- const clc = require("cli-color");
4
+ const clc = require("colorette");
5
5
  const error_1 = require("../../../error");
6
6
  const sourceTokenScraper_1 = require("./sourceTokenScraper");
7
7
  const timer_1 = require("./timer");
@@ -301,10 +301,10 @@ class Fabricator {
301
301
  endpoint.uri = (_b = resultFunction === null || resultFunction === void 0 ? void 0 : resultFunction.httpsTrigger) === null || _b === void 0 ? void 0 : _b.url;
302
302
  let invoker;
303
303
  if (backend.isHttpsTriggered(endpoint)) {
304
- invoker = endpoint.httpsTrigger.invoker;
304
+ invoker = endpoint.httpsTrigger.invoker === null ? ["public"] : endpoint.httpsTrigger.invoker;
305
305
  }
306
306
  else if (backend.isTaskQueueTriggered(endpoint)) {
307
- invoker = endpoint.taskQueueTrigger.invoker;
307
+ invoker = endpoint.taskQueueTrigger.invoker === null ? [] : endpoint.taskQueueTrigger.invoker;
308
308
  }
309
309
  else if (backend.isBlockingTriggered(endpoint) &&
310
310
  v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
@@ -337,10 +337,10 @@ class Fabricator {
337
337
  const serviceName = resultFunction.serviceConfig.service;
338
338
  let invoker;
339
339
  if (backend.isHttpsTriggered(endpoint)) {
340
- invoker = endpoint.httpsTrigger.invoker;
340
+ invoker = endpoint.httpsTrigger.invoker === null ? ["public"] : endpoint.httpsTrigger.invoker;
341
341
  }
342
342
  else if (backend.isTaskQueueTriggered(endpoint)) {
343
- invoker = endpoint.taskQueueTrigger.invoker;
343
+ invoker = endpoint.taskQueueTrigger.invoker === null ? [] : endpoint.taskQueueTrigger.invoker;
344
344
  }
345
345
  else if (backend.isBlockingTriggered(endpoint) &&
346
346
  v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
@@ -477,12 +477,13 @@ class Fabricator {
477
477
  .catch(rethrowAs(endpoint, "register blocking trigger"));
478
478
  }
479
479
  async deleteScheduleV1(endpoint) {
480
- const job = scheduler.jobFromEndpoint(endpoint, this.appEngineLocation);
480
+ const jobName = scheduler.jobNameForEndpoint(endpoint, this.appEngineLocation);
481
481
  await this.executor
482
- .run(() => scheduler.deleteJob(job.name))
482
+ .run(() => scheduler.deleteJob(jobName))
483
483
  .catch(rethrowAs(endpoint, "delete schedule"));
484
+ const topicName = scheduler.topicNameForEndpoint(endpoint);
484
485
  await this.executor
485
- .run(() => pubsub.deleteTopic(job.pubsubTarget.topicName))
486
+ .run(() => pubsub.deleteTopic(topicName))
486
487
  .catch(rethrowAs(endpoint, "delete topic"));
487
488
  }
488
489
  deleteScheduleV2(endpoint) {
@@ -509,7 +510,7 @@ class Fabricator {
509
510
  }
510
511
  logOpSuccess(op, endpoint) {
511
512
  const label = helper.getFunctionLabel(endpoint);
512
- utils.logSuccess(`${clc.bold.green(`functions[${label}]`)} Successful ${op} operation.`);
513
+ utils.logSuccess(`${clc.bold(clc.green(`functions[${label}]`))} Successful ${op} operation.`);
513
514
  }
514
515
  }
515
516
  exports.Fabricator = Fabricator;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.printTriggerUrls = exports.release = void 0;
4
- const clc = require("cli-color");
4
+ const clc = require("colorette");
5
5
  const logger_1 = require("../../../logger");
6
6
  const functional_1 = require("../../../functional");
7
7
  const backend = require("../backend");
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.triggerTag = exports.printAbortedErrors = exports.printErrors = exports.logAndTrackDeployStats = exports.AbortedDeploymentError = exports.DeploymentError = void 0;
4
4
  const backend = require("../backend");
5
- const clc = require("cli-color");
5
+ const clc = require("colorette");
6
6
  const logger_1 = require("../../../logger");
7
7
  const track_1 = require("../../../track");
8
8
  const utils = require("../../../utils");
@@ -23,35 +23,46 @@ function assertKeyTypes(prefix, yaml, schema) {
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
- const schemaType = schema[key];
26
+ let schemaType = schema[key];
27
27
  if (typeof schemaType === "function") {
28
28
  if (!schemaType(value)) {
29
- throw new error_1.FirebaseError(`${Array.isArray(value) ? "array" : typeof value} ${fullKey} failed validation`);
29
+ const friendlyName = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
30
+ throw new error_1.FirebaseError(`${friendlyName} ${fullKey} failed validation`);
30
31
  }
32
+ continue;
31
33
  }
32
- else if (schemaType === "string") {
34
+ if (value === null) {
35
+ if (schemaType.endsWith("?")) {
36
+ continue;
37
+ }
38
+ throw new error_1.FirebaseError(`Expected ${fullKey}} to be type ${schemaType}; was null`);
39
+ }
40
+ if (schemaType.endsWith("?")) {
41
+ schemaType = schemaType.slice(0, schemaType.length - 1);
42
+ }
43
+ if (schemaType === "string") {
33
44
  if (typeof value !== "string") {
34
- throw new error_1.FirebaseError(`Expected ${fullKey} to be string; was ${typeof value}`);
45
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be type string; was ${typeof value}`);
35
46
  }
36
47
  }
37
48
  else if (schemaType === "number") {
38
49
  if (typeof value !== "number") {
39
- throw new error_1.FirebaseError(`Expected ${fullKey} to be a number; was ${typeof value}`);
50
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be type number; was ${typeof value}`);
40
51
  }
41
52
  }
42
53
  else if (schemaType === "boolean") {
43
54
  if (typeof value !== "boolean") {
44
- throw new error_1.FirebaseError(`Expected ${fullKey} to be a boolean; was ${typeof value}`);
55
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be type boolean; was ${typeof value}`);
45
56
  }
46
57
  }
47
58
  else if (schemaType === "array") {
48
59
  if (!Array.isArray(value)) {
49
- throw new error_1.FirebaseError(`Expected ${fullKey} to be an array; was ${typeof value}`);
60
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be type array; was ${typeof value}`);
50
61
  }
51
62
  }
52
63
  else if (schemaType === "object") {
53
64
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
54
- throw new error_1.FirebaseError(`Expected ${fullKey} to be an object; was ${typeof value}`);
65
+ throw new error_1.FirebaseError(`Expected ${fullKey} to be type object; was ${typeof value}`);
55
66
  }
56
67
  }
57
68
  else {
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
2
  Object.defineProperty(exports, "__esModule", { value: true });
14
3
  exports.backendFromV1Alpha1 = exports.buildFromV1Alpha1 = void 0;
15
4
  const backend = require("../../backend");
@@ -17,6 +6,7 @@ const build = require("../../build");
17
6
  const proto_1 = require("../../../../gcp/proto");
18
7
  const parsing_1 = require("./parsing");
19
8
  const error_1 = require("../../../../error");
9
+ const functional_1 = require("../../../../functional");
20
10
  const CHANNEL_NAME_REGEX = new RegExp("(projects\\/" +
21
11
  "(?<project>(?:\\d+)|(?:[A-Za-z]+[A-Za-z\\d-]*[A-Za-z\\d]?))\\/)?" +
22
12
  "locations\\/" +
@@ -82,29 +72,30 @@ function assertManifestEndpoint(ep, id) {
82
72
  region: "array",
83
73
  platform: (platform) => backend.AllFunctionsPlatforms.includes(platform),
84
74
  entryPoint: "string",
85
- availableMemoryMb: (mem) => backend.AllMemoryOptions.includes(mem),
86
- maxInstances: "number",
87
- minInstances: "number",
88
- concurrency: "number",
89
- serviceAccountEmail: "string",
90
- timeoutSeconds: "number",
91
- vpc: "object",
92
- labels: "object",
93
- ingressSettings: (setting) => backend.AllIngressSettings.includes(setting),
94
- environmentVariables: "object",
95
- secretEnvironmentVariables: "array",
75
+ availableMemoryMb: (mem) => mem === null || backend.isValidMemoryOption(mem),
76
+ maxInstances: "number?",
77
+ minInstances: "number?",
78
+ concurrency: "number?",
79
+ serviceAccount: "string?",
80
+ serviceAccountEmail: "string?",
81
+ timeoutSeconds: "number?",
82
+ vpc: "object?",
83
+ labels: "object?",
84
+ ingressSettings: (setting) => setting === null || backend.AllIngressSettings.includes(setting),
85
+ environmentVariables: "object?",
86
+ secretEnvironmentVariables: "array?",
96
87
  httpsTrigger: "object",
97
88
  callableTrigger: "object",
98
89
  eventTrigger: "object",
99
90
  scheduleTrigger: "object",
100
91
  taskQueueTrigger: "object",
101
92
  blockingTrigger: "object",
102
- cpu: (cpu) => typeof cpu === "number" || cpu === "gcf_gen1",
93
+ cpu: (cpu) => cpu === null || typeof cpu === "number" || cpu === "gcf_gen1",
103
94
  });
104
95
  if (ep.vpc) {
105
96
  (0, parsing_1.assertKeyTypes)(prefix + ".vpc", ep.vpc, {
106
97
  connector: "string",
107
- egressSettings: (setting) => backend.AllVpcEgressSettings.includes(setting),
98
+ egressSettings: (setting) => setting === null || backend.AllVpcEgressSettings.includes(setting),
108
99
  });
109
100
  (0, parsing_1.requireKeys)(prefix + ".vpc", ep.vpc, "connector");
110
101
  }
@@ -141,13 +132,14 @@ function assertManifestEndpoint(ep, id) {
141
132
  eventType: "string",
142
133
  retry: "boolean",
143
134
  region: "string",
144
- serviceAccountEmail: "string",
135
+ serviceAccount: "string?",
136
+ serviceAccountEmail: "string?",
145
137
  channel: "string",
146
138
  });
147
139
  }
148
140
  else if (backend.isHttpsTriggered(ep)) {
149
141
  (0, parsing_1.assertKeyTypes)(prefix + ".httpsTrigger", ep.httpsTrigger, {
150
- invoker: "array",
142
+ invoker: "array?",
151
143
  });
152
144
  }
153
145
  else if (backend.isCallableTriggered(ep)) {
@@ -155,36 +147,39 @@ function assertManifestEndpoint(ep, id) {
155
147
  else if (backend.isScheduleTriggered(ep)) {
156
148
  (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger", ep.scheduleTrigger, {
157
149
  schedule: "string",
158
- timeZone: "string",
159
- retryConfig: "object",
150
+ timeZone: "string?",
151
+ retryConfig: "object?",
160
152
  });
161
- (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger.retryConfig", ep.scheduleTrigger.retryConfig, {
162
- retryCount: "number",
163
- maxDoublings: "number",
164
- minBackoffDuration: "string",
165
- maxBackoffDuration: "string",
166
- maxRetryDuration: "string",
153
+ (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger.retryConfig", ep.scheduleTrigger.retryConfig || {}, {
154
+ retryCount: "number?",
155
+ maxDoublings: "number?",
156
+ minBackoffSeconds: "number?",
157
+ maxBackoffSeconds: "number?",
158
+ maxRetrySeconds: "number?",
159
+ minBackoffDuration: "string?",
160
+ maxBackoffDuration: "string?",
161
+ maxRetryDuration: "string?",
167
162
  });
168
163
  }
169
164
  else if (backend.isTaskQueueTriggered(ep)) {
170
165
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger", ep.taskQueueTrigger, {
171
- rateLimits: "object",
172
- retryConfig: "object",
173
- invoker: "array",
166
+ rateLimits: "object?",
167
+ retryConfig: "object?",
168
+ invoker: "array?",
174
169
  });
175
170
  if (ep.taskQueueTrigger.rateLimits) {
176
171
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.rateLimits", ep.taskQueueTrigger.rateLimits, {
177
- maxConcurrentDispatches: "number",
178
- maxDispatchesPerSecond: "number",
172
+ maxConcurrentDispatches: "number?",
173
+ maxDispatchesPerSecond: "number?",
179
174
  });
180
175
  }
181
176
  if (ep.taskQueueTrigger.retryConfig) {
182
177
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.retryConfig", ep.taskQueueTrigger.retryConfig, {
183
- maxAttempts: "number",
184
- maxRetrySeconds: "number",
185
- minBackoffSeconds: "number",
186
- maxBackoffSeconds: "number",
187
- maxDoublings: "number",
178
+ maxAttempts: "number?",
179
+ maxRetrySeconds: "number?",
180
+ minBackoffSeconds: "number?",
181
+ maxBackoffSeconds: "number?",
182
+ maxDoublings: "number?",
188
183
  });
189
184
  }
190
185
  }
@@ -201,18 +196,24 @@ function assertManifestEndpoint(ep, id) {
201
196
  }
202
197
  }
203
198
  function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
199
+ var _a;
204
200
  let triggered;
205
201
  if (backend.isEventTriggered(ep)) {
206
- const newTrigger = __rest(ep.eventTrigger, []);
207
- delete newTrigger.serviceAccountEmail;
208
- triggered = { eventTrigger: newTrigger };
209
- triggered.eventTrigger.serviceAccount = ep.eventTrigger.serviceAccountEmail;
210
- (0, proto_1.renameIfPresent)(triggered.eventTrigger, ep.eventTrigger, "channel", "channel", (c) => resolveChannelName(project, c, defaultRegion));
211
- for (const [k, v] of Object.entries(triggered.eventTrigger.eventFilters)) {
212
- if (k === "topic" && !v.startsWith("projects/")) {
213
- triggered.eventTrigger.eventFilters[k] = `projects/${project}/topics/${v}`;
202
+ const eventTrigger = {
203
+ eventType: ep.eventTrigger.eventType,
204
+ retry: ep.eventTrigger.retry,
205
+ };
206
+ (0, proto_1.renameIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "serviceAccountEmail");
207
+ (0, proto_1.copyIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "eventFilterPathPatterns", "region");
208
+ (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "channel", (c) => resolveChannelName(project, c, defaultRegion));
209
+ (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "eventFilters", (filters) => {
210
+ const copy = Object.assign({}, filters);
211
+ if (copy["topic"] && !copy["topic"].startsWith("projects/")) {
212
+ copy["topic"] = `projects/${project}/topics/${copy["topic"]}`;
214
213
  }
215
- }
214
+ return copy;
215
+ });
216
+ triggered = { eventTrigger };
216
217
  }
217
218
  else if (backend.isHttpsTriggered(ep)) {
218
219
  triggered = { httpsTrigger: {} };
@@ -224,39 +225,39 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
224
225
  else if (backend.isScheduleTriggered(ep)) {
225
226
  const st = {
226
227
  schedule: ep.scheduleTrigger.schedule || "",
227
- timeZone: ep.scheduleTrigger.timeZone || "",
228
- retryConfig: {},
228
+ timeZone: (_a = ep.scheduleTrigger.timeZone) !== null && _a !== void 0 ? _a : null,
229
229
  };
230
230
  if (ep.scheduleTrigger.retryConfig) {
231
- st.retryConfig = {
232
- retryCount: ep.scheduleTrigger.retryConfig.retryCount,
233
- maxDoublings: ep.scheduleTrigger.retryConfig.maxDoublings,
234
- };
235
- if (ep.scheduleTrigger.retryConfig.maxRetryDuration) {
236
- st.retryConfig.maxRetrySeconds = (0, proto_1.secondsFromDuration)(ep.scheduleTrigger.retryConfig.maxRetryDuration);
237
- }
238
- if (ep.scheduleTrigger.retryConfig.maxBackoffDuration) {
239
- st.retryConfig.maxBackoffSeconds = (0, proto_1.secondsFromDuration)(ep.scheduleTrigger.retryConfig.maxBackoffDuration);
240
- }
241
- if (ep.scheduleTrigger.retryConfig.minBackoffDuration) {
242
- st.retryConfig.minBackoffSeconds = (0, proto_1.secondsFromDuration)(ep.scheduleTrigger.retryConfig.minBackoffDuration);
243
- }
231
+ st.retryConfig = {};
232
+ (0, proto_1.copyIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "retryCount", "minBackoffSeconds", "maxBackoffSeconds", "maxRetrySeconds", "maxDoublings");
233
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "minBackoffSeconds", "minBackoffDuration", (0, functional_1.nullsafeVisitor)(proto_1.secondsFromDuration));
234
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "maxBackoffSeconds", "maxBackoffDuration", (0, functional_1.nullsafeVisitor)(proto_1.secondsFromDuration));
235
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "maxRetrySeconds", "maxRetryDuration", (0, functional_1.nullsafeVisitor)(proto_1.secondsFromDuration));
236
+ }
237
+ else if (ep.scheduleTrigger.retryConfig === null) {
238
+ st.retryConfig = null;
244
239
  }
245
240
  triggered = { scheduleTrigger: st };
246
241
  }
247
242
  else if (backend.isTaskQueueTriggered(ep)) {
248
- const tq = {
249
- invoker: ep.taskQueueTrigger.invoker,
250
- rateLimits: ep.taskQueueTrigger.rateLimits,
251
- };
243
+ const tq = {};
244
+ if (ep.taskQueueTrigger.invoker) {
245
+ tq.invoker = ep.taskQueueTrigger.invoker;
246
+ }
247
+ else if (ep.taskQueueTrigger.invoker === null) {
248
+ tq.invoker = null;
249
+ }
252
250
  if (ep.taskQueueTrigger.retryConfig) {
253
- tq.retryConfig = {
254
- maxRetryDurationSeconds: ep.taskQueueTrigger.retryConfig.maxRetrySeconds,
255
- maxBackoffSeconds: ep.taskQueueTrigger.retryConfig.maxBackoffSeconds,
256
- minBackoffSeconds: ep.taskQueueTrigger.retryConfig.minBackoffSeconds,
257
- maxDoublings: ep.taskQueueTrigger.retryConfig.maxDoublings,
258
- maxAttempts: ep.taskQueueTrigger.retryConfig.maxAttempts,
259
- };
251
+ tq.retryConfig = Object.assign({}, ep.taskQueueTrigger.retryConfig);
252
+ }
253
+ else if (ep.taskQueueTrigger.retryConfig === null) {
254
+ tq.retryConfig = null;
255
+ }
256
+ if (ep.taskQueueTrigger.rateLimits) {
257
+ tq.rateLimits = Object.assign({}, ep.taskQueueTrigger.rateLimits);
258
+ }
259
+ else if (ep.taskQueueTrigger.rateLimits === null) {
260
+ tq.rateLimits = null;
260
261
  }
261
262
  triggered = { taskQueueTrigger: tq };
262
263
  }
@@ -268,18 +269,16 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
268
269
  "firebase-tools with npm install -g firebase-tools@latest");
269
270
  }
270
271
  const parsed = Object.assign({ platform: ep.platform || "gcfv2", region: ep.region || [defaultRegion], project,
271
- runtime, entryPoint: ep.entryPoint, serviceAccount: ep.serviceAccountEmail || null }, triggered);
272
- (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables");
273
- (0, proto_1.renameIfPresent)(parsed, ep, "secretEnvironmentVariables", "secretEnvironmentVariables", (senvs) => {
274
- const secretEnvironmentVariables = [];
275
- for (const { key, secret } of senvs) {
276
- secretEnvironmentVariables.push({
277
- key,
278
- secret: secret || key,
279
- projectId: project,
280
- });
272
+ runtime, entryPoint: ep.entryPoint }, triggered);
273
+ (0, proto_1.renameIfPresent)(parsed, ep, "serviceAccount", "serviceAccountEmail");
274
+ (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
275
+ (0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
276
+ if (!senvs) {
277
+ return null;
281
278
  }
282
- return secretEnvironmentVariables;
279
+ return senvs.map(({ key, secret }) => {
280
+ return { key, secret: secret || key, projectId: project };
281
+ });
283
282
  });
284
283
  return parsed;
285
284
  }
@@ -287,17 +286,25 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
287
286
  const allParsed = [];
288
287
  const prefix = `endpoints[${id}]`;
289
288
  const ep = manifest.endpoints[id];
290
- assertManifestEndpoint(ep, prefix);
289
+ assertManifestEndpoint(ep, id);
291
290
  for (const region of ep.region || [defaultRegion]) {
292
291
  let triggered;
293
292
  if (backend.isEventTriggered(ep)) {
294
- triggered = { eventTrigger: ep.eventTrigger };
295
- (0, proto_1.renameIfPresent)(triggered.eventTrigger, ep.eventTrigger, "channel", "channel", (c) => resolveChannelName(project, c, defaultRegion));
296
- for (const [k, v] of Object.entries(triggered.eventTrigger.eventFilters)) {
297
- if (k === "topic" && !v.startsWith("projects/")) {
298
- triggered.eventTrigger.eventFilters[k] = `projects/${project}/topics/${v}`;
293
+ const eventTrigger = {
294
+ eventType: ep.eventTrigger.eventType,
295
+ retry: false,
296
+ };
297
+ (0, proto_1.renameIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "serviceAccountEmail");
298
+ (0, proto_1.copyIfPresent)(eventTrigger, ep.eventTrigger, "eventFilterPathPatterns", "retry", "serviceAccount", "region");
299
+ (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "channel", (c) => resolveChannelName(project, c, defaultRegion));
300
+ (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "eventFilters", (filters) => {
301
+ const copy = Object.assign({}, filters);
302
+ if (copy["topic"] && !copy["topic"].startsWith("projects/")) {
303
+ copy["topic"] = `projects/${project}/topics/${copy["topic"]}`;
299
304
  }
300
- }
305
+ return copy;
306
+ });
307
+ triggered = { eventTrigger };
301
308
  }
302
309
  else if (backend.isHttpsTriggered(ep)) {
303
310
  triggered = { httpsTrigger: {} };
@@ -324,17 +331,15 @@ function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
324
331
  region,
325
332
  project,
326
333
  runtime, entryPoint: ep.entryPoint }, triggered);
327
- (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "serviceAccountEmail", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "cpu");
328
- (0, proto_1.renameIfPresent)(parsed, ep, "secretEnvironmentVariables", "secretEnvironmentVariables", (senvs) => {
329
- const secretEnvironmentVariables = [];
330
- for (const { key, secret } of senvs) {
331
- secretEnvironmentVariables.push({
332
- key,
333
- secret: secret || key,
334
- projectId: project,
335
- });
334
+ (0, proto_1.renameIfPresent)(parsed, ep, "serviceAccount", "serviceAccountEmail");
335
+ (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "serviceAccount", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "cpu");
336
+ (0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
337
+ if (!senvs) {
338
+ return null;
336
339
  }
337
- return secretEnvironmentVariables;
340
+ return senvs.map(({ key, secret }) => {
341
+ return { key, secret: secret || key, projectId: project };
342
+ });
338
343
  });
339
344
  allParsed.push(parsed);
340
345
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRuntimeChoice = exports.DEPRECATED_NODE_VERSION_INFO = exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG = exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG = exports.RUNTIME_NOT_SET = void 0;
4
4
  const path = require("path");
5
- const clc = require("cli-color");
5
+ const clc = require("colorette");
6
6
  const error_1 = require("../../../../error");
7
7
  const track_1 = require("../../../../track");
8
8
  const runtimes = require("../../runtimes");
@@ -10,6 +10,7 @@ const backend = require("../../backend");
10
10
  const api = require("../../../../api");
11
11
  const proto = require("../../../../gcp/proto");
12
12
  const events = require("../../../../functions/events");
13
+ const functional_1 = require("../../../../functional");
13
14
  const TRIGGER_PARSER = path.resolve(__dirname, "./triggerParser.js");
14
15
  function removeInspectOptions(options) {
15
16
  return options.filter((opt) => !opt.startsWith("--inspect"));
@@ -88,8 +89,9 @@ function mergeRequiredAPIs(backend) {
88
89
  }
89
90
  exports.mergeRequiredAPIs = mergeRequiredAPIs;
90
91
  function addResourcesToBuild(projectId, runtime, annotation, want) {
91
- var _a;
92
+ var _a, _b;
92
93
  Object.freeze(annotation);
94
+ const toSeconds = (0, functional_1.nullsafeVisitor)(proto.secondsFromDuration);
93
95
  const regions = annotation.regions || [api.functionsDefaultRegion];
94
96
  let triggered;
95
97
  const triggerCount = +!!annotation.httpsTrigger +
@@ -110,9 +112,11 @@ function addResourcesToBuild(projectId, runtime, annotation, want) {
110
112
  proto.copyIfPresent(triggered.taskQueueTrigger, annotation.taskQueueTrigger, "invoker");
111
113
  proto.copyIfPresent(triggered.taskQueueTrigger, annotation.taskQueueTrigger, "rateLimits");
112
114
  if (annotation.taskQueueTrigger.retryConfig) {
113
- triggered.taskQueueTrigger.retryConfig = Object.assign(annotation.taskQueueTrigger.retryConfig, {
114
- maxRetryDurationSeconds: proto.secondsFromDuration(annotation.taskQueueTrigger.retryConfig.maxRetryDuration || "0"),
115
- });
115
+ triggered.taskQueueTrigger.retryConfig = {};
116
+ proto.copyIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxAttempts", "maxDoublings");
117
+ proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "minBackoffSeconds", "minBackoff", toSeconds);
118
+ proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxBackoffSeconds", "maxBackoff", toSeconds);
119
+ proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxRetryDurationSeconds", "maxRetryDuration", toSeconds);
116
120
  }
117
121
  }
118
122
  else if (annotation.httpsTrigger) {
@@ -139,21 +143,16 @@ function addResourcesToBuild(projectId, runtime, annotation, want) {
139
143
  triggered = {
140
144
  scheduleTrigger: {
141
145
  schedule: annotation.schedule.schedule,
142
- timeZone: annotation.schedule.timeZone || "America/Los_Angeles",
146
+ timeZone: (_b = annotation.schedule.timeZone) !== null && _b !== void 0 ? _b : null,
143
147
  retryConfig: {},
144
148
  },
145
149
  };
146
150
  if (annotation.schedule.retryConfig) {
147
- if (annotation.schedule.retryConfig.maxBackoffDuration) {
148
- triggered.scheduleTrigger.retryConfig.maxBackoffSeconds = proto.secondsFromDuration(annotation.schedule.retryConfig.maxBackoffDuration);
149
- }
150
- if (annotation.schedule.retryConfig.minBackoffDuration) {
151
- triggered.scheduleTrigger.retryConfig.minBackoffSeconds = proto.secondsFromDuration(annotation.schedule.retryConfig.minBackoffDuration);
152
- }
153
- if (annotation.schedule.retryConfig.maxRetryDuration) {
154
- triggered.scheduleTrigger.retryConfig.maxRetrySeconds = proto.secondsFromDuration(annotation.schedule.retryConfig.maxRetryDuration);
155
- }
156
- proto.copyIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "maxDoublings", "retryCount");
151
+ triggered.scheduleTrigger.retryConfig = {};
152
+ proto.copyIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "retryCount", "maxDoublings");
153
+ proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "maxRetrySeconds", "maxRetryDuration", toSeconds);
154
+ proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "minBackoffSeconds", "minBackoffDuration", toSeconds);
155
+ proto.convertIfPresent(triggered.scheduleTrigger.retryConfig, annotation.schedule.retryConfig, "maxBackoffSeconds", "maxBackoffDuration", toSeconds);
157
156
  }
158
157
  }
159
158
  else if (annotation.blockingTrigger) {
@@ -169,7 +168,7 @@ function addResourcesToBuild(projectId, runtime, annotation, want) {
169
168
  },
170
169
  };
171
170
  }
172
- else {
171
+ else if (annotation.eventTrigger) {
173
172
  triggered = {
174
173
  eventTrigger: {
175
174
  eventType: annotation.eventTrigger.eventType,
@@ -178,18 +177,28 @@ function addResourcesToBuild(projectId, runtime, annotation, want) {
178
177
  },
179
178
  };
180
179
  }
180
+ else {
181
+ throw new error_1.FirebaseError("Do not understand Cloud Function annotation without a trigger" +
182
+ JSON.stringify(annotation, null, 2));
183
+ }
181
184
  const endpointId = annotation.name;
182
- const endpoint = Object.assign({ platform: annotation.platform || "gcfv1", region: regions, project: projectId, entryPoint: annotation.entryPoint, runtime: runtime, serviceAccount: annotation.serviceAccountEmail || null }, triggered);
185
+ const endpoint = Object.assign({ platform: annotation.platform || "gcfv1", region: regions, project: projectId, entryPoint: annotation.entryPoint, runtime: runtime }, triggered);
186
+ proto.renameIfPresent(endpoint, annotation, "serviceAccount", "serviceAccountEmail");
183
187
  if (annotation.vpcConnector != null) {
184
- let maybeId = annotation.vpcConnector;
185
- if (maybeId && !maybeId.includes("/")) {
186
- maybeId = `projects/${projectId}/locations/$REGION/connectors/${maybeId}`;
187
- }
188
- endpoint.vpc = { connector: maybeId };
188
+ endpoint.vpc = { connector: annotation.vpcConnector };
189
189
  proto.renameIfPresent(endpoint.vpc, annotation, "egressSettings", "vpcConnectorEgressSettings");
190
190
  }
191
- proto.copyIfPresent(endpoint, annotation, "concurrency", "labels", "ingressSettings", "maxInstances", "minInstances", "availableMemoryMb");
192
- proto.renameIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
191
+ proto.copyIfPresent(endpoint, annotation, "concurrency", "labels", "maxInstances", "minInstances", "availableMemoryMb");
192
+ proto.convertIfPresent(endpoint, annotation, "ingressSettings", (str) => {
193
+ if (str === null) {
194
+ return null;
195
+ }
196
+ if (!backend.AllIngressSettings.includes(str)) {
197
+ throw new Error(`Invalid ingress setting ${str}`);
198
+ }
199
+ return str;
200
+ });
201
+ proto.convertIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
193
202
  want.endpoints[endpointId] = endpoint;
194
203
  }
195
204
  exports.addResourcesToBuild = addResourcesToBuild;
@@ -285,8 +294,27 @@ function addResourcesToBackend(projectId, runtime, annotation, want) {
285
294
  }
286
295
  endpoint.secretEnvironmentVariables = secretEnvs;
287
296
  }
288
- proto.copyIfPresent(endpoint, annotation, "concurrency", "serviceAccountEmail", "labels", "ingressSettings", "maxInstances", "minInstances", "availableMemoryMb");
289
- proto.renameIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
297
+ proto.copyIfPresent(endpoint, annotation, "concurrency", "labels", "maxInstances", "minInstances");
298
+ proto.renameIfPresent(endpoint, annotation, "serviceAccount", "serviceAccountEmail");
299
+ proto.convertIfPresent(endpoint, annotation, "ingressSettings", (ingress) => {
300
+ if (ingress == null) {
301
+ return null;
302
+ }
303
+ if (!backend.AllIngressSettings.includes(ingress)) {
304
+ throw new error_1.FirebaseError(`Invalid ingress setting ${ingress}`);
305
+ }
306
+ return ingress;
307
+ });
308
+ proto.convertIfPresent(endpoint, annotation, "availableMemoryMb", (mem) => {
309
+ if (mem === null) {
310
+ return null;
311
+ }
312
+ if (!backend.isValidMemoryOption(mem)) {
313
+ throw new error_1.FirebaseError(`This version of firebase-tools does not know about the memory option ${mem}. Is an upgrade necessary?`);
314
+ }
315
+ return mem;
316
+ });
317
+ proto.convertIfPresent(endpoint, annotation, "timeoutSeconds", "timeout", proto.secondsFromDuration);
290
318
  want.endpoints[region] = want.endpoints[region] || {};
291
319
  want.endpoints[region][endpoint.id] = endpoint;
292
320
  mergeRequiredAPIs(want);