Skip to content

Commit 2354637

Browse files
authored
Merge pull request #567 from HubSpot/project-create-command
Project create command
2 parents d3426a8 + 4134f5d commit 2354637

File tree

5 files changed

+81
-80
lines changed

5 files changed

+81
-80
lines changed

packages/cli-lib/lib/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ const PROJECT_TEMPLATE_TYPES = {
118118
},
119119
};
120120

121+
const PROJECT_TEMPLATE_REPO = {
122+
'getting-started': 'getting-started-project-template',
123+
};
124+
121125
const TEMPLATE_TYPES = {
122126
unmapped: 0,
123127
email_base_template: 1,
@@ -239,6 +243,7 @@ module.exports = {
239243
PROJECT_BUILD_STATUS_TEXT,
240244
PROJECT_DEPLOY_STATUS,
241245
PROJECT_DEPLOY_STATUS_TEXT,
246+
PROJECT_TEMPLATE_REPO,
242247
PROJECT_OVERALL_STATUS,
243248
PROJECT_TEMPLATE_TYPES,
244249
PROJECT_TEXT,

packages/cli/commands/project.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const {
44
addOverwriteOptions,
55
} = require('../lib/commonOpts');
66
const deploy = require('./project/deploy');
7-
const init = require('./project/init');
7+
const create = require('./project/create');
88
const upload = require('./project/upload');
99
const logs = require('./project/logs');
1010

@@ -18,7 +18,7 @@ exports.builder = yargs => {
1818

1919
// TODO: deploy must be updated
2020
yargs.command(deploy).demandCommand(1, '');
21-
yargs.command(init).demandCommand(0, '');
21+
yargs.command(create).demandCommand(0, '');
2222
yargs.command(upload).demandCommand(0, '');
2323
yargs.command(logs).demandCommand(1, '');
2424

packages/cli/commands/project/init.js renamed to packages/cli/commands/project/create.js

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,11 @@ const {
1212
validateConfig,
1313
checkAndWarnGitInclusion,
1414
} = require('@hubspot/cli-lib');
15-
const {
16-
logApiErrorInstance,
17-
ApiErrorContext,
18-
} = require('@hubspot/cli-lib/errorHandlers');
19-
const { logger } = require('@hubspot/cli-lib/logger');
20-
const { createProject } = require('@hubspot/cli-lib/api/dfs');
2115
const { validateAccount } = require('../../lib/validation');
2216
const { getCwd } = require('@hubspot/cli-lib/path');
2317
const path = require('path');
2418
const {
25-
getOrCreateProjectConfig,
19+
createProjectConfig,
2620
showWelcomeMessage,
2721
} = require('../../lib/projects');
2822

@@ -38,40 +32,20 @@ const loadAndValidateOptions = async options => {
3832
}
3933
};
4034

41-
exports.command = 'init [path]';
35+
exports.command = 'create [path]';
4236
exports.describe = false;
4337

4438
exports.handler = async options => {
4539
loadAndValidateOptions(options);
4640

47-
const { path: projectPath } = options;
41+
const { path: projectPath, name } = options;
4842
const accountId = getAccountId(options);
4943

50-
trackCommandUsage('project-init', { projectPath }, accountId);
44+
trackCommandUsage('project-create', { projectPath }, accountId);
5145

5246
const cwd = projectPath ? path.resolve(getCwd(), projectPath) : getCwd();
53-
const projectConfig = await getOrCreateProjectConfig(cwd);
54-
55-
logger.log(`Initializing project: ${projectConfig.name}`);
56-
57-
try {
58-
await createProject(accountId, projectConfig.name);
5947

60-
logger.success(
61-
`"${projectConfig.name}" creation succeeded in account ${accountId}`
62-
);
63-
} catch (e) {
64-
if (e.statusCode === 409) {
65-
logger.log(
66-
`Project ${projectConfig.name} already exists in ${accountId}.`
67-
);
68-
} else {
69-
return logApiErrorInstance(
70-
e,
71-
new ApiErrorContext({ accountId, projectPath })
72-
);
73-
}
74-
}
48+
const projectConfig = await createProjectConfig(cwd, name);
7549

7650
showWelcomeMessage(projectConfig.name, accountId);
7751
};
@@ -81,22 +55,17 @@ exports.builder = yargs => {
8155
describe: 'Path to a project folder',
8256
type: 'string',
8357
});
84-
// TODO: These are not currently used
8558
yargs.options({
8659
name: {
8760
describe: 'Project name (cannot be changed)',
8861
type: 'string',
8962
},
90-
srcDir: {
91-
describe: 'Directory of project',
92-
type: 'string',
93-
},
9463
});
9564

9665
yargs.example([
9766
[
98-
'$0 project init myProjectFolder',
99-
'Initialize a project within the myProjectFolder folder',
67+
'$0 project create myProjectFolder',
68+
'Create a project within the myProjectFolder folder',
10069
],
10170
]);
10271

packages/cli/commands/project/deploy.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ const { logger } = require('@hubspot/cli-lib/logger');
2121
const { deployProject, fetchProject } = require('@hubspot/cli-lib/api/dfs');
2222
const { getCwd } = require('@hubspot/cli-lib/path');
2323
const { validateAccount } = require('../../lib/validation');
24-
const {
25-
getOrCreateProjectConfig,
26-
pollDeployStatus,
27-
} = require('../../lib/projects');
24+
const { getProjectConfig, pollDeployStatus } = require('../../lib/projects');
2825

2926
const loadAndValidateOptions = async options => {
3027
setLogLevel(options);
@@ -50,7 +47,7 @@ exports.handler = async options => {
5047
trackCommandUsage('project-deploy', { projectPath }, accountId);
5148

5249
const cwd = projectPath ? path.resolve(getCwd(), projectPath) : getCwd();
53-
const projectConfig = await getOrCreateProjectConfig(cwd);
50+
const projectConfig = await getProjectConfig(cwd);
5451

5552
logger.debug(`Deploying project at path: ${projectPath}`);
5653

packages/cli/lib/projects.js

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const fs = require('fs');
1+
const fs = require('fs-extra');
22
const path = require('path');
33

44
const chalk = require('chalk');
@@ -7,18 +7,19 @@ const { prompt } = require('inquirer');
77
const Spinnies = require('spinnies');
88
const { logger } = require('@hubspot/cli-lib/logger');
99
const { getEnv } = require('@hubspot/cli-lib/lib/config');
10+
const { createProject } = require('@hubspot/cli-lib/projects');
1011
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
1112
const {
1213
ENVIRONMENTS,
1314
POLLING_DELAY,
15+
PROJECT_TEMPLATE_REPO,
1416
PROJECT_OVERALL_STATUS,
1517
PROJECT_TEXT,
1618
} = require('@hubspot/cli-lib/lib/constants');
1719
const {
1820
getBuildStatus,
1921
getDeployStatus,
2022
fetchProject,
21-
createProject,
2223
} = require('@hubspot/cli-lib/api/dfs');
2324
const {
2425
logApiErrorInstance,
@@ -53,6 +54,7 @@ const isTaskComplete = task => {
5354

5455
const writeProjectConfig = (configPath, config) => {
5556
try {
57+
fs.ensureFileSync(configPath);
5658
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
5759
logger.debug(`Wrote project config at ${configPath}`);
5860
} catch (e) {
@@ -78,14 +80,25 @@ const getProjectConfig = async projectPath => {
7880
}
7981
};
8082

81-
const getOrCreateProjectConfig = async projectPath => {
83+
const createProjectConfig = async (projectPath, projectName) => {
8284
const projectConfig = await getProjectConfig(projectPath);
85+
const projectConfigPath = path.join(projectPath, 'hsproject.json');
8386

84-
if (!projectConfig) {
85-
const { name, srcDir } = await prompt([
87+
if (projectConfig) {
88+
logger.log(
89+
`Found an existing project config in this folder (${chalk.bold(
90+
projectConfig.name
91+
)})`
92+
);
93+
} else {
94+
logger.log(
95+
`Creating project in ${projectPath ? projectPath : 'the current folder'}`
96+
);
97+
const { name, template, srcDir } = await prompt([
8698
{
8799
name: 'name',
88100
message: 'Please enter a project name:',
101+
when: !projectName,
89102
validate: input => {
90103
if (!input) {
91104
return 'A project name is required';
@@ -94,20 +107,43 @@ const getOrCreateProjectConfig = async projectPath => {
94107
},
95108
},
96109
{
97-
name: 'srcDir',
98-
message: 'Which directory contains your project files?',
99-
validate: input => {
100-
if (!input) {
101-
return 'A source directory is required';
102-
}
103-
return true;
104-
},
110+
name: 'template',
111+
message: 'Start from a template?',
112+
type: 'rawlist',
113+
choices: [
114+
{
115+
name: 'No template',
116+
value: 'none',
117+
},
118+
{
119+
name: 'Getting Started Project',
120+
value: 'getting-started',
121+
},
122+
],
105123
},
106124
]);
107-
writeProjectConfig(path.join(projectPath, 'hsproject.json'), {
108-
name,
109-
srcDir,
110-
});
125+
126+
if (template === 'none') {
127+
fs.ensureDirSync(path.join(projectPath, 'src'));
128+
129+
writeProjectConfig(projectConfigPath, {
130+
name: projectName || name,
131+
srcDir: 'src',
132+
});
133+
} else {
134+
await createProject(
135+
projectPath,
136+
'project',
137+
PROJECT_TEMPLATE_REPO[template],
138+
''
139+
);
140+
const _config = JSON.parse(fs.readFileSync(projectConfigPath));
141+
writeProjectConfig(projectConfigPath, {
142+
..._config,
143+
name: projectName || name,
144+
});
145+
}
146+
111147
return { name, srcDir };
112148
}
113149

@@ -178,31 +214,24 @@ const getProjectDetailUrl = (projectName, accountId) => {
178214
return `${baseUrl}/developer-projects/${accountId}/project/${projectName}`;
179215
};
180216

181-
const showWelcomeMessage = (projectName, accountId) => {
182-
const projectDetailUrl = getProjectDetailUrl(projectName, accountId);
183-
217+
const showWelcomeMessage = () => {
184218
logger.log('');
185-
logger.log(chalk.bold('> Welcome to HubSpot Developer Projects!'));
219+
logger.log(chalk.bold('Welcome to HubSpot Developer Projects!'));
186220
logger.log(
187221
'\n-------------------------------------------------------------\n'
188222
);
189-
if (projectDetailUrl) {
190-
logger.log(chalk.italic(`View this project at: ${projectDetailUrl}`));
191-
}
192-
logger.log('');
193-
logger.log(chalk.bold('Getting Started'));
194-
logger.log('');
195-
logger.log('1. hs project upload');
223+
logger.log(chalk.bold("What's next?\n"));
224+
logger.log('🎨 Add deployables to your project with `hs create`.\n');
196225
logger.log(
197-
' Upload your project files to HubSpot. Upload action adds your files to a build.'
226+
`🏗 Run \`hs project upload\` to upload your files to HubSpot and trigger builds.\n`
198227
);
199-
logger.log();
200-
logger.log('2. View your changes on the preview build url');
201-
logger.log();
202-
logger.log('Use `hs project --help` to learn more about the command.');
203228
logger.log(
204-
'\n-------------------------------------------------------------\n'
229+
`🚀 Ready to take your project live? Run \`hs project deploy\`.\n`
230+
);
231+
logger.log(
232+
`🔗 Use \`hs project --help\` to learn more about available commands.\n`
205233
);
234+
logger.log('-------------------------------------------------------------');
206235
};
207236

208237
const makeGetTaskStatus = taskType => {
@@ -311,9 +340,10 @@ const makeGetTaskStatus = taskType => {
311340
module.exports = {
312341
writeProjectConfig,
313342
getProjectConfig,
314-
getOrCreateProjectConfig,
343+
createProjectConfig,
315344
validateProjectConfig,
316345
showWelcomeMessage,
346+
getProjectDetailUrl,
317347
pollBuildStatus: makeGetTaskStatus('build'),
318348
pollDeployStatus: makeGetTaskStatus('deploy'),
319349
ensureProjectExists,

0 commit comments

Comments
 (0)