-
Notifications
You must be signed in to change notification settings - Fork 906
/
project.ts
143 lines (128 loc) · 4.6 KB
/
project.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import * as clc from "cli-color";
import * as _ from "lodash";
import * as Config from "../../config";
import * as FirebaseError from "../../error";
import { FirebaseProject, getProject, listProjects } from "../../firebaseApi";
import * as logger from "../../logger";
import { promptOnce, Question } from "../../prompt";
import * as utils from "../../utils";
const NO_PROJECT = "[don't setup a default project]";
const NEW_PROJECT = "[create a new project]";
/**
* Used in init flows to keep information about the project - basically
* a shorter version of {@link FirebaseProject} with some additional fields.
*/
export interface ProjectInfo {
id: string; // maps to FirebaseProject.projectId
label?: string;
instance?: string; // maps to FirebaseProject.resources.realtimeDatabaseInstance
location?: string; // maps to FirebaseProject.resources.locationId
}
/**
* Get the user's desired project, prompting if necessary.
* @returns A {@link ProjectInfo} object.
*/
async function getProjectInfo(options: any): Promise<ProjectInfo> {
if (options.project) {
return selectProjectFromOptions(options);
}
return selectProjectFromList(options);
}
/**
* Selects project when --project is passed in.
* @param options Command line options.
* @returns A {@link FirebaseProject} object.
*/
async function selectProjectFromOptions(options: any): Promise<ProjectInfo> {
let project: FirebaseProject;
try {
project = await getProject(options.project);
} catch (e) {
throw new FirebaseError(`Error getting project ${options.project}: ${e}`);
}
const projectId = project.projectId;
const name = project.displayName;
return {
id: projectId,
label: `${projectId} (${name})`,
instance: _.get(project, "resources.realtimeDatabaseInstance"),
};
}
/**
* Presents user with list of projects to choose from and gets project
* information for chosen project.
* @param options Command line options.
* @returns A {@link FirebaseProject} object.
*/
async function selectProjectFromList(options: any): Promise<ProjectInfo> {
const projects: FirebaseProject[] = await listProjects();
let choices = projects.filter((p: FirebaseProject) => !!p).map((p) => {
return {
name: `${p.projectId} (${p.displayName})`,
value: p.projectId,
};
});
choices = _.orderBy(choices, ["name"], ["asc"]);
choices.unshift({ name: NO_PROJECT, value: NO_PROJECT });
choices.push({ name: NEW_PROJECT, value: NEW_PROJECT });
if (choices.length >= 25) {
utils.logBullet(
`Don't want to scroll through all your projects? If you know your project ID, ` +
`you can initialize it directly using ${clc.bold(
"firebase init --project <project_id>"
)}.\n`
);
}
const projectId: string = await promptOnce({
type: "list",
name: "id",
message: "Select a default Firebase project for this directory:",
choices,
});
if (projectId === NEW_PROJECT || projectId === NO_PROJECT) {
return { id: projectId };
}
let project: FirebaseProject | undefined;
project = projects.find((p) => p.projectId === projectId);
const pId = choices.find((p) => p.value === projectId);
const label = pId ? pId.name : "";
return {
id: projectId,
label,
instance: _.get(project, "resources.realtimeDatabaseInstance"),
};
}
/**
* Sets up the default project if provided and writes .firebaserc file.
* @param setup A helper object to use for the rest of the init features.
* @param config Configuration for the project.
* @param options Command line options.
*/
export async function doSetup(setup: any, config: Config, options: any): Promise<void> {
setup.project = {};
logger.info();
logger.info(`First, let's associate this project directory with a Firebase project.`);
logger.info(
`You can create multiple project aliases by running ${clc.bold("firebase use --add")}, `
);
logger.info(`but for now we'll just set up a default project.`);
logger.info();
if (_.has(setup.rcfile, "projects.default")) {
utils.logBullet(`.firebaserc already has a default project, skipping`);
setup.projectId = _.get(setup.rcfile, "projects.default");
return;
}
const projectInfo = await getProjectInfo(options);
if (projectInfo.id === NEW_PROJECT) {
setup.createProject = true;
return;
} else if (projectInfo.id === 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;
utils.makeActiveProject(config.projectDir, projectInfo.id);
}