firebase-tools 9.23.0 → 10.0.1

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 (49) hide show
  1. package/lib/api.js +0 -1
  2. package/lib/commands/database-remove.js +2 -2
  3. package/lib/commands/database-set.js +2 -2
  4. package/lib/commands/database-update.js +2 -2
  5. package/lib/commands/firestore-delete.js +2 -2
  6. package/lib/commands/functions-delete.js +7 -1
  7. package/lib/commands/hosting-disable.js +3 -3
  8. package/lib/commands/remoteconfig-get.js +6 -5
  9. package/lib/deploy/functions/checkIam.js +65 -4
  10. package/lib/deploy/functions/containerCleaner.js +28 -38
  11. package/lib/deploy/functions/deploy.js +6 -7
  12. package/lib/deploy/functions/eventTypes.js +10 -0
  13. package/lib/deploy/functions/prepare.js +12 -2
  14. package/lib/deploy/functions/release/fabricator.js +6 -1
  15. package/lib/deploy/functions/release/index.js +6 -2
  16. package/lib/deploy/functions/release/reporter.js +4 -0
  17. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +1 -1
  18. package/lib/deploy/functions/runtimes/node/parseTriggers.js +3 -9
  19. package/lib/deploy/functions/services/index.js +38 -0
  20. package/lib/deploy/functions/services/storage.js +43 -0
  21. package/lib/deploy/functions/triggerRegionHelper.js +6 -30
  22. package/lib/emulator/auth/handlers.js +1 -1
  23. package/lib/emulator/auth/operations.js +27 -9
  24. package/lib/emulator/auth/widget_ui.js +17 -3
  25. package/lib/emulator/downloadableEmulators.js +5 -5
  26. package/lib/emulator/functionsEmulator.js +15 -1
  27. package/lib/emulator/functionsEmulatorRuntime.js +1 -1
  28. package/lib/emulator/functionsEmulatorShared.js +1 -0
  29. package/lib/emulator/pubsubEmulator.js +58 -45
  30. package/lib/emulator/storage/cloudFunctions.js +13 -6
  31. package/lib/ensureApiEnabled.js +11 -14
  32. package/lib/extensions/askUserForParam.js +32 -8
  33. package/lib/extensions/emulator/triggerHelper.js +1 -0
  34. package/lib/functions/env.js +2 -2
  35. package/lib/gcp/cloudfunctions.js +11 -2
  36. package/lib/gcp/cloudfunctionsv2.js +35 -3
  37. package/lib/gcp/docker.js +29 -1
  38. package/lib/gcp/location.js +44 -0
  39. package/lib/gcp/storage.js +48 -32
  40. package/lib/init/features/functions/index.js +3 -3
  41. package/lib/init/features/hosting/github.js +3 -0
  42. package/lib/init/features/project.js +2 -1
  43. package/lib/previews.js +1 -1
  44. package/package.json +3 -3
  45. package/templates/init/functions/javascript/package.lint.json +1 -1
  46. package/templates/init/functions/javascript/package.nolint.json +1 -1
  47. package/templates/init/functions/typescript/package.lint.json +1 -1
  48. package/templates/init/functions/typescript/package.nolint.json +1 -1
  49. package/CHANGELOG.md +0 -1
@@ -77,6 +77,7 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
77
77
  "You may only select one option.",
78
78
  choices: utils_1.convertExtensionOptionToLabeledList(paramSpec.options),
79
79
  });
80
+ valid = checkResponse(response, paramSpec);
80
81
  break;
81
82
  case extensionsApi_1.ParamType.MULTISELECT:
82
83
  response = await utils_1.onceWithJoin({
@@ -95,11 +96,13 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
95
96
  "You may select multiple options.",
96
97
  choices: utils_1.convertExtensionOptionToLabeledList(paramSpec.options),
97
98
  });
99
+ valid = checkResponse(response, paramSpec);
98
100
  break;
99
101
  case extensionsApi_1.ParamType.SECRET:
100
102
  response = reconfiguring
101
103
  ? await promptReconfigureSecret(projectId, instanceId, paramSpec)
102
104
  : await promptCreateSecret(projectId, instanceId, paramSpec);
105
+ valid = true;
103
106
  break;
104
107
  default:
105
108
  response = await prompt_1.promptOnce({
@@ -108,8 +111,8 @@ async function askForParam(projectId, instanceId, paramSpec, reconfiguring) {
108
111
  default: paramSpec.default,
109
112
  message: `Enter a value for ${label}:`,
110
113
  });
114
+ valid = checkResponse(response, paramSpec);
111
115
  }
112
- valid = checkResponse(response, paramSpec);
113
116
  }
114
117
  return response;
115
118
  }
@@ -139,10 +142,24 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
139
142
  type: "password",
140
143
  message: `This secret will be stored in Cloud Secret Manager as ${secretName}.\nEnter new value for ${paramSpec.label.trim()}:`,
141
144
  });
142
- if (!secret) {
143
- secret = await secretManagerApi.createSecret(projectId, secretName, secretsUtils.getSecretLabels(instanceId));
145
+ if (secretValue === "" && paramSpec.required) {
146
+ logger_1.logger.info(`Secret value cannot be empty for required param ${paramSpec.param}`);
147
+ return promptReconfigureSecret(projectId, instanceId, paramSpec);
148
+ }
149
+ else if (secretValue !== "") {
150
+ if (checkResponse(secretValue, paramSpec)) {
151
+ if (!secret) {
152
+ secret = await secretManagerApi.createSecret(projectId, secretName, secretsUtils.getSecretLabels(instanceId));
153
+ }
154
+ return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
155
+ }
156
+ else {
157
+ return promptReconfigureSecret(projectId, instanceId, paramSpec);
158
+ }
159
+ }
160
+ else {
161
+ return "";
144
162
  }
145
- return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
146
163
  case SecretUpdateAction.LEAVE:
147
164
  default:
148
165
  return paramSpec.default || "";
@@ -158,13 +175,20 @@ async function promptCreateSecret(projectId, instanceId, paramSpec, secretName)
158
175
  });
159
176
  if (secretValue === "" && paramSpec.required) {
160
177
  logger_1.logger.info(`Secret value cannot be empty for required param ${paramSpec.param}`);
161
- return await promptCreateSecret(projectId, instanceId, paramSpec, name);
178
+ return promptCreateSecret(projectId, instanceId, paramSpec, name);
162
179
  }
163
180
  else if (secretValue !== "") {
164
- const secret = await secretManagerApi.createSecret(projectId, name, secretsUtils.getSecretLabels(instanceId));
165
- return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
181
+ if (checkResponse(secretValue, paramSpec)) {
182
+ const secret = await secretManagerApi.createSecret(projectId, name, secretsUtils.getSecretLabels(instanceId));
183
+ return addNewSecretVersion(projectId, instanceId, secret, paramSpec, secretValue);
184
+ }
185
+ else {
186
+ return promptCreateSecret(projectId, instanceId, paramSpec, name);
187
+ }
188
+ }
189
+ else {
190
+ return "";
166
191
  }
167
- return secretValue;
168
192
  }
169
193
  exports.promptCreateSecret = promptCreateSecret;
170
194
  async function generateSecretName(projectId, instanceId, paramName) {
@@ -9,6 +9,7 @@ function functionResourceToEmulatedTriggerDefintion(resource) {
9
9
  const etd = {
10
10
  name: resource.name,
11
11
  entryPoint: resource.name,
12
+ platform: "gcfv1",
12
13
  };
13
14
  const properties = _.get(resource, "properties", {});
14
15
  if (properties.timeout) {
@@ -32,11 +32,11 @@ const RESERVED_KEYS = [
32
32
  const LINE_RE = new RegExp("^" +
33
33
  "\\s*" +
34
34
  "(\\w+)" +
35
- "\\s*=\\s*" +
35
+ "\\s*=[\\f\\t\\v]*" +
36
36
  "(" +
37
37
  "\\s*'(?:\\\\'|[^'])*'|" +
38
38
  '\\s*"(?:\\\\"|[^"])*"|' +
39
- "[^#\\r\\n]+" +
39
+ "[^#\\r\\n]*" +
40
40
  ")?" +
41
41
  "\\s*" +
42
42
  "(?:#[^\\n]*)?" +
@@ -4,6 +4,7 @@ exports.functionFromEndpoint = exports.endpointFromFunction = exports.listAllFun
4
4
  const clc = require("cli-color");
5
5
  const error_1 = require("../error");
6
6
  const logger_1 = require("../logger");
7
+ const previews_1 = require("../previews");
7
8
  const api = require("../api");
8
9
  const backend = require("../deploy/functions/backend");
9
10
  const utils = require("../utils");
@@ -50,8 +51,12 @@ async function createFunction(cloudFunction) {
50
51
  const apiPath = cloudFunction.name.substring(0, cloudFunction.name.lastIndexOf("/"));
51
52
  const endpoint = `/${exports.API_VERSION}/${apiPath}`;
52
53
  try {
54
+ const headers = {};
55
+ if (previews_1.previews.artifactregistry) {
56
+ headers["X-Firebase-Artifact-Registry"] = "optin";
57
+ }
53
58
  const res = await api.request("POST", endpoint, {
54
- headers: { "X-Firebase-Artifact-Registry": "optin" },
59
+ headers,
55
60
  auth: true,
56
61
  data: cloudFunction,
57
62
  origin: api.functionsOrigin,
@@ -146,8 +151,12 @@ async function updateFunction(cloudFunction) {
146
151
  const endpoint = `/${exports.API_VERSION}/${cloudFunction.name}`;
147
152
  const fieldMasks = proto.fieldMasks(cloudFunction, "labels", "environmentVariables");
148
153
  try {
154
+ const headers = {};
155
+ if (previews_1.previews.artifactregistry) {
156
+ headers["X-Firebase-Artifact-Registry"] = "optin";
157
+ }
149
158
  const res = await api.request("PATCH", endpoint, {
150
- headers: { "X-Firebase-Artifact-Registry": "optin" },
159
+ headers,
151
160
  qs: {
152
161
  updateMask: fieldMasks.join(","),
153
162
  },
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
3
+ exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.megabytes = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
4
4
  const clc = require("cli-color");
5
5
  const apiv2_1 = require("../apiv2");
6
6
  const error_1 = require("../error");
@@ -17,6 +17,35 @@ const client = new apiv2_1.Client({
17
17
  apiVersion: exports.API_VERSION,
18
18
  });
19
19
  exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
20
+ const BYTES_PER_UNIT = {
21
+ "": 1,
22
+ k: 1e3,
23
+ M: 1e6,
24
+ G: 1e9,
25
+ T: 1e12,
26
+ Ki: 1 << 10,
27
+ Mi: 1 << 20,
28
+ Gi: 1 << 30,
29
+ Ti: 1 << 40,
30
+ };
31
+ function megabytes(memory) {
32
+ const re = /^([0-9]+(\.[0-9]*)?)(Ki|Mi|Gi|Ti|k|M|G|T|([eE]([0-9]+)))?$/;
33
+ const matches = re.exec(memory);
34
+ if (!matches) {
35
+ throw new Error(`Invalid memory quantity "${memory}""`);
36
+ }
37
+ const quantity = Number.parseFloat(matches[1]);
38
+ let bytes;
39
+ if (matches[5]) {
40
+ bytes = quantity * Math.pow(10, Number.parseFloat(matches[5]));
41
+ }
42
+ else {
43
+ const suffix = matches[3] || "";
44
+ bytes = quantity * BYTES_PER_UNIT[suffix];
45
+ }
46
+ return bytes / 1e6;
47
+ }
48
+ exports.megabytes = megabytes;
20
49
  function functionsOpLogReject(funcName, type, err) {
21
50
  var _a, _b;
22
51
  if (((_b = (_a = err === null || err === void 0 ? void 0 : err.context) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode) === 429) {
@@ -136,7 +165,8 @@ function functionFromEndpoint(endpoint, source) {
136
165
  serviceConfig: {},
137
166
  };
138
167
  proto.copyIfPresent(gcfFunction, endpoint, "labels");
139
- proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemoryMb", "environmentVariables", "vpcConnector", "vpcConnectorEgressSettings", "serviceAccountEmail", "ingressSettings");
168
+ proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "vpcConnector", "vpcConnectorEgressSettings", "serviceAccountEmail", "ingressSettings");
169
+ proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemory", "availableMemoryMb", (mb) => `${mb}M`);
140
170
  proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
141
171
  proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
142
172
  proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
@@ -153,6 +183,7 @@ function functionFromEndpoint(endpoint, source) {
153
183
  gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
154
184
  }
155
185
  }
186
+ proto.renameIfPresent(gcfFunction.eventTrigger, endpoint.eventTrigger, "triggerRegion", "region");
156
187
  if (endpoint.eventTrigger.retry) {
157
188
  logger_1.logger.warn("Cannot set a retry policy on Cloud Function", endpoint.id);
158
189
  }
@@ -207,7 +238,8 @@ function endpointFromFunction(gcfFunction) {
207
238
  const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
208
239
  project,
209
240
  region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
210
- proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "availableMemoryMb", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
241
+ proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
242
+ proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "availableMemoryMb", "availableMemory", megabytes);
211
243
  proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
212
244
  proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
213
245
  proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
package/lib/gcp/docker.js CHANGED
@@ -1,8 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Client = void 0;
3
+ exports.Client = exports.GCR_SUBDOMAIN_MAPPING = void 0;
4
4
  const error_1 = require("../error");
5
5
  const api = require("../apiv2");
6
+ exports.GCR_SUBDOMAIN_MAPPING = {
7
+ "us-west1": "us",
8
+ "us-west2": "us",
9
+ "us-west3": "us",
10
+ "us-west4": "us",
11
+ "us-central1": "us",
12
+ "us-central2": "us",
13
+ "us-east1": "us",
14
+ "us-east4": "us",
15
+ "northamerica-northeast1": "us",
16
+ "southamerica-east1": "us",
17
+ "europe-west1": "eu",
18
+ "europe-west2": "eu",
19
+ "europe-west3": "eu",
20
+ "europe-west4": "eu",
21
+ "europe-west5": "eu",
22
+ "europe-west6": "eu",
23
+ "europe-central2": "eu",
24
+ "europe-north1": "eu",
25
+ "asia-east1": "asia",
26
+ "asia-east2": "asia",
27
+ "asia-northeast1": "asia",
28
+ "asia-northeast2": "asia",
29
+ "asia-northeast3": "asia",
30
+ "asia-south1": "asia",
31
+ "asia-southeast2": "asia",
32
+ "australia-southeast1": "asia",
33
+ };
6
34
  function isErrors(response) {
7
35
  return !!response && Object.prototype.hasOwnProperty.call(response, "errors");
8
36
  }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.regionInLocation = exports.DUAL_REGION_MAPPING = exports.MULTI_REGION_MAPPING = void 0;
4
+ exports.MULTI_REGION_MAPPING = {
5
+ "us-central1": "us",
6
+ "us-east1": "us",
7
+ "us-east4": "us",
8
+ "us-west1": "us",
9
+ "us-west2": "us",
10
+ "us-west3": "us",
11
+ "us-west4": "us",
12
+ "europe-central2": "eu",
13
+ "europe-north1": "eu",
14
+ "europe-west1": "eu",
15
+ "europe-west3": "eu",
16
+ "europe-west4": "eu",
17
+ "europe-west5": "eu",
18
+ "asia-east1": "asia",
19
+ "asia-east2": "asia",
20
+ "asia-northeast1": "asia",
21
+ "asia-northeast2": "asia",
22
+ "asia-northeast3": "asia",
23
+ "asia-south1": "asia",
24
+ "asia-south2": "asia",
25
+ "asia-southeast1": "asia",
26
+ "asia-southeast2": "asia",
27
+ };
28
+ exports.DUAL_REGION_MAPPING = {
29
+ "asia-northeast1": "asia1",
30
+ "asia-northeast2": "asia1",
31
+ "europe-north1": "eur4",
32
+ "europe-west4": "eur4",
33
+ "us-central1": "nam4",
34
+ "us-east1": "nam4",
35
+ };
36
+ function regionInLocation(region, location) {
37
+ region = region.toLowerCase();
38
+ location = location.toLowerCase();
39
+ if (exports.MULTI_REGION_MAPPING[region] === location || exports.DUAL_REGION_MAPPING[region] === location) {
40
+ return true;
41
+ }
42
+ return false;
43
+ }
44
+ exports.regionInLocation = regionInLocation;
@@ -1,26 +1,29 @@
1
1
  "use strict";
2
- var path = require("path");
3
- var api = require("../api");
4
- const { logger } = require("../logger");
5
- var { FirebaseError } = require("../error");
6
- function _getDefaultBucket(projectId) {
7
- return api
8
- .request("GET", "/v1/apps/" + projectId, {
9
- auth: true,
10
- origin: api.appengineOrigin,
11
- })
12
- .then(function (resp) {
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getServiceAccount = exports.getBucket = exports.deleteObject = exports.uploadObject = exports.upload = exports.getDefaultBucket = void 0;
4
+ const path = require("path");
5
+ const api = require("../api");
6
+ const logger_1 = require("../logger");
7
+ const error_1 = require("../error");
8
+ async function getDefaultBucket(projectId) {
9
+ try {
10
+ const resp = await api.request("GET", "/v1/apps/" + projectId, {
11
+ auth: true,
12
+ origin: api.appengineOrigin,
13
+ });
13
14
  if (resp.body.defaultBucket === "undefined") {
14
- logger.debug("Default storage bucket is undefined.");
15
- return Promise.reject(new FirebaseError("Your project is being set up. Please wait a minute before deploying again."));
15
+ logger_1.logger.debug("Default storage bucket is undefined.");
16
+ throw new error_1.FirebaseError("Your project is being set up. Please wait a minute before deploying again.");
16
17
  }
17
- return Promise.resolve(resp.body.defaultBucket);
18
- }, function (err) {
19
- logger.info("\n\nThere was an issue deploying your functions. Verify that your project has a Google App Engine instance setup at https://console.cloud.google.com/appengine and try again. If this issue persists, please contact support.");
20
- return Promise.reject(err);
21
- });
18
+ return resp.body.defaultBucket;
19
+ }
20
+ catch (err) {
21
+ logger_1.logger.info("\n\nThere was an issue deploying your functions. Verify that your project has a Google App Engine instance setup at https://console.cloud.google.com/appengine and try again. If this issue persists, please contact support.");
22
+ throw err;
23
+ }
22
24
  }
23
- async function _uploadSource(source, uploadUrl, extraHeaders) {
25
+ exports.getDefaultBucket = getDefaultBucket;
26
+ async function upload(source, uploadUrl, extraHeaders) {
24
27
  const url = new URL(uploadUrl);
25
28
  const result = await api.request("PUT", url.pathname + url.search, {
26
29
  data: source.stream,
@@ -33,9 +36,10 @@ async function _uploadSource(source, uploadUrl, extraHeaders) {
33
36
  generation: result.response.headers["x-goog-generation"],
34
37
  };
35
38
  }
36
- async function _uploadObject(source, bucketName) {
39
+ exports.upload = upload;
40
+ async function uploadObject(source, bucketName) {
37
41
  if (path.extname(source.file) !== ".zip") {
38
- throw new FirebaseError(`Expected a file name ending in .zip, got ${source.file}`);
42
+ throw new error_1.FirebaseError(`Expected a file name ending in .zip, got ${source.file}`);
39
43
  }
40
44
  const location = `/${bucketName}/${path.basename(source.file)}`;
41
45
  const result = await api.request("PUT", location, {
@@ -55,13 +59,15 @@ async function _uploadObject(source, bucketName) {
55
59
  generation: result.response.headers["x-goog-generation"],
56
60
  };
57
61
  }
58
- function _deleteObject(location) {
62
+ exports.uploadObject = uploadObject;
63
+ function deleteObject(location) {
59
64
  return api.request("DELETE", location, {
60
65
  auth: true,
61
66
  origin: api.storageOrigin,
62
67
  });
63
68
  }
64
- async function _getBucket(bucketName) {
69
+ exports.deleteObject = deleteObject;
70
+ async function getBucket(bucketName) {
65
71
  try {
66
72
  const result = await api.request("GET", `/storage/v1/b/${bucketName}`, {
67
73
  auth: true,
@@ -70,16 +76,26 @@ async function _getBucket(bucketName) {
70
76
  return result.body;
71
77
  }
72
78
  catch (err) {
73
- logger.debug(err);
74
- throw new FirebaseError("Failed to obtain the storage bucket", {
79
+ logger_1.logger.debug(err);
80
+ throw new error_1.FirebaseError("Failed to obtain the storage bucket", {
81
+ original: err,
82
+ });
83
+ }
84
+ }
85
+ exports.getBucket = getBucket;
86
+ async function getServiceAccount(projectId) {
87
+ try {
88
+ const response = await api.request("GET", `/storage/v1/projects/${projectId}/serviceAccount`, {
89
+ auth: true,
90
+ origin: api.storageOrigin,
91
+ });
92
+ return response.body;
93
+ }
94
+ catch (err) {
95
+ logger_1.logger.debug(err);
96
+ throw new error_1.FirebaseError("Failed to obtain the Cloud Storage service agent", {
75
97
  original: err,
76
98
  });
77
99
  }
78
100
  }
79
- module.exports = {
80
- getDefaultBucket: _getDefaultBucket,
81
- deleteObject: _deleteObject,
82
- upload: _uploadSource,
83
- uploadObject: _uploadObject,
84
- getBucket: _getBucket,
85
- };
101
+ exports.getServiceAccount = getServiceAccount;
@@ -5,7 +5,7 @@ const logger_1 = require("../../../logger");
5
5
  const prompt_1 = require("../../../prompt");
6
6
  const requirePermissions_1 = require("../../../requirePermissions");
7
7
  const previews_1 = require("../../../previews");
8
- const ensureApiEnabled = require("../../../ensureApiEnabled");
8
+ const ensureApiEnabled_1 = require("../../../ensureApiEnabled");
9
9
  module.exports = async function (setup, config, options) {
10
10
  var _a, _b;
11
11
  logger_1.logger.info();
@@ -17,8 +17,8 @@ module.exports = async function (setup, config, options) {
17
17
  if (projectId) {
18
18
  await requirePermissions_1.requirePermissions(Object.assign(Object.assign({}, options), { project: projectId }));
19
19
  await Promise.all([
20
- ensureApiEnabled.enable(projectId, "cloudfunctions.googleapis.com"),
21
- ensureApiEnabled.enable(projectId, "runtimeconfig.googleapis.com"),
20
+ ensureApiEnabled_1.ensure(projectId, "cloudfunctions.googleapis.com", "unused", true),
21
+ ensureApiEnabled_1.ensure(projectId, "runtimeconfig.googleapis.com", "unused", true),
22
22
  ]);
23
23
  }
24
24
  const choices = [
@@ -31,6 +31,9 @@ async function initGitHub(setup, config, options) {
31
31
  if (!setup.projectId) {
32
32
  return utils_1.reject("Could not determine Project ID, can't set up GitHub workflow.", { exit: 1 });
33
33
  }
34
+ if (!setup.config.hosting) {
35
+ return utils_1.reject(`Didn't find a Hosting config in firebase.json. Run ${cli_color_1.bold("firebase init hosting")} instead.`);
36
+ }
34
37
  logger_1.logger.info();
35
38
  const gitRoot = getGitFolderPath();
36
39
  GIT_DIR = path.join(gitRoot, ".git");
@@ -72,7 +72,7 @@ async function doSetup(setup, config, options) {
72
72
  logger_1.logger.info(`but for now we'll just set up a default project.`);
73
73
  logger_1.logger.info();
74
74
  const projectFromRcFile = _.get(setup.rcfile, "projects.default");
75
- if (projectFromRcFile) {
75
+ if (projectFromRcFile && !options.project) {
76
76
  utils.logBullet(`.firebaserc already has a default project, using ${projectFromRcFile}.`);
77
77
  const rcProject = await projects_1.getFirebaseProject(projectFromRcFile);
78
78
  setup.projectId = rcProject.projectId;
@@ -81,6 +81,7 @@ async function doSetup(setup, config, options) {
81
81
  }
82
82
  let projectMetaData;
83
83
  if (options.project) {
84
+ logger_1.logger.debug(`Using project from CLI flag: ${options.project}`);
84
85
  projectMetaData = await projects_1.getFirebaseProject(options.project);
85
86
  }
86
87
  else {
package/lib/previews.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.previews = void 0;
4
4
  const lodash_1 = require("lodash");
5
5
  const configstore_1 = require("./configstore");
6
- exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, dotenv: false }, configstore_1.configstore.get("previews"));
6
+ exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, dotenv: false, artifactregistry: false }, configstore_1.configstore.get("previews"));
7
7
  if (process.env.FIREBASE_CLI_PREVIEWS) {
8
8
  process.env.FIREBASE_CLI_PREVIEWS.split(",").forEach((feature) => {
9
9
  if (lodash_1.has(exports.previews, feature)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "9.23.0",
3
+ "version": "10.0.1",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -55,7 +55,7 @@
55
55
  ],
56
56
  "preferGlobal": true,
57
57
  "engines": {
58
- "node": ">= 10.13"
58
+ "node": ">= 12"
59
59
  },
60
60
  "author": "Firebase (https://firebase.google.com/)",
61
61
  "license": "MIT",
@@ -94,7 +94,7 @@
94
94
  "chokidar": "^3.0.2",
95
95
  "cjson": "^0.3.1",
96
96
  "cli-color": "^1.2.0",
97
- "cli-table": "^0.3.8",
97
+ "cli-table": "0.3.11",
98
98
  "commander": "^4.0.1",
99
99
  "configstore": "^5.0.1",
100
100
  "cors": "^2.8.5",
@@ -10,7 +10,7 @@
10
10
  "logs": "firebase functions:log"
11
11
  },
12
12
  "engines": {
13
- "node": "14"
13
+ "node": "16"
14
14
  },
15
15
  "main": "index.js",
16
16
  "dependencies": {
@@ -9,7 +9,7 @@
9
9
  "logs": "firebase functions:log"
10
10
  },
11
11
  "engines": {
12
- "node": "14"
12
+ "node": "16"
13
13
  },
14
14
  "main": "index.js",
15
15
  "dependencies": {
@@ -10,7 +10,7 @@
10
10
  "logs": "firebase functions:log"
11
11
  },
12
12
  "engines": {
13
- "node": "14"
13
+ "node": "16"
14
14
  },
15
15
  "main": "lib/index.js",
16
16
  "dependencies": {
@@ -9,7 +9,7 @@
9
9
  "logs": "firebase functions:log"
10
10
  },
11
11
  "engines": {
12
- "node": "14"
12
+ "node": "16"
13
13
  },
14
14
  "main": "lib/index.js",
15
15
  "dependencies": {
package/CHANGELOG.md DELETED
@@ -1 +0,0 @@
1
- - `firebase deploy --only extensions` now supports project specifc .env files. When deploying to multiple projects, param values that are different between projects can be put in `extensions/${extensionInstanceId}.env.${projectIdOrAlias}` and common param values can be put in `extensions/${extensionInstanceId}.env`.