firebase-tools 11.4.0 → 11.5.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 (188) hide show
  1. package/README.md +8 -15
  2. package/lib/accountImporter.js +1 -1
  3. package/lib/auth.js +3 -4
  4. package/lib/bin/firebase.js +4 -4
  5. package/lib/command.js +3 -3
  6. package/lib/commands/apps-android-sha-create.js +1 -1
  7. package/lib/commands/apps-android-sha-delete.js +1 -1
  8. package/lib/commands/apps-create.js +1 -1
  9. package/lib/commands/apps-list.js +1 -1
  10. package/lib/commands/auth-export.js +1 -1
  11. package/lib/commands/auth-import.js +1 -1
  12. package/lib/commands/database-instances-list.js +1 -1
  13. package/lib/commands/database-push.js +1 -1
  14. package/lib/commands/database-remove.js +1 -1
  15. package/lib/commands/database-set.js +1 -1
  16. package/lib/commands/database-update.js +1 -1
  17. package/lib/commands/emulators-start.js +1 -1
  18. package/lib/commands/ext-dev-deprecate.js +1 -1
  19. package/lib/commands/ext-dev-emulators-exec.js +1 -1
  20. package/lib/commands/ext-dev-emulators-start.js +1 -1
  21. package/lib/commands/ext-dev-extension-delete.js +1 -1
  22. package/lib/commands/ext-dev-list.js +1 -1
  23. package/lib/commands/ext-dev-publish.js +1 -1
  24. package/lib/commands/ext-dev-register.js +1 -1
  25. package/lib/commands/ext-dev-undeprecate.js +1 -1
  26. package/lib/commands/ext-dev-unpublish.js +1 -1
  27. package/lib/commands/ext-dev-usage.js +1 -1
  28. package/lib/commands/ext-info.js +1 -1
  29. package/lib/commands/ext-install.js +2 -2
  30. package/lib/commands/ext-update.js +1 -1
  31. package/lib/commands/ext.js +1 -1
  32. package/lib/commands/firestore-delete.js +2 -2
  33. package/lib/commands/firestore-indexes-list.js +3 -3
  34. package/lib/commands/functions-config-clone.js +1 -1
  35. package/lib/commands/functions-config-export.js +1 -1
  36. package/lib/commands/functions-config-set.js +1 -1
  37. package/lib/commands/functions-config-unset.js +1 -1
  38. package/lib/commands/functions-delete.js +1 -1
  39. package/lib/commands/functions-secrets-set.js +1 -1
  40. package/lib/commands/help.js +1 -1
  41. package/lib/commands/hosting-channel-create.js +5 -5
  42. package/lib/commands/hosting-channel-delete.js +3 -3
  43. package/lib/commands/hosting-channel-deploy.js +6 -6
  44. package/lib/commands/hosting-channel-list.js +2 -2
  45. package/lib/commands/hosting-channel-open.js +2 -2
  46. package/lib/commands/hosting-clone.js +13 -8
  47. package/lib/commands/hosting-disable.js +1 -1
  48. package/lib/commands/hosting-sites-create.js +4 -4
  49. package/lib/commands/hosting-sites-delete.js +4 -4
  50. package/lib/commands/hosting-sites-list.js +2 -2
  51. package/lib/commands/init.js +5 -5
  52. package/lib/commands/login-add.js +1 -1
  53. package/lib/commands/login-ci.js +4 -2
  54. package/lib/commands/login-list.js +1 -1
  55. package/lib/commands/login-use.js +1 -1
  56. package/lib/commands/login.js +1 -1
  57. package/lib/commands/logout.js +1 -1
  58. package/lib/commands/open.js +3 -3
  59. package/lib/commands/projects-list.js +2 -2
  60. package/lib/commands/serve.js +1 -1
  61. package/lib/commands/target-apply.js +1 -1
  62. package/lib/commands/target-clear.js +1 -1
  63. package/lib/commands/target-remove.js +1 -1
  64. package/lib/commands/target.js +1 -1
  65. package/lib/commands/use.js +7 -7
  66. package/lib/config.js +1 -1
  67. package/lib/deploy/database/prepare.js +3 -3
  68. package/lib/deploy/database/release.js +3 -3
  69. package/lib/deploy/extensions/deploymentSummary.js +1 -1
  70. package/lib/deploy/extensions/errors.js +1 -1
  71. package/lib/deploy/extensions/secrets.js +1 -1
  72. package/lib/deploy/extensions/tasks.js +2 -2
  73. package/lib/deploy/firestore/deploy.js +2 -2
  74. package/lib/deploy/firestore/prepare.js +2 -2
  75. package/lib/deploy/functions/backend.js +7 -5
  76. package/lib/deploy/functions/build.js +110 -95
  77. package/lib/deploy/functions/checkIam.js +3 -3
  78. package/lib/deploy/functions/containerCleaner.js +2 -2
  79. package/lib/deploy/functions/deploy.js +2 -2
  80. package/lib/deploy/functions/ensure.js +2 -2
  81. package/lib/deploy/functions/params.js +5 -2
  82. package/lib/deploy/functions/prepare.js +4 -4
  83. package/lib/deploy/functions/prepareFunctionsUpload.js +2 -2
  84. package/lib/deploy/functions/pricing.js +3 -2
  85. package/lib/deploy/functions/prompts.js +2 -2
  86. package/lib/deploy/functions/release/fabricator.js +10 -9
  87. package/lib/deploy/functions/release/index.js +1 -1
  88. package/lib/deploy/functions/release/reporter.js +1 -1
  89. package/lib/deploy/functions/runtimes/discovery/parsing.js +19 -8
  90. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +112 -107
  91. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +1 -1
  92. package/lib/deploy/functions/runtimes/node/parseTriggers.js +54 -26
  93. package/lib/deploy/functions/runtimes/node/versioning.js +4 -4
  94. package/lib/deploy/functions/services/storage.js +6 -0
  95. package/lib/deploy/functions/validate.js +1 -1
  96. package/lib/deploy/hosting/convertConfig.js +13 -2
  97. package/lib/deploy/hosting/deploy.js +11 -10
  98. package/lib/deploy/hosting/uploader.js +2 -2
  99. package/lib/deploy/hosting/validate.js +2 -2
  100. package/lib/deploy/index.js +7 -7
  101. package/lib/deploy/lifecycleHooks.js +5 -2
  102. package/lib/deploy/storage/prepare.js +5 -3
  103. package/lib/deploy/storage/release.js +7 -6
  104. package/lib/emulator/commandUtils.js +1 -1
  105. package/lib/emulator/controller.js +1 -1
  106. package/lib/emulator/databaseEmulator.js +1 -1
  107. package/lib/emulator/downloadableEmulators.js +1 -1
  108. package/lib/emulator/emulatorLogger.js +1 -1
  109. package/lib/emulator/extensionsEmulator.js +2 -2
  110. package/lib/emulator/firestoreEmulator.js +1 -1
  111. package/lib/emulator/functionsEmulator.js +22 -10
  112. package/lib/emulator/functionsEmulatorShared.js +6 -11
  113. package/lib/emulator/loggingEmulator.js +2 -2
  114. package/lib/emulator/storage/apis/firebase.js +13 -1
  115. package/lib/emulator/storage/apis/gcloud.js +15 -8
  116. package/lib/emulator/storage/files.js +26 -24
  117. package/lib/emulator/storage/metadata.js +6 -6
  118. package/lib/emulator/storage/multipart.js +4 -3
  119. package/lib/emulator/storage/persistence.js +26 -12
  120. package/lib/emulator/storage/rules/runtime.js +1 -1
  121. package/lib/emulator/storage/rules/utils.js +4 -2
  122. package/lib/emulator/types.js +1 -0
  123. package/lib/ensureApiEnabled.js +7 -7
  124. package/lib/extensions/askUserForConsent.js +1 -1
  125. package/lib/extensions/askUserForEventsConfig.js +1 -1
  126. package/lib/extensions/askUserForParam.js +1 -1
  127. package/lib/extensions/changelog.js +2 -2
  128. package/lib/extensions/checkProjectBilling.js +2 -2
  129. package/lib/extensions/displayExtensionInfo.js +2 -102
  130. package/lib/extensions/emulator/triggerHelper.js +2 -2
  131. package/lib/extensions/extensionsApi.js +1 -1
  132. package/lib/extensions/extensionsHelper.js +1 -1
  133. package/lib/extensions/listExtensions.js +1 -1
  134. package/lib/extensions/manifest.js +1 -1
  135. package/lib/extensions/metricsUtils.js +1 -1
  136. package/lib/extensions/paramHelper.js +1 -1
  137. package/lib/extensions/updateHelper.js +3 -9
  138. package/lib/extensions/warnings.js +2 -2
  139. package/lib/fetchMOTD.js +1 -1
  140. package/lib/firestore/delete.js +1 -1
  141. package/lib/firestore/indexes.js +2 -2
  142. package/lib/firestore/validator.js +1 -1
  143. package/lib/functional.js +16 -1
  144. package/lib/functions/env.js +3 -3
  145. package/lib/functions/runtimeConfigExport.js +1 -1
  146. package/lib/functionsConfig.js +1 -1
  147. package/lib/functionsConfigClone.js +1 -1
  148. package/lib/functionsShellCommandAction.js +1 -1
  149. package/lib/gcp/cloudfunctions.js +24 -11
  150. package/lib/gcp/cloudfunctionsv2.js +48 -24
  151. package/lib/gcp/cloudscheduler.js +58 -22
  152. package/lib/gcp/cloudtasks.js +21 -4
  153. package/lib/gcp/proto.js +18 -6
  154. package/lib/gcp/resourceManager.js +25 -3
  155. package/lib/gcp/serviceusage.js +2 -2
  156. package/lib/handlePreviewToggles.js +4 -4
  157. package/lib/hosting/implicitInit.js +1 -1
  158. package/lib/hosting/normalizedHostingConfigs.js +3 -3
  159. package/lib/index.js +3 -3
  160. package/lib/init/features/database.js +1 -1
  161. package/lib/init/features/emulators.js +1 -1
  162. package/lib/init/features/firestore/index.js +2 -2
  163. package/lib/init/features/firestore/indexes.js +1 -1
  164. package/lib/init/features/firestore/rules.js +1 -1
  165. package/lib/init/features/functions/golang.js +1 -1
  166. package/lib/init/features/functions/index.js +8 -1
  167. package/lib/init/features/hosting/github.js +9 -9
  168. package/lib/init/features/hosting/index.js +1 -1
  169. package/lib/init/features/project.js +1 -1
  170. package/lib/init/features/remoteconfig.js +1 -1
  171. package/lib/init/features/storage.js +1 -1
  172. package/lib/init/index.js +1 -1
  173. package/lib/logError.js +3 -3
  174. package/lib/management/projects.js +1 -1
  175. package/lib/parseBoltRules.js +1 -1
  176. package/lib/previews.js +1 -1
  177. package/lib/profileReport.js +2 -2
  178. package/lib/projectUtils.js +1 -1
  179. package/lib/rc.js +1 -1
  180. package/lib/requireAuth.js +5 -1
  181. package/lib/requireDatabaseInstance.js +2 -2
  182. package/lib/requirePermissions.js +2 -2
  183. package/lib/rulesDeploy.js +49 -13
  184. package/lib/serve/hosting.js +2 -1
  185. package/lib/utils.js +10 -10
  186. package/npm-shrinkwrap.json +26 -295
  187. package/package.json +8 -5
  188. package/templates/hosting/init.js +6 -2
@@ -7,24 +7,21 @@ const listFiles_1 = require("../../listFiles");
7
7
  const logger_1 = require("../../logger");
8
8
  const track_1 = require("../../track");
9
9
  const utils_1 = require("../../utils");
10
- const clc = require("cli-color");
11
- const SPINNER = ["", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
12
- const _ERASE_LINE = "\x1b[2K";
10
+ const colorette_1 = require("colorette");
11
+ const ora = require("ora");
13
12
  async function deploy(context, options) {
14
13
  var _a, _b;
15
14
  if (!((_a = context.hosting) === null || _a === void 0 ? void 0 : _a.deploys)) {
16
15
  return;
17
16
  }
18
- let spins = 0;
17
+ const spinner = ora();
19
18
  function updateSpinner(newMessage, debugging) {
20
19
  if (debugging) {
21
20
  (0, utils_1.logLabeledBullet)("hosting", newMessage);
22
21
  }
23
22
  else {
24
- process.stdout.write(_ERASE_LINE + clc.move(-9999, 0));
25
- process.stdout.write(clc.bold.cyan(SPINNER[spins % SPINNER.length] + " hosting: ") + newMessage);
23
+ spinner.text = `${(0, colorette_1.bold)((0, colorette_1.cyan)(" hosting:"))} ${newMessage}`;
26
24
  }
27
- spins++;
28
25
  }
29
26
  async function runDeploys(deploys, debugging) {
30
27
  var _a;
@@ -36,11 +33,11 @@ async function deploy(context, options) {
36
33
  (0, utils_1.logLabeledBullet)(`hosting[${deploy.site}]`, 'no "public" directory to upload, continuing with release');
37
34
  return runDeploys(deploys, debugging);
38
35
  }
39
- (0, utils_1.logLabeledBullet)("hosting[" + deploy.site + "]", "beginning deploy...");
36
+ (0, utils_1.logLabeledBullet)(`hosting[${deploy.site}]`, "beginning deploy...");
40
37
  const t0 = Date.now();
41
38
  const publicDir = options.config.path(deploy.config.public);
42
39
  const files = (0, listFiles_1.listFiles)(publicDir, deploy.config.ignore);
43
- (0, utils_1.logLabeledBullet)(`hosting[${deploy.site}]`, `found ${files.length} files in ${clc.bold(deploy.config.public)}`);
40
+ (0, utils_1.logLabeledBullet)(`hosting[${deploy.site}]`, `found ${files.length} files in ${(0, colorette_1.bold)(deploy.config.public)}`);
44
41
  let concurrency = 200;
45
42
  const envConcurrency = (0, utils_1.envOverride)("FIREBASE_HOSTING_UPLOAD_CONCURRENCY", "");
46
43
  if (envConcurrency) {
@@ -59,6 +56,9 @@ async function deploy(context, options) {
59
56
  uploadConcurrency: concurrency,
60
57
  });
61
58
  const progressInterval = setInterval(() => updateSpinner(uploader.statusMessage(), debugging), debugging ? 2000 : 200);
59
+ if (!debugging) {
60
+ spinner.start();
61
+ }
62
62
  try {
63
63
  await uploader.start();
64
64
  }
@@ -68,9 +68,10 @@ async function deploy(context, options) {
68
68
  }
69
69
  finally {
70
70
  clearInterval(progressInterval);
71
+ updateSpinner(uploader.statusMessage(), debugging);
71
72
  }
72
73
  if (!debugging) {
73
- process.stdout.write(_ERASE_LINE + clc.move(-9999, 0));
74
+ spinner.stop();
74
75
  }
75
76
  (0, utils_1.logLabeledSuccess)("hosting[" + deploy.site + "]", "file upload complete");
76
77
  const dt = Date.now() - t0;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Uploader = void 0;
4
4
  const lodash_1 = require("lodash");
5
5
  const abort_controller_1 = require("abort-controller");
6
- const clc = require("cli-color");
6
+ const clc = require("colorette");
7
7
  const crypto = require("crypto");
8
8
  const fs = require("fs");
9
9
  const path = require("path");
@@ -19,7 +19,7 @@ const MAX_UPLOAD_TIMEOUT = 7200000;
19
19
  function progressMessage(message, current, total) {
20
20
  current = Math.min(current, total);
21
21
  const percent = Math.floor(((current * 1.0) / total) * 100).toString();
22
- return `${message} [${current}/${total}] (${clc.bold.green(`${percent}%`)})`;
22
+ return `${message} [${current}/${total}] (${clc.bold(clc.green(`${percent}%`))})`;
23
23
  }
24
24
  class Uploader {
25
25
  constructor(options) {
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateDeploy = 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 projectPath_1 = require("../../projectPath");
8
8
  const fsutils_1 = require("../../fsutils");
@@ -33,7 +33,7 @@ function validateDeploy(deploy, options) {
33
33
  else {
34
34
  const i18nPath = path.join(cfg.public, cfg.i18n.root);
35
35
  if (!(0, fsutils_1.dirExistsSync)((0, projectPath_1.resolveProjectPath)(options, i18nPath))) {
36
- (0, utils_1.logLabeledWarning)("hosting", `Couldn't find specified i18n root directory ${clc.bold(cfg.i18n.root)} in public directory ${clc.bold(cfg.public)}.`);
36
+ (0, utils_1.logLabeledWarning)("hosting", `Couldn't find specified i18n root directory ${clc.bold(cfg.i18n.root)} in public directory ${clc.bold(cfg.public || "")}.`);
37
37
  }
38
38
  }
39
39
  }
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deploy = void 0;
4
4
  const logger_1 = require("../logger");
5
5
  const api_1 = require("../api");
6
- const cli_color_1 = require("cli-color");
6
+ const colorette_1 = require("colorette");
7
7
  const lodash_1 = require("lodash");
8
8
  const projectUtils_1 = require("../projectUtils");
9
9
  const utils_1 = require("../utils");
@@ -52,7 +52,7 @@ const deploy = async function (targetNames, options, customContext = {}) {
52
52
  for (const targetName of targetNames) {
53
53
  const target = TARGETS[targetName];
54
54
  if (!target) {
55
- return Promise.reject(new error_1.FirebaseError(`${(0, cli_color_1.bold)(targetName)} is not a valid deploy target`));
55
+ return Promise.reject(new error_1.FirebaseError(`${(0, colorette_1.bold)(targetName)} is not a valid deploy target`));
56
56
  }
57
57
  predeploys.push((0, lifecycleHooks_1.lifecycleHooks)(targetName, "predeploy"));
58
58
  prepares.push(target.prepare);
@@ -61,9 +61,9 @@ const deploy = async function (targetNames, options, customContext = {}) {
61
61
  postdeploys.push((0, lifecycleHooks_1.lifecycleHooks)(targetName, "postdeploy"));
62
62
  }
63
63
  logger_1.logger.info();
64
- logger_1.logger.info((0, cli_color_1.bold)((0, cli_color_1.white)("===") + " Deploying to '" + projectId + "'..."));
64
+ logger_1.logger.info((0, colorette_1.bold)((0, colorette_1.white)("===") + " Deploying to '" + projectId + "'..."));
65
65
  logger_1.logger.info();
66
- (0, utils_1.logBullet)("deploying " + (0, cli_color_1.bold)(targetNames.join(", ")));
66
+ (0, utils_1.logBullet)("deploying " + (0, colorette_1.bold)(targetNames.join(", ")));
67
67
  await chain(predeploys, context, options, payload);
68
68
  await chain(prepares, context, options, payload);
69
69
  await chain(deploys, context, options, payload);
@@ -75,13 +75,13 @@ const deploy = async function (targetNames, options, customContext = {}) {
75
75
  const duration = Date.now() - startTime;
76
76
  await (0, track_1.track)("Product Deploy", [...targetNames].sort().join(","), duration);
77
77
  logger_1.logger.info();
78
- (0, utils_1.logSuccess)(cli_color_1.bold.underline("Deploy complete!"));
78
+ (0, utils_1.logSuccess)((0, colorette_1.bold)((0, colorette_1.underline)("Deploy complete!")));
79
79
  logger_1.logger.info();
80
80
  const deployedHosting = (0, lodash_1.includes)(targetNames, "hosting");
81
- logger_1.logger.info((0, cli_color_1.bold)("Project Console:"), (0, utils_1.consoleUrl)(options.project, "/overview"));
81
+ logger_1.logger.info((0, colorette_1.bold)("Project Console:"), (0, utils_1.consoleUrl)(options.project, "/overview"));
82
82
  if (deployedHosting) {
83
83
  (0, lodash_1.each)(context.hosting.deploys, (deploy) => {
84
- logger_1.logger.info((0, cli_color_1.bold)("Hosting URL:"), (0, utils_1.addSubdomain)(api_1.hostingOrigin, deploy.site));
84
+ logger_1.logger.info((0, colorette_1.bold)("Hosting URL:"), (0, utils_1.addSubdomain)(api_1.hostingOrigin, deploy.site));
85
85
  });
86
86
  const versionNames = context.hosting.deploys.map((deploy) => deploy.version);
87
87
  return { hosting: versionNames.length === 1 ? versionNames[0] : versionNames };
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.lifecycleHooks = void 0;
4
4
  const utils = require("../utils");
5
- const clc = require("cli-color");
5
+ const clc = require("colorette");
6
6
  const childProcess = require("child_process");
7
7
  const error_1 = require("../error");
8
8
  const needProjectId = require("../projectUtils").needProjectId;
@@ -82,7 +82,10 @@ function runTargetCommands(target, hook, overallOptions, config) {
82
82
  }
83
83
  return runAllCommands
84
84
  .then(() => {
85
- utils.logSuccess(clc.green.bold(logIdentifier + ":") + " Finished running " + clc.bold(hook) + " script.");
85
+ utils.logSuccess(clc.green(clc.bold(logIdentifier + ":")) +
86
+ " Finished running " +
87
+ clc.bold(hook) +
88
+ " script.");
86
89
  })
87
90
  .catch((err) => {
88
91
  throw new error_1.FirebaseError(logIdentifier + " " + hook + " error: " + err.message);
@@ -24,13 +24,11 @@ async function default_1(context, options) {
24
24
  }
25
25
  }
26
26
  }
27
- _.set(context, "storage.rules", rulesConfig);
28
27
  const rulesDeploy = new rulesDeploy_1.RulesDeploy(options, rulesDeploy_1.RulesetServiceType.FIREBASE_STORAGE);
29
- _.set(context, "storage.rulesDeploy", rulesDeploy);
28
+ const rulesConfigsToDeploy = [];
30
29
  if (!Array.isArray(rulesConfig)) {
31
30
  const defaultBucket = await gcp.storage.getDefaultBucket(options.project);
32
31
  rulesConfig = [Object.assign(rulesConfig, { bucket: defaultBucket })];
33
- _.set(context, "storage.rules", rulesConfig);
34
32
  }
35
33
  for (const ruleConfig of rulesConfig) {
36
34
  const target = ruleConfig.target;
@@ -39,12 +37,16 @@ async function default_1(context, options) {
39
37
  }
40
38
  if (allStorage || onlyTargets.has(target)) {
41
39
  rulesDeploy.addFile(ruleConfig.rules);
40
+ rulesConfigsToDeploy.push(ruleConfig);
42
41
  onlyTargets.delete(target);
43
42
  }
44
43
  }
45
44
  if (!allStorage && onlyTargets.size !== 0) {
46
45
  throw new error_1.FirebaseError(`Could not find rules for the following storage targets: ${[...onlyTargets].join(", ")}`);
47
46
  }
47
+ _.set(context, "storage.rules", rulesConfig);
48
+ _.set(context, "storage.rulesConfigsToDeploy", rulesConfigsToDeploy);
49
+ _.set(context, "storage.rulesDeploy", rulesDeploy);
48
50
  await rulesDeploy.compile();
49
51
  }
50
52
  exports.default = default_1;
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const lodash_1 = require("lodash");
4
4
  const rulesDeploy_1 = require("../../rulesDeploy");
5
5
  async function default_1(context, options) {
6
- const rules = (0, lodash_1.get)(context, "storage.rules", []);
6
+ const rulesConfigsToDeploy = (0, lodash_1.get)(context, "storage.rulesConfigsToDeploy", []);
7
7
  const rulesDeploy = (0, lodash_1.get)(context, "storage.rulesDeploy");
8
- if (!rules.length || !rulesDeploy) {
9
- return;
8
+ if (!rulesConfigsToDeploy.length || !rulesDeploy) {
9
+ return [];
10
10
  }
11
11
  const toRelease = [];
12
- for (const ruleConfig of rules) {
12
+ for (const ruleConfig of rulesConfigsToDeploy) {
13
13
  if (ruleConfig.target) {
14
14
  options.rc.target(options.project, "storage", ruleConfig.target).forEach((bucket) => {
15
15
  toRelease.push({ bucket: bucket, rules: ruleConfig.rules });
@@ -19,8 +19,9 @@ async function default_1(context, options) {
19
19
  toRelease.push({ bucket: ruleConfig.bucket, rules: ruleConfig.rules });
20
20
  }
21
21
  }
22
- await Promise.all(toRelease.map((release) => {
23
- return rulesDeploy.release(release.rules, rulesDeploy_1.RulesetServiceType.FIREBASE_STORAGE, release.bucket);
22
+ await Promise.all(toRelease.map((r) => {
23
+ return rulesDeploy.release(r.rules, rulesDeploy_1.RulesetServiceType.FIREBASE_STORAGE, r.bucket);
24
24
  }));
25
+ return toRelease.map((r) => r.bucket);
25
26
  }
26
27
  exports.default = default_1;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JAVA_DEPRECATION_WARNING = exports.checkJavaSupported = exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
4
- const clc = require("cli-color");
4
+ const clc = require("colorette");
5
5
  const childProcess = require("child_process");
6
6
  const controller = require("../emulator/controller");
7
7
  const config_1 = require("../config");
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.exportEmulatorData = exports.startAll = exports.shouldStart = exports.filterEmulatorTargets = exports.cleanShutdown = exports.onExit = exports.exportOnExit = exports.startEmulator = void 0;
4
- const clc = require("cli-color");
4
+ const clc = require("colorette");
5
5
  const fs = require("fs");
6
6
  const path = require("path");
7
7
  const logger_1 = require("../logger");
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DatabaseEmulator = void 0;
4
4
  const chokidar = require("chokidar");
5
- const clc = require("cli-color");
5
+ const clc = require("colorette");
6
6
  const fs = require("fs");
7
7
  const path = require("path");
8
8
  const http = require("http");
@@ -7,7 +7,7 @@ const error_1 = require("../error");
7
7
  const childProcess = require("child_process");
8
8
  const utils = require("../utils");
9
9
  const emulatorLogger_1 = require("./emulatorLogger");
10
- const clc = require("cli-color");
10
+ const clc = require("colorette");
11
11
  const fs = require("fs-extra");
12
12
  const path = require("path");
13
13
  const os = require("os");
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmulatorLogger = exports.Verbosity = void 0;
4
- const clc = require("cli-color");
4
+ const clc = require("colorette");
5
5
  const utils = require("../utils");
6
6
  const logger_1 = require("../logger");
7
7
  const utils_1 = require("../utils");
@@ -4,7 +4,7 @@ exports.ExtensionsEmulator = void 0;
4
4
  const fs = require("fs-extra");
5
5
  const os = require("os");
6
6
  const path = require("path");
7
- const clc = require("cli-color");
7
+ const clc = require("colorette");
8
8
  const Table = require("cli-table");
9
9
  const spawn = require("cross-spawn");
10
10
  const planner = require("../deploy/extensions/planner");
@@ -186,7 +186,7 @@ class ExtensionsEmulator {
186
186
  apiToWarn.apiName,
187
187
  apiToWarn.instanceIds,
188
188
  apiToWarn.enabled ? "Yes" : "No",
189
- apiToWarn.enabled ? "" : clc.bold.underline(enablementUri),
189
+ apiToWarn.enabled ? "" : clc.bold(clc.underline(enablementUri)),
190
190
  ]);
191
191
  }
192
192
  if (constants_1.Constants.isDemoProject(this.args.projectId)) {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FirestoreEmulator = void 0;
4
4
  const chokidar = require("chokidar");
5
5
  const fs = require("fs");
6
- const clc = require("cli-color");
6
+ const clc = require("colorette");
7
7
  const path = require("path");
8
8
  const utils = require("../utils");
9
9
  const downloadableEmulators = require("./downloadableEmulators");
@@ -4,7 +4,7 @@ exports.FunctionsEmulator = void 0;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const express = require("express");
7
- const clc = require("cli-color");
7
+ const clc = require("colorette");
8
8
  const http = require("http");
9
9
  const jwt = require("jsonwebtoken");
10
10
  const cors = require("cors");
@@ -245,15 +245,9 @@ class FunctionsEmulator {
245
245
  await this.destroyServer();
246
246
  }
247
247
  }
248
- async loadTriggers(emulatableBackend, force = false) {
249
- this.workerPool.refresh();
250
- if (!emulatableBackend.nodeBinary) {
251
- throw new error_1.FirebaseError(`No node binary for ${emulatableBackend.functionsDir}. This should never happen.`);
252
- }
253
- this.blockingFunctionsConfig = {};
254
- let triggerDefinitions;
248
+ async discoverTriggers(emulatableBackend) {
255
249
  if (emulatableBackend.predefinedTriggers) {
256
- triggerDefinitions = (0, functionsEmulatorShared_1.emulatedFunctionsByRegion)(emulatableBackend.predefinedTriggers, emulatableBackend.secretEnv);
250
+ return (0, functionsEmulatorShared_1.emulatedFunctionsByRegion)(emulatableBackend.predefinedTriggers, emulatableBackend.secretEnv);
257
251
  }
258
252
  else {
259
253
  const runtimeConfig = this.getRuntimeConfig(emulatableBackend);
@@ -284,8 +278,26 @@ class FunctionsEmulator {
284
278
  for (const e of endpoints) {
285
279
  e.codebase = emulatableBackend.codebase;
286
280
  }
287
- triggerDefinitions = (0, functionsEmulatorShared_1.emulatedFunctionsFromEndpoints)(endpoints);
281
+ return (0, functionsEmulatorShared_1.emulatedFunctionsFromEndpoints)(endpoints);
282
+ }
283
+ }
284
+ async loadTriggers(emulatableBackend, force = false) {
285
+ if (!emulatableBackend.nodeBinary) {
286
+ throw new error_1.FirebaseError(`No node binary for ${emulatableBackend.functionsDir}. This should never happen.`);
288
287
  }
288
+ let triggerDefinitions = [];
289
+ try {
290
+ triggerDefinitions = await this.discoverTriggers(emulatableBackend);
291
+ this.logger.logLabeled("SUCCESS", "functions", `Loaded functions definitions from source: ${triggerDefinitions
292
+ .map((t) => t.entryPoint)
293
+ .join(", ")}.`);
294
+ }
295
+ catch (e) {
296
+ this.logger.logLabeled("ERROR", "functions", `Failed to load function definition from source: ${e}`);
297
+ return;
298
+ }
299
+ this.workerPool.refresh();
300
+ this.blockingFunctionsConfig = {};
289
301
  const toSetup = triggerDefinitions.filter((definition) => {
290
302
  if (force) {
291
303
  return true;
@@ -8,20 +8,11 @@ const crypto_1 = require("crypto");
8
8
  const _ = require("lodash");
9
9
  const backend = require("../deploy/functions/backend");
10
10
  const constants_1 = require("./constants");
11
- const proto_1 = require("../gcp/proto");
12
11
  const manifest_1 = require("../extensions/manifest");
13
12
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
14
13
  const postinstall_1 = require("./extensions/postinstall");
15
14
  const services_1 = require("../deploy/functions/services");
16
15
  const prepare_1 = require("../deploy/functions/prepare");
17
- const memoryLookup = {
18
- "128MB": 128,
19
- "256MB": 256,
20
- "512MB": 512,
21
- "1GB": 1024,
22
- "2GB": 2048,
23
- "4GB": 4096,
24
- };
25
16
  class HttpConstants {
26
17
  }
27
18
  exports.HttpConstants = HttpConstants;
@@ -33,7 +24,7 @@ class EmulatedTrigger {
33
24
  this.module = module;
34
25
  }
35
26
  get memoryLimitBytes() {
36
- return memoryLookup[this.definition.availableMemoryMb || "128MB"] * 1024 * 1024;
27
+ return (this.definition.availableMemoryMb || 128) * 1024 * 1024;
37
28
  }
38
29
  get timeoutMs() {
39
30
  return (this.definition.timeoutSeconds || 60) * 1000;
@@ -69,7 +60,11 @@ function emulatedFunctionsFromEndpoints(endpoints) {
69
60
  id: `${endpoint.region}-${endpoint.id}`,
70
61
  codebase: endpoint.codebase,
71
62
  };
72
- (0, proto_1.copyIfPresent)(def, endpoint, "availableMemoryMb", "labels", "timeoutSeconds", "platform", "secretEnvironmentVariables");
63
+ def.availableMemoryMb = endpoint.availableMemoryMb || 256;
64
+ def.labels = endpoint.labels || {};
65
+ def.timeoutSeconds = endpoint.timeoutSeconds || 60;
66
+ def.secretEnvironmentVariables = endpoint.secretEnvironmentVariables || [];
67
+ def.platform = endpoint.platform;
73
68
  if (backend.isHttpsTriggered(endpoint)) {
74
69
  def.httpsTrigger = endpoint.httpsTrigger;
75
70
  }
@@ -7,7 +7,7 @@ const triple_beam_1 = require("triple-beam");
7
7
  const WebSocket = require("ws");
8
8
  const TransportStream = require("winston-transport");
9
9
  const logger_1 = require("../logger");
10
- const ansiStrip = require("cli-color/strip");
10
+ const stripAnsi = require("strip-ansi");
11
11
  class LoggingEmulator {
12
12
  constructor(args) {
13
13
  this.args = args;
@@ -106,7 +106,7 @@ class WebSocketTransport extends TransportStream {
106
106
  if (bundle.data && bundle.data.metadata && bundle.data.metadata.message) {
107
107
  bundle.message = bundle.data.metadata.message;
108
108
  }
109
- bundle.message = ansiStrip(bundle.message);
109
+ bundle.message = stripAnsi(bundle.message);
110
110
  this.history.push(bundle);
111
111
  this.connections.forEach((ws) => {
112
112
  ws.send(JSON.stringify(bundle));
@@ -121,10 +121,22 @@ function createFirebaseEndpoints(emulator) {
121
121
  var _a, _b, _c, _d;
122
122
  const maxResults = (_a = req.query.maxResults) === null || _a === void 0 ? void 0 : _a.toString();
123
123
  let listResponse;
124
+ let prefix = "";
125
+ if (req.query.prefix) {
126
+ prefix = req.query.prefix.toString();
127
+ if (prefix.charAt(prefix.length - 1) !== "/") {
128
+ return res.status(400).json({
129
+ error: {
130
+ code: 400,
131
+ message: "The prefix parameter is required to be empty or ends with a single / character.",
132
+ },
133
+ });
134
+ }
135
+ }
124
136
  try {
125
137
  listResponse = await storageLayer.listObjects({
126
138
  bucketId: req.params.bucketId,
127
- prefix: req.query.prefix ? req.query.prefix.toString() : "",
139
+ prefix: prefix,
128
140
  delimiter: req.query.delimiter ? req.query.delimiter.toString() : "",
129
141
  pageToken: (_b = req.query.pageToken) === null || _b === void 0 ? void 0 : _b.toString(),
130
142
  maxResults: maxResults ? +maxResults : undefined,
@@ -177,14 +177,6 @@ function createCloudEndpoints(emulator) {
177
177
  });
178
178
  });
179
179
  gcloudStorageAPI.post("/upload/storage/v1/b/:bucketId/o", async (req, res) => {
180
- if (!req.query.name) {
181
- res.sendStatus(400);
182
- return;
183
- }
184
- let name = req.query.name.toString();
185
- if (name.startsWith("/")) {
186
- name = name.slice(1);
187
- }
188
180
  const contentTypeHeader = req.header("content-type") || req.header("x-upload-content-type");
189
181
  if (!contentTypeHeader) {
190
182
  return res.sendStatus(400);
@@ -194,6 +186,11 @@ function createCloudEndpoints(emulator) {
194
186
  if (emulatorInfo === undefined) {
195
187
  return res.sendStatus(500);
196
188
  }
189
+ const name = getIncomingFileNameFromRequest(req.query, req.body);
190
+ if (name === undefined) {
191
+ res.sendStatus(400);
192
+ return;
193
+ }
197
194
  const upload = uploadService.startResumableUpload({
198
195
  bucketId: req.params.bucketId,
199
196
  objectId: name,
@@ -223,6 +220,11 @@ function createCloudEndpoints(emulator) {
223
220
  }
224
221
  throw err;
225
222
  }
223
+ const name = getIncomingFileNameFromRequest(req.query, JSON.parse(metadataRaw));
224
+ if (name === undefined) {
225
+ res.sendStatus(400);
226
+ return;
227
+ }
226
228
  const upload = uploadService.multipartUpload({
227
229
  bucketId: req.params.bucketId,
228
230
  objectId: name,
@@ -363,3 +365,8 @@ function sendObjectNotFound(req, res) {
363
365
  });
364
366
  }
365
367
  }
368
+ function getIncomingFileNameFromRequest(query, metadata) {
369
+ var _a;
370
+ const name = ((_a = query === null || query === void 0 ? void 0 : query.name) === null || _a === void 0 ? void 0 : _a.toString()) || (metadata === null || metadata === void 0 ? void 0 : metadata.name);
371
+ return (name === null || name === void 0 ? void 0 : name.startsWith("/")) ? name.slice(1) : name;
372
+ }
@@ -18,9 +18,8 @@ const adminSdkConfig_1 = require("../adminSdkConfig");
18
18
  const types_1 = require("./rules/types");
19
19
  const upload_1 = require("./upload");
20
20
  class StoredFile {
21
- constructor(metadata, path) {
21
+ constructor(metadata) {
22
22
  this.metadata = metadata;
23
- this._path = path;
24
23
  }
25
24
  get metadata() {
26
25
  return this._metadata;
@@ -28,14 +27,9 @@ class StoredFile {
28
27
  set metadata(value) {
29
28
  this._metadata = value;
30
29
  }
31
- get path() {
32
- return this._path;
33
- }
34
- set path(value) {
35
- this._path = value;
36
- }
37
30
  }
38
31
  exports.StoredFile = StoredFile;
32
+ const TRAILING_SLASHES_PATTERN = /\/+$/;
39
33
  class StorageLayer {
40
34
  constructor(_projectId, _files, _buckets, _rulesValidator, _adminCredsValidator, _persistence, _cloudFunctions) {
41
35
  this._projectId = _projectId;
@@ -144,6 +138,7 @@ class StorageLayer {
144
138
  if (upload.status !== upload_1.UploadStatus.FINISHED) {
145
139
  throw new Error(`Unexpected upload status encountered: ${upload.status}.`);
146
140
  }
141
+ const storedMetadata = this.getMetadata(upload.bucketId, upload.objectId);
147
142
  const filePath = this.path(upload.bucketId, upload.objectId);
148
143
  const metadata = new metadata_1.StoredFileMetadata({
149
144
  name: upload.objectId,
@@ -156,14 +151,17 @@ class StorageLayer {
156
151
  customMetadata: upload.metadata.metadata,
157
152
  }, this._cloudFunctions, this._persistence.readBytes(upload.path, upload.size));
158
153
  metadata.update(upload.metadata, false);
159
- const authorized = await this._rulesValidator.validate(["b", upload.bucketId, "o", upload.objectId].join("/"), upload.bucketId, types_1.RulesetOperationMethod.CREATE, { after: metadata === null || metadata === void 0 ? void 0 : metadata.asRulesResource() }, upload.authorization);
154
+ const authorized = await this._rulesValidator.validate(["b", upload.bucketId, "o", upload.objectId].join("/"), upload.bucketId, types_1.RulesetOperationMethod.CREATE, {
155
+ before: storedMetadata === null || storedMetadata === void 0 ? void 0 : storedMetadata.asRulesResource(),
156
+ after: metadata === null || metadata === void 0 ? void 0 : metadata.asRulesResource(),
157
+ }, upload.authorization);
160
158
  if (!authorized) {
161
159
  this._persistence.deleteFile(upload.path);
162
160
  throw new errors_1.ForbiddenError();
163
161
  }
164
162
  this._persistence.deleteFile(filePath, true);
165
163
  this._persistence.renameFile(upload.path, filePath);
166
- this._files.set(filePath, new StoredFile(metadata, this._persistence.getDiskPath(filePath)));
164
+ this._files.set(filePath, new StoredFile(metadata));
167
165
  this._cloudFunctions.dispatch("finalize", new metadata_1.CloudStorageObjectMetadata(metadata));
168
166
  return metadata;
169
167
  }
@@ -202,7 +200,7 @@ class StorageLayer {
202
200
  cacheControl: newMetadata.cacheControl,
203
201
  customMetadata: newMetadata.metadata,
204
202
  }, this._cloudFunctions, sourceBytes, incomingMetadata);
205
- const file = new StoredFile(copiedFileMetadata, this._persistence.getDiskPath(destinationFilePath));
203
+ const file = new StoredFile(copiedFileMetadata);
206
204
  this._files.set(destinationFilePath, file);
207
205
  this._cloudFunctions.dispatch("finalize", new metadata_1.CloudStorageObjectMetadata(file.metadata));
208
206
  return file.metadata;
@@ -210,7 +208,7 @@ class StorageLayer {
210
208
  async listObjects(request) {
211
209
  var _a;
212
210
  const { bucketId, prefix, delimiter, pageToken, authorization } = request;
213
- const authorized = await this._rulesValidator.validate(["b", bucketId, "o", prefix].join("/"), bucketId, types_1.RulesetOperationMethod.LIST, {}, authorization);
211
+ const authorized = await this._rulesValidator.validate(["b", bucketId, "o", prefix.replace(TRAILING_SLASHES_PATTERN, "")].join("/"), bucketId, types_1.RulesetOperationMethod.LIST, {}, authorization, delimiter);
214
212
  if (!authorized) {
215
213
  throw new errors_1.ForbiddenError();
216
214
  }
@@ -306,13 +304,14 @@ class StorageLayer {
306
304
  await fse.writeFile(bucketsFilePath, JSON.stringify(bucketsList, undefined, 2));
307
305
  const blobsDirPath = path.join(storageExportPath, "blobs");
308
306
  await fse.ensureDir(blobsDirPath);
309
- await fse.copy(this.dirPath, blobsDirPath, { recursive: true });
310
307
  const metadataDirPath = path.join(storageExportPath, "metadata");
311
308
  await fse.ensureDir(metadataDirPath);
312
309
  try {
313
310
  for (var _b = __asyncValues(this._files.entries()), _c; _c = await _b.next(), !_c.done;) {
314
- const [p, file] = _c.value;
315
- const metadataExportPath = path.join(metadataDirPath, encodeURIComponent(p)) + ".json";
311
+ const [, file] = _c.value;
312
+ const diskFileName = this._persistence.getDiskFileName(this.path(file.metadata.bucket, file.metadata.name));
313
+ await fse.copy(path.join(this.dirPath, diskFileName), path.join(blobsDirPath, diskFileName));
314
+ const metadataExportPath = path.join(metadataDirPath, encodeURIComponent(diskFileName)) + ".json";
316
315
  await fse.writeFile(metadataExportPath, metadata_1.StoredFileMetadata.toJSON(file.metadata));
317
316
  }
318
317
  }
@@ -333,6 +332,10 @@ class StorageLayer {
333
332
  }
334
333
  const metadataDir = path.join(storageExportPath, "metadata");
335
334
  const blobsDir = path.join(storageExportPath, "blobs");
335
+ if (!(0, fs_1.existsSync)(metadataDir) || !(0, fs_1.existsSync)(blobsDir)) {
336
+ logger_1.logger.warn(`Could not find metadata directory at "${metadataDir}" and/or blobs directory at "${blobsDir}".`);
337
+ return;
338
+ }
336
339
  const metadataList = this.walkDirSync(metadataDir);
337
340
  const dotJson = ".json";
338
341
  for (const f of metadataList) {
@@ -348,15 +351,14 @@ class StorageLayer {
348
351
  logger_1.logger.warn(`Could not find file "${blobPath}" in storage export.`);
349
352
  continue;
350
353
  }
351
- let decodedBlobPath = decodeURIComponent(blobPath);
352
- const decodedBlobPathSep = getPathSep(decodedBlobPath);
353
- if (decodedBlobPathSep !== path.sep) {
354
- decodedBlobPath = decodedBlobPath.split(decodedBlobPathSep).join(path.sep);
354
+ let fileName = metadata.name;
355
+ const objectNameSep = getPathSep(fileName);
356
+ if (fileName !== path.sep) {
357
+ fileName = fileName.split(objectNameSep).join(path.sep);
355
358
  }
356
- const blobDiskPath = this._persistence.getDiskPath(decodedBlobPath);
357
- const file = new StoredFile(metadata, blobDiskPath);
358
- this._files.set(decodedBlobPath, file);
359
- fse.copyFileSync(blobAbsPath, blobDiskPath);
359
+ const filepath = this.path(metadata.bucket, fileName);
360
+ this._persistence.copyFromExternalPath(blobAbsPath, filepath);
361
+ this._files.set(filepath, new StoredFile(metadata));
360
362
  }
361
363
  }
362
364
  *walkDirSync(dir) {
@@ -374,6 +376,6 @@ class StorageLayer {
374
376
  }
375
377
  exports.StorageLayer = StorageLayer;
376
378
  function getPathSep(decodedPath) {
377
- const firstSepIndex = decodedPath.search(/[^a-z0-9-_.]/g);
379
+ const firstSepIndex = decodedPath.search(/[\/|\\\\]/g);
378
380
  return decodedPath[firstSepIndex];
379
381
  }