Repository: firebase/firebase-tools
Pull request #1601 (2019-08-15 18:04:17)

Renames all users facing bits 


Patch:
diff --git a/src/api.js b/src/api.js
index 2fb2ac3d1..f109d044d 100644
--- a/src/api.js
+++ b/src/api.js
@@ -108,7 +108,7 @@ var api = {
   ),
   firebaseApiOrigin: utils.envOverride("FIREBASE_API_URL", "https://firebase.googleapis.com"),
   firebaseModsRegistryOrigin: utils.envOverride(
-    "FIREBASE_MODS_REGISTRY_ORIGIN",
+    "FIREBASE_EXT_REGISTRY_ORIGIN",
     "https://mods-registry.firebaseapp.com"
   ),
   firedataOrigin: utils.envOverride("FIREBASE_FIREDATA_URL", "https://mobilesdk-pa.googleapis.com"),
@@ -128,7 +128,7 @@ var api = {
   ),
   hostingOrigin: utils.envOverride("FIREBASE_HOSTING_URL", "https://firebaseapp.com"),
   iamOrigin: utils.envOverride("FIREBASE_IAM_URL", "https://iam.googleapis.com"),
-  modsOrigin: utils.envOverride("FIREBASE_MODS_URL", "https://firebasemods.googleapis.com"),
+  modsOrigin: utils.envOverride("FIREBASE_EXT_URL", "https://firebasemods.googleapis.com"),
   realtimeOrigin: utils.envOverride("FIREBASE_REALTIME_URL", "https://firebaseio.com"),
   resourceManagerOrigin: utils.envOverride(
     "FIREBASE_RESOURCEMANAGER_URL",
diff --git a/src/commands/mods-configure.ts b/src/commands/ext-configure.ts
similarity index 82%
rename from src/commands/mods-configure.ts
rename to src/commands/ext-configure.ts
index 6ce6a739e..cbbcffe14 100644
--- a/src/commands/mods-configure.ts
+++ b/src/commands/ext-configure.ts
@@ -7,9 +7,9 @@ import TerminalRenderer = require("marked-terminal");
 import * as Command from "../command";
 import { FirebaseError } from "../error";
 import * as getProjectId from "../getProjectId";
-import * as modsApi from "../mods/modsApi";
-import { logPrefix } from "../mods/modsHelper";
-import * as paramHelper from "../mods/paramHelper";
+import * as modsApi from "../extensions/modsApi";
+import { logPrefix } from "../extensions/modsHelper";
+import * as paramHelper from "../extensions/paramHelper";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
 import * as logger from "../logger";
@@ -21,8 +21,8 @@ marked.setOptions({
 /**
  * Command for configuring an existing mod instance
  */
-export default new Command("mods:configure <instanceId>")
-  .description("configure an existing mod instance")
+export default new Command("ext:configure <instanceId>")
+  .description("configure an existing extension instance")
   .option("--params <paramsFile>", "path of params file with .env format.")
   .before(requirePermissions, [
     // this doesn't exist yet, uncomment when it does
@@ -40,9 +40,12 @@ export default new Command("mods:configure <instanceId>")
         existingInstance = await modsApi.getInstance(projectId, instanceId);
       } catch (err) {
         if (err.status === 404) {
-          return utils.reject(`No mod instance ${instanceId} found in project ${projectId}.`, {
-            exit: 1,
-          });
+          return utils.reject(
+            `No extension instance ${instanceId} found in project ${projectId}.`,
+            {
+              exit: 1,
+            }
+          );
         }
         throw err;
       }
@@ -61,7 +64,7 @@ export default new Command("mods:configure <instanceId>")
       if (removedLocations.length) {
         logger.info(
           `Location is currently set to ${currentLocation}. This cannot be modified. ` +
-            `Please uninstall and reinstall this mod to change location.`
+            `Please uninstall and reinstall this extension to change location.`
         );
         params.LOCATION = currentLocation;
       }
diff --git a/src/commands/mods-info.ts b/src/commands/ext-info.ts
similarity index 84%
rename from src/commands/mods-info.ts
rename to src/commands/ext-info.ts
index 351bf7534..4f123831e 100644
--- a/src/commands/mods-info.ts
+++ b/src/commands/ext-info.ts
@@ -2,9 +2,9 @@ import * as clc from "cli-color";
 import * as _ from "lodash";
 
 import * as Command from "../command";
-import { resolveSource } from "../mods/resolveSource";
-import * as modsApi from "../mods/modsApi";
-import { ensureModsApiEnabled, logPrefix } from "../mods/modsHelper";
+import { resolveSource } from "../extensions/resolveSource";
+import * as modsApi from "../extensions/modsApi";
+import { ensureModsApiEnabled, logPrefix } from "../extensions/modsHelper";
 import * as logger from "../logger";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
@@ -14,8 +14,10 @@ import TerminalRenderer = require("marked-terminal");
 
 const FUNCTION_TYPE_REGEX = /firebasemods\..+\.function/;
 
-export default new Command("mods:info <modName>")
-  .description("display information about a mod by name (modName@x.y.z for a specific version)")
+export default new Command("ext:info <extensionName>")
+  .description(
+    "display information about an extension by name (extensionName@x.y.z for a specific version)"
+  )
   .option("--markdown", "output info in Markdown suitable for constructing a README file")
   .before(requirePermissions, [
     // this doesn't exist yet, uncomment when it does
@@ -81,7 +83,7 @@ export default new Command("mods:info <modName>")
     }
     if (spec.roles) {
       lines.push("", "**Access Required**:");
-      lines.push("", "This mod will operate with the following project IAM roles:");
+      lines.push("", "This extension will operate with the following project IAM roles:");
       _.forEach(spec.roles, (role) => {
         lines.push(`* ${role.role}` + (role.reason ? ` (Reason: ${role.reason})` : ""));
       });
@@ -97,8 +99,8 @@ export default new Command("mods:info <modName>")
       logger.info(marked(lines.join("\n")));
       utils.logLabeledBullet(
         logPrefix,
-        `to install this mod, type ` +
-          clc.bold(`firebase mods:install ${modName} --project=YOUR_PROJECT`)
+        `to install this extension, type ` +
+          clc.bold(`firebase ext:install ${modName} --project=YOUR_PROJECT`)
       );
     }
   });
diff --git a/src/commands/mods-install.ts b/src/commands/ext-install.ts
similarity index 77%
rename from src/commands/mods-install.ts
rename to src/commands/ext-install.ts
index 0dcf58879..a4431636f 100644
--- a/src/commands/mods-install.ts
+++ b/src/commands/ext-install.ts
@@ -4,23 +4,23 @@ import * as marked from "marked";
 import * as ora from "ora";
 import TerminalRenderer = require("marked-terminal");
 
-import { populatePostinstall } from "../mods/populatePostinstall";
-import * as askUserForConsent from "../mods/askUserForConsent";
-import * as checkProjectBilling from "../mods/checkProjectBilling";
+import { populatePostinstall } from "../extensions/populatePostinstall";
+import * as askUserForConsent from "../extensions/askUserForConsent";
+import * as checkProjectBilling from "../extensions/checkProjectBilling";
 import * as Command from "../command";
 import { FirebaseError } from "../error";
-import { getRandomString } from "../mods/generateInstanceId";
+import { getRandomString } from "../extensions/generateInstanceId";
 import * as getProjectId from "../getProjectId";
-import { createServiceAccountAndSetRoles } from "../mods/rolesHelper";
-import * as modsApi from "../mods/modsApi";
-import { resolveSource } from "../mods/resolveSource";
-import * as paramHelper from "../mods/paramHelper";
+import { createServiceAccountAndSetRoles } from "../extensions/rolesHelper";
+import * as modsApi from "../extensions/modsApi";
+import { resolveSource } from "../extensions/resolveSource";
+import * as paramHelper from "../extensions/paramHelper";
 import {
   ensureModsApiEnabled,
   getValidInstanceId,
   logPrefix,
   promptForValidInstanceId,
-} from "../mods/modsHelper";
+} from "../extensions/modsHelper";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
 import * as logger from "../logger";
@@ -38,7 +38,9 @@ interface InstallModOptions {
 async function installMod(options: InstallModOptions): Promise<void> {
   const { projectId, source, paramFilePath } = options;
   const spec = source.spec;
-  const spinner = ora.default("Installing your mod instance. This usually takes 3 to 5 minutes...");
+  const spinner = ora.default(
+    "Installing your extension instance. This usually takes 3 to 5 minutes..."
+  );
   try {
     await checkProjectBilling(projectId, spec.displayName || spec.name, spec.billingRequired);
     const roles = spec.roles ? spec.roles.map((role: modsApi.Role) => role.role) : [];
@@ -94,15 +96,17 @@ async function installMod(options: InstallModOptions): Promise<void> {
     if (err instanceof FirebaseError) {
       throw err;
     }
-    throw new FirebaseError(`Error occurred installing mod: ${err.message}`, { original: err });
+    throw new FirebaseError(`Error occurred installing extension: ${err.message}`, {
+      original: err,
+    });
   }
 }
 
 /**
  * Command for installing a mod
  */
-export default new Command("mods:install <modName>")
-  .description("install a mod, given <modName> or <modName@versionNumber>")
+export default new Command("ext:install <extensionName>")
+  .description("install an extension, given <extensionName> or <extensionName@versionNumber>")
   .option("--params <paramsFile>", "name of params variables file with .env format.")
   .before(requirePermissions, [
     // this doesn't exist yet, uncomment when it does
@@ -122,7 +126,7 @@ export default new Command("mods:install <modName>")
       });
     } catch (err) {
       if (!(err instanceof FirebaseError)) {
-        throw new FirebaseError(`Error occurred installing the mod: ${err.message}`, {
+        throw new FirebaseError(`Error occurred installing the extension: ${err.message}`, {
           original: err,
         });
       }
diff --git a/src/commands/mods-list.ts b/src/commands/ext-list.ts
similarity index 63%
rename from src/commands/mods-list.ts
rename to src/commands/ext-list.ts
index bcc4e2a5c..ae0090a23 100644
--- a/src/commands/mods-list.ts
+++ b/src/commands/ext-list.ts
@@ -1,11 +1,11 @@
 import * as Command from "../command";
 import * as getProjectId from "../getProjectId";
-import { listMods } from "../mods/listMods";
-import { ensureModsApiEnabled } from "../mods/modsHelper";
+import { listMods } from "../extensions/listMods";
+import { ensureModsApiEnabled } from "../extensions/modsHelper";
 import * as requirePermissions from "../requirePermissions";
 
-module.exports = new Command("mods:list")
-  .description("list all the mods that are installed in your Firebase project")
+module.exports = new Command("ext:list")
+  .description("list all the extensions that are installed in your Firebase project")
   .before(requirePermissions, [
     // TODO: this doesn't exist yet, uncomment when it does
     // "firebasemods.instances.list"
diff --git a/src/commands/mods-uninstall.ts b/src/commands/ext-uninstall.ts
similarity index 84%
rename from src/commands/mods-uninstall.ts
rename to src/commands/ext-uninstall.ts
index f122c7444..f5a4127aa 100644
--- a/src/commands/mods-uninstall.ts
+++ b/src/commands/ext-uninstall.ts
@@ -5,14 +5,14 @@ import * as Command from "../command";
 import { FirebaseError } from "../error";
 import * as getProjectId from "../getProjectId";
 import { iam } from "../gcp";
-import * as modsApi from "../mods/modsApi";
-import { ensureModsApiEnabled, logPrefix } from "../mods/modsHelper";
+import * as modsApi from "../extensions/modsApi";
+import { ensureModsApiEnabled, logPrefix } from "../extensions/modsHelper";
 import { promptOnce } from "../prompt";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
 
-export default new Command("mods:uninstall <modInstanceId>")
-  .description("uninstall a mod that is installed in your Firebase project by instance ID")
+export default new Command("ext:uninstall <extensionInstanceId>")
+  .description("uninstall an extension that is installed in your Firebase project by instance ID")
   .option("-f, --force", "No confirmation. Otherwise, a confirmation prompt will appear.")
   .before(requirePermissions, [
     // TODO: This doesn't exist yet. Uncomment when it does.
@@ -26,7 +26,7 @@ export default new Command("mods:uninstall <modInstanceId>")
       instance = await modsApi.getInstance(projectId, instanceId);
     } catch (err) {
       if (err.status === 404) {
-        return utils.reject(`No mod instance ${instanceId} in project ${projectId}.`, {
+        return utils.reject(`No extension instance ${instanceId} in project ${projectId}.`, {
           exit: 1,
         });
       }
@@ -40,7 +40,7 @@ export default new Command("mods:uninstall <modInstanceId>")
             .map((resource: modsApi.Resource) => `- ${resource.type}: ${resource.name} \n`)
             .join("")
         : "";
-      const modDeletionMessage = `You are about to uninstall mod ${clc.bold(
+      const modDeletionMessage = `You are about to uninstall extension ${clc.bold(
         instanceId
       )} from project ${clc.bold(projectId)}.\n${resourcesMessage}Are you sure?`;
       const confirmedModDeletion = await promptOnce({
@@ -58,7 +58,7 @@ export default new Command("mods:uninstall <modInstanceId>")
             .map((role: modsApi.Role) => `- ${role.role} \n`)
             .join("")
         : ". \n";
-      const serviceAccountDeletionMessage = `This mod used service account ${clc.bold(
+      const serviceAccountDeletionMessage = `This extension used service account ${clc.bold(
         instance.serviceAccountEmail
       )} ${rolesMessage}Do you want to delete this service account?`;
       confirmedServiceAccountDeletion = await promptOnce({
@@ -104,7 +104,7 @@ export default new Command("mods:uninstall <modInstanceId>")
       if (err instanceof FirebaseError) {
         throw err;
       }
-      return utils.reject(`Error occurred uninstalling mod ${instanceId}`, { original: err });
+      return utils.reject(`Error occurred uninstalling extension ${instanceId}`, { original: err });
     }
     utils.logLabeledSuccess(logPrefix, `uninstalled ${instanceId}`);
   });
diff --git a/src/commands/mods-update.ts b/src/commands/ext-update.ts
similarity index 80%
rename from src/commands/mods-update.ts
rename to src/commands/ext-update.ts
index 5601102a8..2cb87871e 100644
--- a/src/commands/mods-update.ts
+++ b/src/commands/ext-update.ts
@@ -7,11 +7,11 @@ import TerminalRenderer = require("marked-terminal");
 import * as Command from "../command";
 import { FirebaseError } from "../error";
 import * as getProjectId from "../getProjectId";
-import { resolveSource } from "../mods/resolveSource";
-import * as modsApi from "../mods/modsApi";
-import { ensureModsApiEnabled, logPrefix } from "../mods/modsHelper";
-import * as paramHelper from "../mods/paramHelper";
-import { displayChanges, update } from "../mods/updateHelper";
+import { resolveSource } from "../extensions/resolveSource";
+import * as modsApi from "../extensions/modsApi";
+import { ensureModsApiEnabled, logPrefix } from "../extensions/modsHelper";
+import * as paramHelper from "../extensions/paramHelper";
+import { displayChanges, update } from "../extensions/updateHelper";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
 
@@ -22,8 +22,8 @@ marked.setOptions({
 /**
  * Command for updating an existing mod instance
  */
-export default new Command("mods:update <instanceId>")
-  .description("update an existing mod instance to the latest version")
+export default new Command("ext:update <instanceId>")
+  .description("update an existing extension instance to the latest version")
   .before(requirePermissions, [
     // this doesn't exist yet, uncomment when it does
     // "firebasemods.instances.update"
@@ -41,9 +41,12 @@ export default new Command("mods:update <instanceId>")
         existingInstance = await modsApi.getInstance(projectId, instanceId);
       } catch (err) {
         if (err.status === 404) {
-          return utils.reject(`No mod instance ${instanceId} found in project ${projectId}.`, {
-            exit: 1,
-          });
+          return utils.reject(
+            `No extension instance ${instanceId} found in project ${projectId}.`,
+            {
+              exit: 1,
+            }
+          );
         }
         throw err;
       }
diff --git a/src/commands/mods.ts b/src/commands/ext.ts
similarity index 71%
rename from src/commands/mods.ts
rename to src/commands/ext.ts
index 1d5ba2708..388eb9c80 100644
--- a/src/commands/mods.ts
+++ b/src/commands/ext.ts
@@ -3,24 +3,26 @@ import * as clc from "cli-color";
 
 import * as Command from "../command";
 import * as getProjectId from "../getProjectId";
-import * as modsHelper from "../mods/modsHelper";
-import { listMods } from "../mods/listMods";
+import * as modsHelper from "../extensions/modsHelper";
+import { listMods } from "../extensions/listMods";
 import * as requirePermissions from "../requirePermissions";
 import * as utils from "../utils";
 import * as logger from "../logger";
 
-module.exports = new Command("mods")
-  .description("display information on how to use mods commands and mods installed to your project")
+module.exports = new Command("ext")
+  .description(
+    "display information on how to use ext commands and extensions installed to your project"
+  )
   .before(requirePermissions, ["deploymentmanager.deployments.get"])
   .action((options: any) => {
     const projectId = getProjectId(options);
     const commands = [
-      "mods-configure",
-      "mods-info",
-      "mods-install",
-      "mods-list",
-      "mods-uninstall",
-      "mods-update",
+      "ext-configure",
+      "ext-info",
+      "ext-install",
+      "ext-list",
+      "ext-uninstall",
+      "ext-update",
     ];
 
     _.forEach(commands, (command) => {
diff --git a/src/commands/index.js b/src/commands/index.js
index fa63b814f..2ea38291a 100644
--- a/src/commands/index.js
+++ b/src/commands/index.js
@@ -79,14 +79,14 @@ module.exports = function(client) {
   client.tools.migrate = loadCommand("tools-migrate");
   client.use = loadCommand("use");
 
-  if (previews.mods) {
-    client.mods = loadCommand("mods");
-    client.mods.configure = loadCommand("mods-configure");
-    client.mods.info = loadCommand("mods-info");
-    client.mods.install = loadCommand("mods-install");
-    client.mods.list = loadCommand("mods-list");
-    client.mods.uninstall = loadCommand("mods-uninstall");
-    client.mods.update = loadCommand("mods-update");
+  if (previews.mods || previews.ext) {
+    client.ext = loadCommand("ext");
+    client.ext.configure = loadCommand("ext-configure");
+    client.ext.info = loadCommand("ext-info");
+    client.ext.install = loadCommand("ext-install");
+    client.ext.list = loadCommand("ext-list");
+    client.ext.uninstall = loadCommand("ext-uninstall");
+    client.ext.update = loadCommand("ext-update");
   }
   return client;
 };
diff --git a/src/mods/askUserForConsent.js b/src/extensions/askUserForConsent.js
similarity index 97%
rename from src/mods/askUserForConsent.js
rename to src/extensions/askUserForConsent.js
index fe492fc96..9bfbf09bc 100644
--- a/src/mods/askUserForConsent.js
+++ b/src/extensions/askUserForConsent.js
@@ -50,7 +50,7 @@ function _prompt(modName, projectId, roles) {
 
   return _formatDescription(modName, projectId, roles)
     .then(function(message) {
-      utils.logLabeledBullet("mods", message);
+      utils.logLabeledBullet("extensions", message);
       const question = {
         name: "consent",
         type: "confirm",
diff --git a/src/mods/askUserForParam.ts b/src/extensions/askUserForParam.ts
similarity index 97%
rename from src/mods/askUserForParam.ts
rename to src/extensions/askUserForParam.ts
index 7a2bc952d..00399d2d4 100644
--- a/src/mods/askUserForParam.ts
+++ b/src/extensions/askUserForParam.ts
@@ -2,7 +2,7 @@ import * as _ from "lodash";
 import * as clc from "cli-color";
 import * as marked from "marked";
 
-import { Param, ParamOption, ParamType } from "../mods/modsApi";
+import { Param, ParamOption, ParamType } from "./modsApi";
 import { FirebaseError } from "../error";
 import { logPrefix, substituteParams } from "./modsHelper";
 import { convertModOptionToLabeledList, modOptionToValue, onceWithJoin } from "./utils";
@@ -142,11 +142,11 @@ export async function ask(
   firebaseProjectParams: { [key: string]: string }
 ): Promise<{ [key: string]: string }> {
   if (_.isEmpty(paramSpecs)) {
-    logger.debug("No params were specified for this mod.");
+    logger.debug("No params were specified for this extension.");
     return {};
   }
 
-  utils.logLabeledBullet(logPrefix, "answer the questions below to configure your mod:");
+  utils.logLabeledBullet(logPrefix, "answer the questions below to configure your extension:");
   const substituted = substituteParams(paramSpecs, firebaseProjectParams) as Param[];
   const result: any = {};
   const promises = _.map(substituted, (paramSpec: Param) => {
diff --git a/src/mods/checkProjectBilling.js b/src/extensions/checkProjectBilling.js
similarity index 97%
rename from src/mods/checkProjectBilling.js
rename to src/extensions/checkProjectBilling.js
index 5380a3ced..32220e363 100644
--- a/src/mods/checkProjectBilling.js
+++ b/src/extensions/checkProjectBilling.js
@@ -49,7 +49,8 @@ function _openBillingAccount(projectId, url, open) {
     .promptOnce({
       name: "continue",
       type: "confirm",
-      message: "Press enter when finished upgrading your project to continue setting up your mod.",
+      message:
+        "Press enter when finished upgrading your project to continue setting up your extension.",
       default: true,
     })
     .then(() => {
diff --git a/src/mods/generateInstanceId.ts b/src/extensions/generateInstanceId.ts
similarity index 100%
rename from src/mods/generateInstanceId.ts
rename to src/extensions/generateInstanceId.ts
diff --git a/src/mods/listMods.ts b/src/extensions/listMods.ts
similarity index 79%
rename from src/mods/listMods.ts
rename to src/extensions/listMods.ts
index dac39cb9e..5938118fc 100644
--- a/src/mods/listMods.ts
+++ b/src/extensions/listMods.ts
@@ -12,13 +12,13 @@ export async function listMods(projectId: string): Promise<{ instances: ModInsta
   if (instances.length < 1) {
     utils.logLabeledBullet(
       logPrefix,
-      `there are no mods installed for project ${clc.bold(projectId)}.`
+      `there are no extensions installed on project ${clc.bold(projectId)}.`
     );
     return { instances: [] };
   }
 
   const table = new Table({
-    head: ["Mod Instance ID", "State", "Mod Version", "Create Time", "Update Time"],
+    head: ["Extension Instance ID", "State", "Extension Version", "Create Time", "Update Time"],
     style: { head: ["yellow"] },
   });
 
@@ -34,7 +34,7 @@ export async function listMods(projectId: string): Promise<{ instances: ModInsta
     ]);
   });
 
-  utils.logLabeledBullet(logPrefix, `list of mods installed in ${clc.bold(projectId)}:`);
+  utils.logLabeledBullet(logPrefix, `list of extensions installed in ${clc.bold(projectId)}:`);
   logger.info(table.toString());
   return { instances: sorted };
 }
diff --git a/src/mods/modsApi.ts b/src/extensions/modsApi.ts
similarity index 100%
rename from src/mods/modsApi.ts
rename to src/extensions/modsApi.ts
diff --git a/src/mods/modsHelper.ts b/src/extensions/modsHelper.ts
similarity index 95%
rename from src/mods/modsHelper.ts
rename to src/extensions/modsHelper.ts
index de9ed5b94..7f6000cba 100644
--- a/src/mods/modsHelper.ts
+++ b/src/extensions/modsHelper.ts
@@ -5,11 +5,11 @@ import { FirebaseError } from "../error";
 import { checkResponse } from "./askUserForParam";
 import { ensure } from "../ensureApiEnabled";
 import * as getProjectId from "../getProjectId";
-import { generateInstanceId } from "../mods/generateInstanceId";
+import { generateInstanceId } from "./generateInstanceId";
 import { promptOnce } from "../prompt";
 import * as logger from "../logger";
 
-export const logPrefix = "mods";
+export const logPrefix = "extensions";
 
 /**
  * Turns database URLs (e.g. https://my-db.firebaseio.com) into database instance names
@@ -109,7 +109,7 @@ export function validateCommandLineParams(envVars: any, paramSpec: any): void {
       return paramList.indexOf(key) === -1;
     });
     logger.info(
-      "Warning: The following params were specified in your env file but do not exist in the spec for this mod: " +
+      "Warning: The following params were specified in your env file but do not exist in the extension spec: " +
         `${misnamedParams.join(", ")}.`
     );
   }
@@ -135,7 +135,7 @@ export function validateCommandLineParams(envVars: any, paramSpec: any): void {
 export async function getValidInstanceId(projectId: string, modName: string): Promise<string> {
   let instanceId = await generateInstanceId(projectId, modName);
   if (instanceId !== modName) {
-    logger.info(`A mod named ${modName} already exists in project ${projectId}.`);
+    logger.info(`An extension named ${modName} already exists in project ${projectId}.`);
     instanceId = await promptForValidInstanceId(instanceId);
   }
   return instanceId;
@@ -169,6 +169,6 @@ export async function ensureModsApiEnabled(options: any): Promise<void> {
   const projectId = getProjectId(options);
   await Promise.all([
     ensure(projectId, "deploymentmanager.googleapis.com", "deploymentManager", true),
-    ensure(projectId, "firebasemods.googleapis.com", "mods", options.markdown),
+    ensure(projectId, "firebasemods.googleapis.com", "extensions", options.markdown),
   ]);
 }
diff --git a/src/mods/paramHelper.ts b/src/extensions/paramHelper.ts
similarity index 97%
rename from src/mods/paramHelper.ts
rename to src/extensions/paramHelper.ts
index 5e68b764f..a071ec760 100644
--- a/src/mods/paramHelper.ts
+++ b/src/extensions/paramHelper.ts
@@ -11,8 +11,8 @@ import {
   getFirebaseProjectParams,
   populateDefaultParams,
   validateCommandLineParams,
-} from "../mods/modsHelper";
-import * as askUserForParam from "../mods/askUserForParam";
+} from "./modsHelper";
+import * as askUserForParam from "./askUserForParam";
 import * as track from "../track";
 
 /**
diff --git a/src/mods/populatePostinstall.ts b/src/extensions/populatePostinstall.ts
similarity index 100%
rename from src/mods/populatePostinstall.ts
rename to src/extensions/populatePostinstall.ts
diff --git a/src/mods/resolveSource.ts b/src/extensions/resolveSource.ts
similarity index 89%
rename from src/mods/resolveSource.ts
rename to src/extensions/resolveSource.ts
index f39e5886f..c2659a63a 100644
--- a/src/mods/resolveSource.ts
+++ b/src/extensions/resolveSource.ts
@@ -23,7 +23,7 @@ export async function resolveSource(modName: string): Promise<string> {
   const modsRegistry = await getModRegistry();
   const mod = _.get(modsRegistry, name);
   if (!mod) {
-    throw new FirebaseError(`Unable to find mod named ${clc.bold(name)}.`);
+    throw new FirebaseError(`Unable to find extension source named ${clc.bold(name)}.`);
   }
   // The version to search for when a user passes a version x.y.z or no version
   const seekVersion = version || "latest";
@@ -35,7 +35,7 @@ export async function resolveSource(modName: string): Promise<string> {
     _.get(mod, ["versions", seekVersion]) || _.get(mod, ["versions", versionFromLabel]);
   if (!source) {
     throw new FirebaseError(
-      `Could not resolve version ${clc.bold(version)} of mod ${clc.bold(name)}.`
+      `Could not resolve version ${clc.bold(version)} of extension ${clc.bold(name)}.`
     );
   }
   return source;
diff --git a/src/mods/rolesHelper.ts b/src/extensions/rolesHelper.ts
similarity index 90%
rename from src/mods/rolesHelper.ts
rename to src/extensions/rolesHelper.ts
index a274b7013..c0a80ac59 100644
--- a/src/mods/rolesHelper.ts
+++ b/src/extensions/rolesHelper.ts
@@ -77,16 +77,16 @@ export async function createServiceAccountAndSetRoles(
   try {
     serviceAccount = await iam.createServiceAccount(
       projectId,
-      `mod-${shortenedInstanceId}`,
-      `Runtime service account for Firebase Mod ${instanceId}`,
-      `Firebase Mod ${instanceId} service account`
+      `ext-${shortenedInstanceId}`,
+      `Runtime service account for Firebase Extension ${instanceId}`,
+      `Firebase Extension ${instanceId} service account`
     );
   } catch (err) {
     if (err.status === 409) {
       // if the service account already exists
       return utils.reject(
-        `A service account mod-${shortenedInstanceId} already exists in project ${projectId}. ` +
-          `Please delete it or choose a different mod instance id.`,
+        `A service account ext-${shortenedInstanceId} already exists in project ${projectId}. ` +
+          `Please delete it or choose a different extension instance id.`,
         {
           exit: 1,
           status: 409,
diff --git a/src/mods/updateHelper.ts b/src/extensions/updateHelper.ts
similarity index 95%
rename from src/mods/updateHelper.ts
rename to src/extensions/updateHelper.ts
index f5e97bd23..48839854d 100644
--- a/src/mods/updateHelper.ts
+++ b/src/extensions/updateHelper.ts
@@ -46,7 +46,7 @@ export function displayChangesNoInput(spec: modsApi.ModSpec, newSpec: modsApi.Mo
   }
 
   if (spec.billingRequired && !newSpec.billingRequired) {
-    lines.push("", "**Billing is no longer required for this mod.**");
+    lines.push("", "**Billing is no longer required for this extension.**");
   }
   logger.info(marked(lines.join("\n")));
   return lines;
@@ -126,7 +126,7 @@ export async function displayChangesRequiringConfirmation(
   if (!spec.billingRequired && newSpec.billingRequired) {
     await getConsent(
       "billingRequired",
-      "Billing is now required for the new version of this mod. Would you like to continue?"
+      "Billing is now required for the new version of this extension. Would you like to continue?"
     );
   }
 }
@@ -145,7 +145,7 @@ async function getConsent(field: string, message: string): Promise<void> {
   });
   if (!consent) {
     throw new FirebaseError(
-      `Without explicit consent for the change to ${field}, we cannot update this mod instance.`,
+      `Without explicit consent for the change to ${field}, we cannot update this extension instance.`,
       { exit: 2 }
     );
   }
@@ -165,7 +165,7 @@ export async function displayChanges(
 ): Promise<void> {
   logger.info(
     "This update contains the following changes. " +
-      "If at any point you choose not to continue, the mod will not be updated and the changes will be discarded:"
+      "If at any point you choose not to continue, the extension will not be updated and the changes will be discarded:"
   );
   displayChangesNoInput(spec, newSpec);
   await displayChangesRequiringConfirmation(spec, newSpec);
diff --git a/src/mods/utils.ts b/src/extensions/utils.ts
similarity index 100%
rename from src/mods/utils.ts
rename to src/extensions/utils.ts
diff --git a/src/previews.js b/src/previews.js
index daa95e426..45f655189 100644
--- a/src/previews.js
+++ b/src/previews.js
@@ -7,6 +7,7 @@ var previews = _.assign(
   {
     // insert previews here...
     mods: false,
+    ext: false,
   },
   configstore.get("previews")
 );


Test patch:
diff --git a/src/test/mods/askUserForConsent.spec.js b/src/test/extensions/askUserForConsent.spec.js
similarity index 95%
rename from src/test/mods/askUserForConsent.spec.js
rename to src/test/extensions/askUserForConsent.spec.js
index f91b0c2db..29972f471 100644
--- a/src/test/mods/askUserForConsent.spec.js
+++ b/src/test/extensions/askUserForConsent.spec.js
@@ -7,7 +7,7 @@ const chai = require("chai");
 chai.use(require("chai-as-promised"));
 const sinon = require("sinon");
 
-const askUserForConsent = require("../../mods/askUserForConsent");
+const askUserForConsent = require("../../extensions/askUserForConsent");
 
 const expect = chai.expect;
 
diff --git a/src/test/mods/askUserForParam.spec.ts b/src/test/extensions/askUserForParam.spec.ts
similarity index 96%
rename from src/test/mods/askUserForParam.spec.ts
rename to src/test/extensions/askUserForParam.spec.ts
index 046b943dd..0e5fce609 100644
--- a/src/test/mods/askUserForParam.spec.ts
+++ b/src/test/extensions/askUserForParam.spec.ts
@@ -1,11 +1,16 @@
 import { expect } from "chai";
 import * as sinon from "sinon";
 
-import { ask, askForParam, checkResponse, getInquirerDefault } from "../../mods/askUserForParam";
+import {
+  ask,
+  askForParam,
+  checkResponse,
+  getInquirerDefault,
+} from "../../extensions/askUserForParam";
 import * as utils from "../../utils";
 import * as prompt from "../../prompt";
-import { ParamType } from "../../mods/modsApi";
-import * as modsHelper from "../../mods/modsHelper";
+import { ParamType } from "../../extensions/modsApi";
+import * as modsHelper from "../../extensions/modsHelper";
 
 describe("askUserForParam", () => {
   const testSpec = {
diff --git a/src/test/mods/checkProjectBilling.spec.js b/src/test/extensions/checkProjectBilling.spec.js
similarity index 97%
rename from src/test/mods/checkProjectBilling.spec.js
rename to src/test/extensions/checkProjectBilling.spec.js
index 67f5e7c1f..2dfdcb37d 100644
--- a/src/test/mods/checkProjectBilling.spec.js
+++ b/src/test/extensions/checkProjectBilling.spec.js
@@ -4,7 +4,7 @@ const chai = require("chai");
 chai.use(require("chai-as-promised"));
 const sinon = require("sinon");
 
-const checkProjectBilling = require("../../mods/checkProjectBilling");
+const checkProjectBilling = require("../../extensions/checkProjectBilling");
 const prompt = require("../../prompt");
 const cloudbilling = require("../../gcp/cloudbilling");
 
diff --git a/src/test/mods/generateInstanceId.spec.ts b/src/test/extensions/generateInstanceId.spec.ts
similarity index 91%
rename from src/test/mods/generateInstanceId.spec.ts
rename to src/test/extensions/generateInstanceId.spec.ts
index 2a0b24797..cda7342c1 100644
--- a/src/test/mods/generateInstanceId.spec.ts
+++ b/src/test/extensions/generateInstanceId.spec.ts
@@ -2,8 +2,8 @@ import { expect } from "chai";
 import * as sinon from "sinon";
 
 import { FirebaseError } from "../../error";
-import { generateInstanceId } from "../../mods/generateInstanceId";
-import * as modsApi from "../../mods/modsApi";
+import { generateInstanceId } from "../../extensions/generateInstanceId";
+import * as modsApi from "../../extensions/modsApi";
 
 const TEST_NAME = "image-resizer";
 
diff --git a/src/test/mods/listMods.spec.ts b/src/test/extensions/listMods.spec.ts
similarity index 95%
rename from src/test/mods/listMods.spec.ts
rename to src/test/extensions/listMods.spec.ts
index 9718b1bfe..7241b77d3 100644
--- a/src/test/mods/listMods.spec.ts
+++ b/src/test/extensions/listMods.spec.ts
@@ -1,8 +1,8 @@
 import { expect } from "chai";
 import * as sinon from "sinon";
 
-import * as modsApi from "../../mods/modsApi";
-import { listMods } from "../../mods/listMods";
+import * as modsApi from "../../extensions/modsApi";
+import { listMods } from "../../extensions/listMods";
 
 const MOCK_INSTANCES = [
   {
diff --git a/src/test/mods/modsApi.spec.ts b/src/test/extensions/modsApi.spec.ts
similarity index 99%
rename from src/test/mods/modsApi.spec.ts
rename to src/test/extensions/modsApi.spec.ts
index 4f9a5a0fb..d1c4fe958 100644
--- a/src/test/mods/modsApi.spec.ts
+++ b/src/test/extensions/modsApi.spec.ts
@@ -4,7 +4,7 @@ import * as nock from "nock";
 import * as api from "../../api";
 import { FirebaseError } from "../../error";
 
-import * as modsApi from "../../mods/modsApi";
+import * as modsApi from "../../extensions/modsApi";
 
 const VERSION = "v1beta1";
 
diff --git a/src/test/mods/modsHelper.spec.ts b/src/test/extensions/modsHelper.spec.ts
similarity index 98%
rename from src/test/mods/modsHelper.spec.ts
rename to src/test/extensions/modsHelper.spec.ts
index 46cc1553b..67a63e4aa 100644
--- a/src/test/mods/modsHelper.spec.ts
+++ b/src/test/extensions/modsHelper.spec.ts
@@ -2,8 +2,8 @@ import { expect } from "chai";
 import * as sinon from "sinon";
 
 import { FirebaseError } from "../../error";
-import * as generateInstanceId from "../../mods/generateInstanceId";
-import * as modsHelper from "../../mods/modsHelper";
+import * as generateInstanceId from "../../extensions/generateInstanceId";
+import * as modsHelper from "../../extensions/modsHelper";
 import * as prompt from "../../prompt";
 
 describe("modsHelper", () => {
diff --git a/src/test/mods/paramHelper.spec.ts b/src/test/extensions/paramHelper.spec.ts
similarity index 97%
rename from src/test/mods/paramHelper.spec.ts
rename to src/test/extensions/paramHelper.spec.ts
index d26e2faeb..2f4dd4008 100644
--- a/src/test/mods/paramHelper.spec.ts
+++ b/src/test/extensions/paramHelper.spec.ts
@@ -6,9 +6,9 @@ import * as fs from "fs-extra";
 
 import { FirebaseError } from "../../error";
 import * as logger from "../../logger";
-import { ModInstance, ParamType } from "../../mods/modsApi";
-import * as modsHelper from "../../mods/modsHelper";
-import * as paramHelper from "../../mods/paramHelper";
+import { ModInstance, ParamType } from "../../extensions/modsApi";
+import * as modsHelper from "../../extensions/modsHelper";
+import * as paramHelper from "../../extensions/paramHelper";
 import * as prompt from "../../prompt";
 
 const PROJECT_ID = "test-proj";
@@ -129,7 +129,7 @@ describe("paramHelper", () => {
 
       expect(loggerSpy).to.have.been.calledWith(
         "Warning: The following params were specified in your env file but" +
-          " do not exist in the spec for this mod: A_THIRD_PARAMETER, A_FOURTH_PARAMETER."
+          " do not exist in the extension spec: A_THIRD_PARAMETER, A_FOURTH_PARAMETER."
       );
     });
 
diff --git a/src/test/mods/populatePostinstall.spec.ts b/src/test/extensions/populatePostinstall.spec.ts
similarity index 94%
rename from src/test/mods/populatePostinstall.spec.ts
rename to src/test/extensions/populatePostinstall.spec.ts
index 8dae99121..f28651b91 100644
--- a/src/test/mods/populatePostinstall.spec.ts
+++ b/src/test/extensions/populatePostinstall.spec.ts
@@ -1,6 +1,6 @@
 import { expect } from "chai";
 
-import { populatePostinstall } from "../../mods/populatePostinstall";
+import { populatePostinstall } from "../../extensions/populatePostinstall";
 
 describe("populatePostinstallInstructions", () => {
   const instructions = "These are instructions, param foo is ${param:FOO}";
diff --git a/src/test/mods/rolesHelper.spec.ts b/src/test/extensions/rolesHelper.spec.ts
similarity index 94%
rename from src/test/mods/rolesHelper.spec.ts
rename to src/test/extensions/rolesHelper.spec.ts
index 781df6cd5..f30672f78 100644
--- a/src/test/mods/rolesHelper.spec.ts
+++ b/src/test/extensions/rolesHelper.spec.ts
@@ -4,7 +4,7 @@ import * as nock from "nock";
 import * as api from "../../api";
 import { FirebaseError } from "../../error";
 
-import * as rolesHelper from "../../mods/rolesHelper";
+import * as rolesHelper from "../../extensions/rolesHelper";
 
 const PROJECT_ID = "test-proj";
 const INSTANCE_ID = "test-instance";
@@ -20,7 +20,7 @@ describe("createServiceAccountAndSetRoles", () => {
     nock.cleanAll();
   });
 
-  it("should create a service account named mod-{instanceId} and set roles on it", async () => {
+  it("should create a service account named ext-{instanceId} and set roles on it", async () => {
     nock(api.iamOrigin)
       .post(`/${IAM_VERSION}/projects/${PROJECT_ID}/serviceAccounts`)
       .reply(200, { email: TEST_SERVICE_ACCOUNT_EMAIL });
@@ -61,8 +61,8 @@ describe("createServiceAccountAndSetRoles", () => {
       rolesHelper.createServiceAccountAndSetRoles(PROJECT_ID, TEST_ROLES, INSTANCE_ID)
     ).to.be.rejectedWith(
       FirebaseError,
-      "A service account mod-test-instance already exists in project test-proj. " +
-        "Please delete it or choose a different mod instance id."
+      "A service account ext-test-instance already exists in project test-proj. " +
+        "Please delete it or choose a different extension instance id."
     );
   });
 
diff --git a/src/test/mods/updateHelper.spec.ts b/src/test/extensions/updateHelper.spec.ts
similarity index 96%
rename from src/test/mods/updateHelper.spec.ts
rename to src/test/extensions/updateHelper.spec.ts
index 64bc6965e..8dd0397de 100644
--- a/src/test/mods/updateHelper.spec.ts
+++ b/src/test/extensions/updateHelper.spec.ts
@@ -3,7 +3,7 @@ import { expect } from "chai";
 import * as sinon from "sinon";
 
 import { FirebaseError } from "../../error";
-import * as updateHelper from "../../mods/updateHelper";
+import * as updateHelper from "../../extensions/updateHelper";
 import * as prompt from "../../prompt";
 
 const SPEC = {
@@ -73,7 +73,7 @@ describe("updateHelper", () => {
 
       const loggedLines = updateHelper.displayChangesNoInput(SPEC, newSpec);
 
-      const expected = ["", "**Billing is no longer required for this mod.**"];
+      const expected = ["", "**Billing is no longer required for this extension.**"];
       expect(loggedLines).to.eql(expected);
     });
 
@@ -159,7 +159,7 @@ describe("updateHelper", () => {
 
       expect(promptStub.callCount).to.equal(1);
       expect(promptStub.firstCall.args[0].message).to.contain(
-        "Billing is now required for the new version of this mod. Would you like to continue?"
+        "Billing is now required for the new version of this extension. Would you like to continue?"
       );
     });
 
@@ -172,7 +172,7 @@ describe("updateHelper", () => {
 
       expect(updateHelper.displayChangesRequiringConfirmation(SPEC, newSpec)).to.be.rejectedWith(
         FirebaseError,
-        "Without explicit consent for the change to license, we cannot update this mod instance."
+        "Without explicit consent for the change to license, we cannot update this extension instance."
       );
 
       expect(promptStub.callCount).to.equal(1);
@@ -185,7 +185,7 @@ describe("updateHelper", () => {
 
       expect(updateHelper.displayChangesRequiringConfirmation(SPEC, newSpec)).to.be.rejectedWith(
         FirebaseError,
-        "Without explicit consent for the change to license, we cannot update this mod instance."
+        "Without explicit consent for the change to license, we cannot update this extension instance."
       );
     });