Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions src/commands/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,5 @@ module.exports = new Command("init [feature]")
}
logger.info();
utils.logSuccess("Firebase initialization complete!");

if (setup.createProject) {
logger.info();
logger.info(
clc.bold.cyan("Project creation is only available from the Firebase Console")
);
logger.info(
"Please visit",
clc.underline("https://console.firebase.google.com"),
"to create a new project, then run",
clc.bold("firebase use --add")
);
}
});
});
57 changes: 4 additions & 53 deletions src/commands/projects-create.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,12 @@
import * as clc from "cli-color";
import * as ora from "ora";

import * as Command from "../command";
import * as FirebaseError from "../error";
import {
addFirebaseToCloudProject,
createCloudProject,
ProjectParentResource,
createFirebaseProjectAndLog,
ProjectParentResourceType,
PROJECTS_CREATE_QUESTIONS,
} from "../management/projects";
import { prompt } from "../prompt";
import * as requireAuth from "../requireAuth";
import * as logger from "../logger";

async function createFirebaseProject(
projectId: string,
options: { displayName?: string; parentResource?: ProjectParentResource }
): Promise<any> {
let spinner = ora("Creating Google Cloud Platform project").start();
try {
await createCloudProject(projectId, options);
spinner.succeed();

spinner = ora("Adding Firebase to Google Cloud project").start();
const projectInfo = await addFirebaseToCloudProject(projectId);
spinner.succeed();

logger.info("");
logger.info("🎉🎉🎉 Your Firebase project is ready! 🎉🎉🎉");
logger.info("");
logger.info("Project information:");
logger.info(` - Project ID: ${clc.bold(projectInfo.projectId)}`);
logger.info(` - Project Name: ${clc.bold(projectInfo.displayName)}`);
logger.info("");
logger.info("Firebase console is available at");
logger.info(`https://console.firebase.google.com/project/${clc.bold(projectId)}/overview`);
return projectInfo;
} catch (err) {
spinner.fail();
throw err;
}
}

module.exports = new Command("projects:create [projectId]")
.description("create a new firebase project")
Expand All @@ -64,22 +30,7 @@ module.exports = new Command("projects:create [projectId]")
);
}
if (!options.nonInteractive) {
await prompt(options, [
{
type: "input",
name: "projectId",
default: "",
message:
"Please specify a unique project id " +
`(${clc.yellow("warning")}: cannot be modified afterward) [6-30 characters]:\n`,
},
{
type: "input",
name: "displayName",
default: "",
message: "What would you like to call your project? (defaults to your project ID)",
},
]);
await prompt(options, PROJECTS_CREATE_QUESTIONS);
}
if (!options.projectId) {
throw new FirebaseError("Project ID cannot be empty");
Expand All @@ -92,7 +43,7 @@ module.exports = new Command("projects:create [projectId]")
parentResource = { type: ProjectParentResourceType.FOLDER, id: options.folder };
}

return createFirebaseProject(options.projectId, {
return createFirebaseProjectAndLog(options.projectId, {
displayName: options.displayName,
parentResource,
});
Expand Down
50 changes: 37 additions & 13 deletions src/init/features/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import * as _ from "lodash";
import * as Config from "../../config";
import * as FirebaseError from "../../error";
import {
createFirebaseProjectAndLog,
FirebaseProjectMetadata,
getFirebaseProject,
getProjectPage,
PROJECTS_CREATE_QUESTIONS,
} from "../../management/projects";
import * as logger from "../../logger";
import { promptOnce } from "../../prompt";
import { prompt, promptOnce } from "../../prompt";
import * as utils from "../../utils";

const MAXIMUM_PROMPT_LIST = 100;
Expand Down Expand Up @@ -98,6 +100,25 @@ async function selectProjectFromList(
return toProjectInfo(project);
}

async function promptAndCreateNewProject(): Promise<ProjectInfo> {
utils.logBullet(
"If you want to create a project in a Google Cloud organization or folder, please use " +
`"firebase projects:create" instead, and return to this command when you've created the project.`
);

const promptAnswer: { projectId?: string; displayName?: string } = {};
await prompt(promptAnswer, PROJECTS_CREATE_QUESTIONS);
if (!promptAnswer.projectId) {
throw new FirebaseError("Project ID cannot be empty");
}

return toProjectInfo(
await createFirebaseProjectAndLog(promptAnswer.projectId, {
displayName: promptAnswer.displayName,
})
);
}

function toProjectInfo(projectMetaData: FirebaseProjectMetadata): ProjectInfo {
const { projectId, displayName, resources } = projectMetaData;
return {
Expand Down Expand Up @@ -131,7 +152,7 @@ export async function doSetup(setup: any, config: Config, options: any): Promise
// we still need to get project info in case user wants to init firestore or storage, which
// require a resource location:
const rcProject: FirebaseProjectMetadata = await getFirebaseProject(projectFromRcFile);
setup.projectId = projectFromRcFile;
setup.projectId = rcProject.projectId;
setup.projectLocation = _.get(rcProject, "resources.locationId");
return;
}
Expand All @@ -148,18 +169,21 @@ export async function doSetup(setup: any, config: Config, options: any): Promise
choices,
});

let projectInfo;
if (projectSetupOption === OPTION_USE_PROJECT) {
const projectInfo = await getProjectInfo(options);
utils.logBullet(`Using project ${projectInfo.label}`);

// write "default" alias and activate it immediately
_.set(setup.rcfile, "projects.default", projectInfo.id);
setup.projectId = projectInfo.id;
setup.instance = projectInfo.instance;
setup.projectLocation = projectInfo.location;
utils.makeActiveProject(config.projectDir, projectInfo.id);
projectInfo = await getProjectInfo(options);
} else if (projectSetupOption === OPTION_NEW_PROJECT) {
// TODO(caot): Implement create a new project
setup.createProject = true;
projectInfo = await promptAndCreateNewProject();
} else {
// Do nothing if use choose NO_PROJECT
return;
}

utils.logBullet(`Using project ${projectInfo.label}`);
// write "default" alias and activate it immediately
_.set(setup.rcfile, "projects.default", projectInfo.id);
setup.projectId = projectInfo.id;
setup.instance = projectInfo.instance;
setup.projectLocation = projectInfo.location;
utils.makeActiveProject(config.projectDir, projectInfo.id);
}
54 changes: 54 additions & 0 deletions src/management/projects.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as api from "../api";
import * as clc from "cli-color";
import * as ora from "ora";

import * as FirebaseError from "../error";
import * as logger from "../logger";
import { pollOperation } from "../operation-poller";
import { Question } from "inquirer";

const TIMEOUT_MILLIS = 30000;
const PROJECT_LIST_PAGE_SIZE = 1000;
Expand Down Expand Up @@ -36,6 +40,56 @@ export interface ProjectParentResource {
type: ProjectParentResourceType;
}

export const PROJECTS_CREATE_QUESTIONS: Question[] = [
{
type: "input",
name: "projectId",
default: "",
message:
"Please specify a unique project id " +
`(${clc.yellow("warning")}: cannot be modified afterward) [6-30 characters]:\n`,
},
{
type: "input",
name: "displayName",
default: "",
message: "What would you like to call your project? (defaults to your project ID)",
},
];

export async function createFirebaseProjectAndLog(
projectId: string,
options: { displayName?: string; parentResource?: ProjectParentResource }
): Promise<FirebaseProjectMetadata> {
let spinner = ora("Creating Google Cloud Platform project").start();
try {
await createCloudProject(projectId, options);
spinner.succeed();

spinner = ora("Adding Firebase to Google Cloud project").start();
const projectInfo = await addFirebaseToCloudProject(projectId);
spinner.succeed();

logger.info("");
if (process.platform === "win32") {
logger.info("=== Your Firebase project is ready! ===");
} else {
logger.info("🎉🎉🎉 Your Firebase project is ready! 🎉🎉🎉");
}
logger.info("");
logger.info("Project information:");
logger.info(` - Project ID: ${clc.bold(projectInfo.projectId)}`);
logger.info(` - Project Name: ${clc.bold(projectInfo.displayName)}`);
logger.info("");
logger.info("Firebase console is available at");
logger.info(`https://console.firebase.google.com/project/${clc.bold(projectId)}/overview`);
return projectInfo;
} catch (err) {
spinner.fail();
throw err;
}
}

/**
* Send an API request to create a new Google Cloud Platform project and poll the LRO to get the
* new project information.
Expand Down
Loading