@hubspot/cli 3.0.12 → 3.0.13-beta.2

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 (48) hide show
  1. package/bin/cli.js +28 -2
  2. package/commands/accounts/use.js +82 -0
  3. package/commands/accounts.js +2 -0
  4. package/commands/config/set/allowUsageTracking.js +12 -19
  5. package/commands/config/set/defaultMode.js +11 -35
  6. package/commands/config/set/httpTimeout.js +27 -24
  7. package/commands/config/set.js +81 -13
  8. package/commands/logs.js +1 -7
  9. package/commands/module/marketplace-validate.js +77 -0
  10. package/commands/module.js +17 -0
  11. package/commands/project/logs.js +124 -60
  12. package/commands/project/open.js +75 -0
  13. package/commands/project.js +2 -0
  14. package/commands/sandbox/create.js +2 -2
  15. package/commands/sandbox.js +3 -1
  16. package/commands/theme/marketplace-validate.js +4 -2
  17. package/commands/upload.js +21 -10
  18. package/lib/projects.js +10 -7
  19. package/lib/prompts/personalAccessKeyPrompt.js +1 -1
  20. package/lib/prompts/projectNamePrompt.js +29 -0
  21. package/lib/prompts/projectsLogsPrompt.js +57 -0
  22. package/lib/serverlessLogs.js +25 -11
  23. package/lib/validators/__tests__/{BaseValidator.js → AbsoluteValidator.js} +3 -3
  24. package/lib/validators/__tests__/ModuleDependencyValidator.js +79 -0
  25. package/lib/validators/__tests__/ModuleValidator.js +22 -55
  26. package/lib/validators/__tests__/RelativeValidator.js +28 -0
  27. package/lib/validators/__tests__/TemplateValidator.js +1 -1
  28. package/lib/validators/__tests__/ThemeConfigValidator.js +1 -1
  29. package/lib/validators/__tests__/{DependencyValidator.js → ThemeDependencyValidator.js} +14 -12
  30. package/lib/validators/__tests__/ThemeModuleValidator.js +84 -0
  31. package/lib/validators/__tests__/validatorTestUtils.js +2 -0
  32. package/lib/validators/applyValidators.js +20 -4
  33. package/lib/validators/constants.js +4 -2
  34. package/lib/validators/index.js +8 -4
  35. package/lib/validators/marketplaceValidators/{BaseValidator.js → AbsoluteValidator.js} +8 -8
  36. package/lib/validators/marketplaceValidators/RelativeValidator.js +46 -0
  37. package/lib/validators/marketplaceValidators/module/ModuleDependencyValidator.js +101 -0
  38. package/lib/validators/marketplaceValidators/module/ModuleValidator.js +102 -0
  39. package/lib/validators/marketplaceValidators/theme/SectionValidator.js +2 -2
  40. package/lib/validators/marketplaceValidators/theme/TemplateValidator.js +2 -2
  41. package/lib/validators/marketplaceValidators/theme/ThemeConfigValidator.js +3 -3
  42. package/lib/validators/marketplaceValidators/theme/{DependencyValidator.js → ThemeDependencyValidator.js} +15 -12
  43. package/lib/validators/marketplaceValidators/theme/{ModuleValidator.js → ThemeModuleValidator.js} +5 -5
  44. package/package.json +4 -5
  45. package/bin/hubspot +0 -3
  46. package/commands/config/set/defaultAccount.js +0 -94
  47. package/commands/server.js +0 -80
  48. package/lib/server/updateContext.js +0 -105
@@ -1,5 +1,6 @@
1
- const Spinnies = require('spinnies');
2
- const { getCwd } = require('@hubspot/cli-lib/path');
1
+ const { getEnv } = require('@hubspot/cli-lib/lib/config');
2
+ const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
3
+ const { ENVIRONMENTS } = require('@hubspot/cli-lib/lib/constants');
3
4
  const {
4
5
  addAccountOptions,
5
6
  addConfigOptions,
@@ -9,6 +10,11 @@ const {
9
10
  const { trackCommandUsage } = require('../../lib/usageTracking');
10
11
  const { logger } = require('@hubspot/cli-lib/logger');
11
12
  const { outputLogs } = require('@hubspot/cli-lib/lib/logs');
13
+ const { fetchProject } = require('@hubspot/cli-lib/api/dfs');
14
+ const {
15
+ getTableContents,
16
+ getTableHeader,
17
+ } = require('@hubspot/cli-lib/lib/table');
12
18
  const {
13
19
  getProjectAppFunctionLogs,
14
20
  getLatestProjectAppFunctionLog,
@@ -17,35 +23,32 @@ const {
17
23
  getFunctionLogs,
18
24
  getLatestFunctionLog,
19
25
  } = require('@hubspot/cli-lib/api/results');
20
- const { getProjectConfig } = require('../../lib/projects');
26
+ const { ensureProjectExists } = require('../../lib/projects');
21
27
  const { loadAndValidateOptions } = require('../../lib/validation');
28
+ const { uiLine, uiLink } = require('../../lib/ui');
29
+ const { projectLogsPrompt } = require('../../lib/prompts/projectsLogsPrompt');
22
30
  const { tailLogs } = require('../../lib/serverlessLogs');
23
- const { uiAccountDescription } = require('../../lib/ui');
24
31
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
32
+ const { EXIT_CODES } = require('../../lib/enums/exitCodes');
25
33
 
26
34
  const i18nKey = 'cli.commands.project.subcommands.logs';
27
- const { EXIT_CODES } = require('../../lib/enums/exitCodes');
28
35
 
29
- const handleLogsError = (e, accountId, projectName, appPath, functionName) => {
36
+ const getPrivateAppsUrl = accountId => {
37
+ const baseUrl = getHubSpotWebsiteOrigin(
38
+ getEnv() === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD
39
+ );
40
+
41
+ return `${baseUrl}/private-apps/${accountId}`;
42
+ };
43
+
44
+ const handleLogsError = (e, name) => {
45
+ logger.debug(`Log fetch error: ${e.message}`);
30
46
  if (e.statusCode === 404) {
31
- logger.error(
32
- appPath
33
- ? i18n(`${i18nKey}.errors.noAppFunctionLogs`, {
34
- accountId,
35
- appPath,
36
- functionName,
37
- projectName,
38
- })
39
- : i18n(`${i18nKey}.errors.noEndpointLogs`, {
40
- accountId,
41
- functionName,
42
- projectName,
43
- })
44
- );
47
+ logger.log(i18n(`${i18nKey}.logs.noLogsFound`, { name }));
45
48
  }
46
49
  };
47
50
 
48
- const functionLog = async (accountId, options) => {
51
+ const handleFunctionLog = async (accountId, options) => {
49
52
  const {
50
53
  latest,
51
54
  follow,
@@ -71,9 +74,10 @@ const functionLog = async (accountId, options) => {
71
74
  )
72
75
  : getFunctionLogs(accountId, functionName, { after });
73
76
  } catch (e) {
74
- handleLogsError(e, accountId, projectName, appPath, functionName);
77
+ handleLogsError(e, functionName);
75
78
  }
76
79
  };
80
+
77
81
  const fetchLatest = async () => {
78
82
  return appPath
79
83
  ? getLatestProjectAppFunctionLog(
@@ -86,85 +90,145 @@ const functionLog = async (accountId, options) => {
86
90
  };
87
91
 
88
92
  if (follow) {
89
- const spinnies = new Spinnies();
90
-
91
- spinnies.add('tailLogs', {
92
- text: i18n(`${i18nKey}.loading`, {
93
- functionName,
94
- accountId: uiAccountDescription(accountId),
95
- }),
96
- });
97
-
98
93
  await tailLogs({
99
94
  accountId,
100
95
  compact,
101
- spinnies,
102
96
  tailCall,
103
97
  fetchLatest,
98
+ name: functionName,
104
99
  });
105
100
  } else if (latest) {
106
101
  try {
107
102
  logsResp = await fetchLatest();
108
103
  } catch (e) {
109
- handleLogsError(e, accountId, projectName, appPath, functionName);
104
+ handleLogsError(e, functionName);
105
+ return true;
110
106
  }
111
107
  } else {
112
108
  try {
113
109
  logsResp = await tailCall();
114
110
  } catch (e) {
115
- handleLogsError(e, accountId, projectName, appPath, functionName);
111
+ handleLogsError(e, functionName);
112
+ return true;
116
113
  }
117
114
  }
118
115
 
119
116
  if (logsResp) {
120
- return outputLogs(logsResp, options);
117
+ outputLogs(logsResp, options);
118
+ return true;
121
119
  }
120
+ return false;
122
121
  };
123
122
 
124
- exports.command = 'logs';
123
+ exports.command = 'logs [--project] [--app] [--function]';
125
124
  exports.describe = i18n(`${i18nKey}.describe`);
126
125
 
127
126
  exports.handler = async options => {
128
127
  await loadAndValidateOptions(options);
129
128
 
130
- const { latest, functionName } = options;
131
- let projectName = options.projectName;
132
-
133
- if (!functionName) {
134
- logger.error(i18n(`${i18nKey}.errors.functionNameRequired`));
135
- process.exit(EXIT_CODES.ERROR);
136
- } else if (!projectName) {
137
- const { projectConfig } = await getProjectConfig(getCwd());
138
- if (projectConfig && projectConfig.name) {
139
- projectName = projectConfig.name;
140
- } else {
141
- logger.error(i18n(`${i18nKey}.errors.projectNameRequired`));
142
- process.exit(EXIT_CODES.ERROR);
129
+ const accountId = getAccountId(options);
130
+
131
+ logger.log(options);
132
+ const {
133
+ projectName: promptProjectName,
134
+ appName: promptAppName,
135
+ functionName: promptFunctionName,
136
+ } = await projectLogsPrompt(accountId, options);
137
+
138
+ const projectName = options.project || promptProjectName;
139
+ const appName = options.app || promptAppName;
140
+ const functionName =
141
+ options.function || promptFunctionName || options.endpoint;
142
+
143
+ let relativeAppPath;
144
+
145
+ if (appName && !options.endpoint) {
146
+ await ensureProjectExists(accountId, projectName, {
147
+ allowCreate: false,
148
+ });
149
+ const { deployedBuild } = await fetchProject(accountId, projectName);
150
+
151
+ if (deployedBuild && deployedBuild.subbuildStatuses) {
152
+ const appSubbuild = deployedBuild.subbuildStatuses.find(
153
+ subbuild => subbuild.buildName === appName
154
+ );
155
+ if (appSubbuild) {
156
+ relativeAppPath = appSubbuild.rootPath;
157
+ } else {
158
+ logger.error(
159
+ i18n(`${i18nKey}.errors.invalidAppName`, {
160
+ appName: options.app,
161
+ projectName,
162
+ })
163
+ );
164
+ process.exit(EXIT_CODES.ERROR);
165
+ }
143
166
  }
144
167
  }
145
168
 
146
- const accountId = getAccountId(options);
169
+ trackCommandUsage('project-logs', { latest: options.latest }, accountId);
147
170
 
148
- trackCommandUsage('project-logs', { latest }, accountId);
171
+ const logsInfo = [
172
+ [accountId, `"${projectName}"`, `"${appName}"`, functionName],
173
+ ];
149
174
 
150
- functionLog(accountId, { ...options, projectName });
175
+ logsInfo.unshift(
176
+ getTableHeader([
177
+ i18n(`${i18nKey}.table.accountHeader`),
178
+ i18n(`${i18nKey}.table.projectHeader`),
179
+ i18n(`${i18nKey}.table.appHeader`),
180
+ i18n(`${i18nKey}.table.functionHeader`),
181
+ ])
182
+ );
183
+
184
+ logger.log(i18n(`${i18nKey}.logs.showingLogs`));
185
+ logger.log(getTableContents(logsInfo, { border: { bodyLeft: ' ' } }));
186
+
187
+ logger.log(
188
+ uiLink(
189
+ i18n(`${i18nKey}.logs.hubspotLogsLink`),
190
+ getPrivateAppsUrl(accountId)
191
+ )
192
+ );
193
+ logger.log();
194
+ uiLine();
195
+
196
+ const showFinalMessage = await handleFunctionLog(accountId, {
197
+ ...options,
198
+ projectName,
199
+ appPath: relativeAppPath,
200
+ functionName,
201
+ });
202
+
203
+ if (showFinalMessage) {
204
+ uiLine();
205
+ }
151
206
  };
152
207
 
153
208
  exports.builder = yargs => {
154
209
  yargs
155
210
  .options({
156
- functionName: {
211
+ function: {
157
212
  alias: 'function',
158
- describe: i18n(`${i18nKey}.positionals.functionName.describe`),
213
+ describe: i18n(`${i18nKey}.options.function.describe`),
214
+ requiresArg: true,
215
+ type: 'string',
216
+ },
217
+ endpoint: {
218
+ alias: 'endpoint',
219
+ describe: i18n(`${i18nKey}.options.endpoint.describe`),
220
+ hidden: true,
221
+ requiresArg: true,
159
222
  type: 'string',
160
- demandOption: true,
161
223
  },
162
- appPath: {
163
- describe: i18n(`${i18nKey}.options.appPath.describe`),
224
+ app: {
225
+ describe: i18n(`${i18nKey}.options.app.describe`),
226
+ requiresArg: true,
164
227
  type: 'string',
165
228
  },
166
- projectName: {
167
- describe: i18n(`${i18nKey}.options.projectName.describe`),
229
+ project: {
230
+ describe: i18n(`${i18nKey}.options.project.describe`),
231
+ requiresArg: true,
168
232
  type: 'string',
169
233
  },
170
234
  latest: {
@@ -191,7 +255,7 @@ exports.builder = yargs => {
191
255
 
192
256
  yargs.example([
193
257
  [
194
- '$0 project logs --function=my-function --appPath="app" --projectName="my-project"',
258
+ '$0 project logs --project="my-project" --app="app" --function=my-function',
195
259
  i18n(`${i18nKey}.examples.default`),
196
260
  ],
197
261
  ]);
@@ -0,0 +1,75 @@
1
+ const open = require('open');
2
+ const {
3
+ addAccountOptions,
4
+ addConfigOptions,
5
+ getAccountId,
6
+ addUseEnvironmentOptions,
7
+ addTestingOptions,
8
+ } = require('../../lib/commonOpts');
9
+ const { loadAndValidateOptions } = require('../../lib/validation');
10
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
11
+ const { logger } = require('@hubspot/cli-lib/logger');
12
+ const {
13
+ getProjectConfig,
14
+ getProjectDetailUrl,
15
+ ensureProjectExists,
16
+ } = require('../../lib/projects');
17
+ const { projectNamePrompt } = require('../../lib/prompts/projectNamePrompt');
18
+ const { EXIT_CODES } = require('../../lib/enums/exitCodes');
19
+
20
+ const i18nKey = 'cli.commands.project.subcommands.open';
21
+
22
+ exports.command = 'open [--project]';
23
+ exports.describe = i18n(`${i18nKey}.describe`);
24
+
25
+ exports.handler = async options => {
26
+ await loadAndValidateOptions(options);
27
+
28
+ const accountId = getAccountId(options);
29
+ const { project } = options;
30
+ const { projectConfig } = await getProjectConfig();
31
+
32
+ let projectName = project;
33
+
34
+ if (projectName) {
35
+ const projectExists = await ensureProjectExists(accountId, projectName, {
36
+ allowCreate: false,
37
+ });
38
+
39
+ if (!projectExists) {
40
+ process.exit(EXIT_CODES.ERROR);
41
+ }
42
+ } else if (!projectName && projectConfig) {
43
+ projectName = projectConfig.name;
44
+ } else if (!projectName && !projectConfig) {
45
+ const namePrompt = await projectNamePrompt(accountId, projectConfig);
46
+
47
+ if (!namePrompt.projectName) {
48
+ process.exit(EXIT_CODES.ERROR);
49
+ }
50
+ projectName = namePrompt.projectName;
51
+ }
52
+
53
+ const url = getProjectDetailUrl(projectName, accountId);
54
+ open(url, { url: true });
55
+ logger.success(i18n(`${i18nKey}.success`, { projectName }));
56
+ process.exit(EXIT_CODES.SUCCESS);
57
+ };
58
+
59
+ exports.builder = yargs => {
60
+ addConfigOptions(yargs, true);
61
+ addAccountOptions(yargs, true);
62
+ addUseEnvironmentOptions(yargs, true);
63
+ addTestingOptions(yargs, true);
64
+
65
+ yargs.options({
66
+ project: {
67
+ describe: i18n(`${i18nKey}.options.project.describe`),
68
+ type: 'string',
69
+ },
70
+ });
71
+
72
+ yargs.example([['$0 project open', i18n(`${i18nKey}.examples.default`)]]);
73
+
74
+ return yargs;
75
+ };
@@ -6,6 +6,7 @@ const listBuilds = require('./project/listBuilds');
6
6
  const logs = require('./project/logs');
7
7
  const watch = require('./project/watch');
8
8
  const download = require('./project/download');
9
+ const open = require('./project/open');
9
10
 
10
11
  exports.command = 'project';
11
12
  exports.describe = false; //'Commands for working with projects';
@@ -22,6 +23,7 @@ exports.builder = yargs => {
22
23
  yargs.command(listBuilds).demandCommand(0, '');
23
24
  yargs.command(logs).demandCommand(1, '');
24
25
  yargs.command(download).demandCommand(0, '');
26
+ yargs.command(open).demandCommand(0, '');
25
27
 
26
28
  return yargs;
27
29
  };
@@ -15,7 +15,7 @@ const { i18n } = require('@hubspot/cli-lib/lib/lang');
15
15
  const i18nKey = 'cli.commands.sandbox.subcommands.create';
16
16
 
17
17
  exports.command = 'create [name]';
18
- exports.describe = false;
18
+ exports.describe = i18n(`${i18nKey}.describe`);
19
19
 
20
20
  exports.handler = async options => {
21
21
  await loadAndValidateOptions(options);
@@ -41,7 +41,7 @@ exports.handler = async options => {
41
41
  return createSandbox(accountId, sandboxName).then(
42
42
  ({ name, sandboxHubId }) => {
43
43
  logger.success(
44
- i18n(`${i18nKey}.describe`, {
44
+ i18n(`${i18nKey}.success.create`, {
45
45
  name,
46
46
  sandboxHubId,
47
47
  })
@@ -1,8 +1,10 @@
1
1
  const { addConfigOptions, addAccountOptions } = require('../lib/commonOpts');
2
2
  const create = require('./sandbox/create');
3
3
 
4
+ // const i18nKey = 'cli.commands.sandbox';
5
+
4
6
  exports.command = 'sandbox';
5
- exports.describe = false; //'Commands for working with sandboxes';
7
+ exports.describe = false; // i18n(`${i18nKey}.describe`);
6
8
 
7
9
  exports.builder = yargs => {
8
10
  addConfigOptions(yargs, true);
@@ -16,7 +16,9 @@ const { trackCommandUsage } = require('../../lib/usageTracking');
16
16
  const {
17
17
  logValidatorResults,
18
18
  } = require('../../lib/validators/logValidatorResults');
19
- const { applyValidators } = require('../../lib/validators/applyValidators');
19
+ const {
20
+ applyAbsoluteValidators,
21
+ } = require('../../lib/validators/applyValidators');
20
22
  const MARKETPLACE_VALIDATORS = require('../../lib/validators');
21
23
  const { VALIDATION_RESULT } = require('../../lib/validators/constants');
22
24
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
@@ -65,7 +67,7 @@ exports.handler = async options => {
65
67
 
66
68
  const themeFiles = await walk(absoluteSrcPath);
67
69
 
68
- applyValidators(
70
+ applyAbsoluteValidators(
69
71
  MARKETPLACE_VALIDATORS.theme,
70
72
  absoluteSrcPath,
71
73
  themeFiles,
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
- const { uploadFolder } = require('@hubspot/cli-lib');
4
+ const { uploadFolder, hasUploadErrors } = require('@hubspot/cli-lib');
5
5
  const { getFileMapperQueryValues } = require('@hubspot/cli-lib/fileMapper');
6
6
  const { upload } = require('@hubspot/cli-lib/api/fileMapper');
7
7
  const {
@@ -55,7 +55,7 @@ exports.handler = async options => {
55
55
  await loadAndValidateOptions(options);
56
56
 
57
57
  if (!validateMode(options)) {
58
- process.exit(EXIT_CODES.ERROR);
58
+ process.exit(EXIT_CODES.WARNING);
59
59
  }
60
60
 
61
61
  const accountId = getAccountId(options);
@@ -98,7 +98,7 @@ exports.handler = async options => {
98
98
 
99
99
  if (srcDestIssues.length) {
100
100
  srcDestIssues.forEach(({ message }) => logger.error(message));
101
- process.exit(EXIT_CODES.ERROR);
101
+ process.exit(EXIT_CODES.WARNING);
102
102
  }
103
103
  if (stats.isFile()) {
104
104
  if (!isAllowedExtension(src)) {
@@ -150,6 +150,7 @@ exports.handler = async options => {
150
150
  payload: src,
151
151
  })
152
152
  );
153
+ process.exit(EXIT_CODES.WARNING);
153
154
  });
154
155
  } else {
155
156
  logger.log(
@@ -162,13 +163,22 @@ exports.handler = async options => {
162
163
  uploadFolder(accountId, absoluteSrcPath, dest, {
163
164
  mode,
164
165
  })
165
- .then(() => {
166
- logger.success(
167
- i18n(`${i18nKey}.success.uploadComplete`, {
168
- dest,
169
- })
170
- );
171
- logThemePreview(src, accountId);
166
+ .then(results => {
167
+ if (!hasUploadErrors(results)) {
168
+ logger.success(
169
+ i18n(`${i18nKey}.success.uploadComplete`, {
170
+ dest,
171
+ })
172
+ );
173
+ logThemePreview(src, accountId);
174
+ } else {
175
+ logger.error(
176
+ i18n(`${i18nKey}.errors.someFilesFailed`, {
177
+ dest,
178
+ })
179
+ );
180
+ process.exit(EXIT_CODES.WARNING);
181
+ }
172
182
  })
173
183
  .catch(error => {
174
184
  logger.error(
@@ -180,6 +190,7 @@ exports.handler = async options => {
180
190
  logErrorInstance(error, {
181
191
  accountId,
182
192
  });
193
+ process.exit(EXIT_CODES.WARNING);
183
194
  });
184
195
  }
185
196
  };
package/lib/projects.js CHANGED
@@ -29,7 +29,7 @@ const {
29
29
  ApiErrorContext,
30
30
  } = require('@hubspot/cli-lib/errorHandlers');
31
31
  const { shouldIgnoreFile } = require('@hubspot/cli-lib/ignoreRules');
32
- const { getCwd } = require('@hubspot/cli-lib/path');
32
+ const { getCwd, getAbsoluteFilePath } = require('@hubspot/cli-lib/path');
33
33
  const { promptUser } = require('./prompts/promptUtils');
34
34
  const { EXIT_CODES } = require('./enums/exitCodes');
35
35
  const { uiLine, uiLink, uiAccountDescription } = require('../lib/ui');
@@ -45,13 +45,13 @@ const writeProjectConfig = (configPath, config) => {
45
45
  }
46
46
  };
47
47
 
48
- const getIsInProject = async _dir => {
49
- const configPath = await getProjectConfigPath(_dir);
48
+ const getIsInProject = _dir => {
49
+ const configPath = getProjectConfigPath(_dir);
50
50
  return !!configPath;
51
51
  };
52
52
 
53
- const getProjectConfigPath = async _dir => {
54
- const projectDir = _dir ? path.resolve(getCwd(), _dir) : getCwd();
53
+ const getProjectConfigPath = _dir => {
54
+ const projectDir = _dir ? getAbsoluteFilePath(_dir) : getCwd();
55
55
 
56
56
  const configPath = findup(PROJECT_CONFIG_FILE, {
57
57
  cwd: projectDir,
@@ -168,7 +168,8 @@ const ensureProjectExists = async (
168
168
  { forceCreate = false, allowCreate = true } = {}
169
169
  ) => {
170
170
  try {
171
- await fetchProject(accountId, projectName);
171
+ const project = await fetchProject(accountId, projectName);
172
+ return !!project;
172
173
  } catch (err) {
173
174
  if (err.statusCode === 404) {
174
175
  let shouldCreateProject = forceCreate;
@@ -193,14 +194,16 @@ const ensureProjectExists = async (
193
194
  return logApiErrorInstance(err, new ApiErrorContext({ accountId }));
194
195
  }
195
196
  } else {
196
- return logger.log(
197
+ logger.log(
197
198
  `Your project ${chalk.bold(
198
199
  projectName
199
200
  )} could not be found in ${chalk.bold(accountId)}.`
200
201
  );
202
+ return false;
201
203
  }
202
204
  }
203
205
  logApiErrorInstance(err, new ApiErrorContext({ accountId }));
206
+ return false;
204
207
  }
205
208
  };
206
209
 
@@ -107,7 +107,7 @@ const PERSONAL_ACCESS_KEY = {
107
107
  name: 'personalAccessKey',
108
108
  message: i18n(`${i18nKey}.enterPersonalAccessKey`),
109
109
  validate(val) {
110
- if (typeof val !== 'string') {
110
+ if (!val || typeof val !== 'string') {
111
111
  return i18n(`${i18nKey}.errors.invalidPersonalAccessKey`);
112
112
  } else if (val[0] === '•') {
113
113
  return i18n(`${i18nKey}.errors.invalidPersonalAccessKeyCopy`);
@@ -0,0 +1,29 @@
1
+ const { promptUser } = require('./promptUtils');
2
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
3
+ const { ensureProjectExists } = require('../projects');
4
+
5
+ const i18nKey = 'cli.lib.prompts.projectNamePrompt';
6
+
7
+ const projectNamePrompt = accountId => {
8
+ return promptUser({
9
+ name: 'projectName',
10
+ message: i18n(`${i18nKey}.enterName`),
11
+ validate: async val => {
12
+ if (typeof val !== 'string') {
13
+ return i18n(`${i18nKey}.errors.invalidName`);
14
+ }
15
+ const projectExists = await ensureProjectExists(accountId, val, {
16
+ allowCreate: false,
17
+ });
18
+
19
+ if (!projectExists) {
20
+ return false;
21
+ }
22
+ return true;
23
+ },
24
+ });
25
+ };
26
+
27
+ module.exports = {
28
+ projectNamePrompt,
29
+ };
@@ -0,0 +1,57 @@
1
+ const { i18n } = require('@hubspot/cli-lib/lib/lang');
2
+ const { fetchProject } = require('@hubspot/cli-lib/api/dfs');
3
+ const { promptUser } = require('./promptUtils');
4
+ const { getProjectConfig, ensureProjectExists } = require('../projects');
5
+ const { logger } = require('@hubspot/cli-lib/logger');
6
+ const { EXIT_CODES } = require('../enums/exitCodes');
7
+
8
+ const i18nKey = 'cli.lib.prompts.projectLogsPrompt';
9
+
10
+ const projectLogsPrompt = (accountId, promptOptions = {}) => {
11
+ return promptUser([
12
+ {
13
+ name: 'projectName',
14
+ message: i18n(`${i18nKey}.projectName`),
15
+ when: !promptOptions.project,
16
+ default: async () => {
17
+ const { projectConfig } = await getProjectConfig();
18
+ return projectConfig && projectConfig.name ? projectConfig.name : null;
19
+ },
20
+ },
21
+ {
22
+ name: 'appName',
23
+ type: 'list',
24
+ message: i18n(`${i18nKey}.appName`),
25
+ when: !promptOptions.app && !promptOptions.endpoint,
26
+ choices: async ({ projectName }) => {
27
+ const name = projectName || promptOptions.project;
28
+
29
+ await ensureProjectExists(accountId, name, {
30
+ allowCreate: false,
31
+ });
32
+ const { deployedBuild } = await fetchProject(accountId, name);
33
+
34
+ if (deployedBuild && deployedBuild.subbuildStatuses) {
35
+ return deployedBuild.subbuildStatuses
36
+ .filter(subbuild => subbuild.buildType === 'APP')
37
+ .map(subbuild => ({
38
+ name: subbuild.buildName,
39
+ value: subbuild.buildName,
40
+ }));
41
+ } else {
42
+ logger.debug('Failed to fetch project');
43
+ process.exit(EXIT_CODES.ERROR);
44
+ }
45
+ },
46
+ },
47
+ {
48
+ name: 'functionName',
49
+ message: i18n(`${i18nKey}.functionName`),
50
+ when: !promptOptions.function && !promptOptions.endpoint,
51
+ },
52
+ ]);
53
+ };
54
+
55
+ module.exports = {
56
+ projectLogsPrompt,
57
+ };