@hubspot/cli 7.7.20-experimental.0 → 7.7.21-experimental.1

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 (62) hide show
  1. package/bin/cli.js +6 -2
  2. package/commands/__tests__/getStarted.test.js +0 -10
  3. package/commands/app/__tests__/install.test.d.ts +1 -0
  4. package/commands/app/__tests__/install.test.js +52 -0
  5. package/commands/app/install.d.ts +8 -0
  6. package/commands/app/install.js +127 -0
  7. package/commands/app.js +6 -1
  8. package/commands/getStarted.js +12 -27
  9. package/commands/mcp/setup.js +1 -0
  10. package/commands/mcp/start.d.ts +4 -1
  11. package/commands/mcp/start.js +8 -3
  12. package/commands/project/__tests__/deploy.test.js +27 -25
  13. package/commands/project/__tests__/devUnifiedFlow.test.js +20 -16
  14. package/commands/project/create.js +1 -1
  15. package/commands/project/deploy.d.ts +3 -2
  16. package/commands/project/deploy.js +61 -55
  17. package/commands/project/dev/unifiedFlow.js +7 -6
  18. package/commands/testAccount/__tests__/createConfig.test.js +0 -3
  19. package/commands/testAccount/create.js +14 -24
  20. package/commands/testAccount/createConfig.d.ts +0 -2
  21. package/commands/testAccount/createConfig.js +7 -8
  22. package/lang/en.d.ts +61 -23
  23. package/lang/en.js +62 -24
  24. package/lang/en.lyaml +0 -26
  25. package/lib/__tests__/buildAccount.test.js +30 -2
  26. package/lib/__tests__/usageTracking.test.js +8 -14
  27. package/lib/buildAccount.d.ts +7 -1
  28. package/lib/buildAccount.js +54 -4
  29. package/lib/mcp/setup.js +8 -3
  30. package/lib/projects/add/legacyAddComponent.js +1 -1
  31. package/lib/projects/add/v3AddComponent.js +1 -1
  32. package/lib/projects/localDev/DevServerManager.js +0 -2
  33. package/lib/projects/localDev/DevServerManagerV2.js +0 -2
  34. package/lib/projects/localDev/helpers.d.ts +1 -1
  35. package/lib/projects/localDev/helpers.js +2 -2
  36. package/lib/projects/structure.d.ts +2 -2
  37. package/lib/projects/upload.d.ts +2 -1
  38. package/lib/projects/upload.js +2 -1
  39. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +11 -10
  40. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +73 -31
  41. package/lib/prompts/promptUtils.js +66 -56
  42. package/lib/ui/index.js +1 -1
  43. package/lib/usageTracking.d.ts +11 -0
  44. package/lib/usageTracking.js +67 -73
  45. package/mcp-server/tools/project/AddFeatureToProject.js +4 -1
  46. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  47. package/mcp-server/tools/project/CreateProjectTool.js +4 -1
  48. package/mcp-server/tools/project/DeployProject.js +4 -1
  49. package/mcp-server/tools/project/GuidedWalkthroughTool.js +4 -1
  50. package/mcp-server/tools/project/UploadProjectTools.js +4 -1
  51. package/mcp-server/tools/project/ValidateProjectTool.js +4 -1
  52. package/mcp-server/tools/project/__tests__/AddFeatureToProject.test.js +1 -0
  53. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -0
  54. package/mcp-server/tools/project/__tests__/DeployProject.test.js +1 -0
  55. package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -0
  56. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -0
  57. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -0
  58. package/mcp-server/utils/__tests__/project.test.js +9 -6
  59. package/mcp-server/utils/project.js +3 -0
  60. package/mcp-server/utils/toolUsageTracking.d.ts +1 -0
  61. package/mcp-server/utils/toolUsageTracking.js +25 -0
  62. package/package.json +4 -4
@@ -1,65 +1,50 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const chalk_1 = __importDefault(require("chalk"));
7
3
  const projects_1 = require("@hubspot/local-dev-lib/api/projects");
8
4
  const config_1 = require("@hubspot/local-dev-lib/config");
9
- const logger_1 = require("@hubspot/local-dev-lib/logger");
10
5
  const index_1 = require("@hubspot/local-dev-lib/errors/index");
11
6
  const buildAndDeploy_1 = require("../../lib/projects/buildAndDeploy");
12
7
  const usageTracking_1 = require("../../lib/usageTracking");
13
8
  const index_2 = require("../../lib/errorHandlers/index");
14
9
  const config_2 = require("../../lib/projects/config");
15
10
  const buildAndDeploy_2 = require("../../lib/projects/buildAndDeploy");
16
- const urls_1 = require("../../lib/projects/urls");
17
11
  const projectNamePrompt_1 = require("../../lib/prompts/projectNamePrompt");
18
12
  const promptUtils_1 = require("../../lib/prompts/promptUtils");
19
- const lang_1 = require("../../lib/lang");
20
13
  const ui_1 = require("../../lib/ui");
21
14
  const exitCodes_1 = require("../../lib/enums/exitCodes");
22
- const ui_2 = require("../../lib/ui");
15
+ const logger_1 = require("../../lib/ui/logger");
23
16
  const yargsUtils_1 = require("../../lib/yargsUtils");
24
17
  const projectProfiles_1 = require("../../lib/projectProfiles");
25
18
  const constants_1 = require("../../lib/constants");
19
+ const en_1 = require("../../lang/en");
26
20
  const command = 'deploy';
27
- const describe = (0, ui_1.uiBetaTag)((0, lang_1.i18n)(`commands.project.subcommands.deploy.describe`), false);
21
+ const describe = (0, ui_1.uiBetaTag)(en_1.commands.project.deploy.describe, false);
28
22
  function validateBuildId(buildId, deployedBuildId, latestBuildId, projectName, accountId) {
29
23
  if (Number(buildId) > latestBuildId) {
30
- return (0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.buildIdDoesNotExist`, {
31
- buildId: buildId,
32
- projectName: projectName,
33
- linkToProject: (0, ui_1.uiLink)((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.viewProjectsBuilds`), (0, urls_1.getProjectDetailUrl)(projectName, accountId)),
34
- });
24
+ return en_1.commands.project.deploy.errors.buildIdDoesNotExist(accountId, buildId, projectName);
35
25
  }
36
26
  if (Number(buildId) === deployedBuildId) {
37
- return (0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.buildAlreadyDeployed`, {
38
- buildId: buildId,
39
- linkToProject: (0, ui_1.uiLink)((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.viewProjectsBuilds`), (0, urls_1.getProjectDetailUrl)(projectName, accountId)),
40
- });
27
+ return en_1.commands.project.deploy.errors.buildAlreadyDeployed(accountId, buildId, projectName);
41
28
  }
42
29
  return true;
43
30
  }
44
31
  function logDeployErrors(errorData) {
45
- logger_1.logger.error(errorData.message);
32
+ logger_1.uiLogger.error(errorData.message);
46
33
  errorData.errors.forEach(err => {
47
34
  if (err.subCategory === constants_1.PROJECT_ERROR_TYPES.DEPLOY_CONTAINS_REMOVALS) {
48
- logger_1.logger.log((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.deployContainsRemovals`, {
49
- componentName: err.context.COMPONENT_NAME,
50
- forceFlag: (0, ui_2.uiCommandReference)('--force'),
51
- }));
35
+ logger_1.uiLogger.log(en_1.commands.project.deploy.errors.deployContainsRemovals(err.context.COMPONENT_NAME));
52
36
  }
53
37
  else {
54
- logger_1.logger.log(err.message);
38
+ logger_1.uiLogger.log(err.message);
55
39
  }
56
40
  });
57
41
  }
58
42
  async function handler(args) {
59
- const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, } = args;
43
+ const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, json: formatOutputAsJson, } = args;
60
44
  const accountConfig = (0, config_1.getAccountConfig)(derivedAccountId);
61
45
  const accountType = accountConfig && accountConfig.accountType;
62
46
  let targetAccountId;
47
+ const jsonOutput = {};
63
48
  const { projectConfig, projectDir } = await (0, config_2.getProjectConfig)();
64
49
  if ((0, buildAndDeploy_1.useV3Api)(projectConfig?.platformVersion)) {
65
50
  if (args.profile) {
@@ -90,55 +75,63 @@ async function handler(args) {
90
75
  });
91
76
  projectName = namePromptResponse.projectName;
92
77
  let buildIdToDeploy = buildIdOption;
78
+ let deploySuccess = false;
93
79
  try {
94
80
  const { data: { latestBuild, deployedBuildId }, } = await (0, projects_1.fetchProject)(targetAccountId, projectName);
95
81
  if (!latestBuild || !latestBuild.buildId) {
96
- logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.noBuilds`));
82
+ logger_1.uiLogger.error(en_1.commands.project.deploy.errors.noBuilds);
97
83
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
98
84
  }
99
85
  if (buildIdToDeploy) {
100
86
  const validationResult = validateBuildId(buildIdToDeploy, deployedBuildId, latestBuild.buildId, projectName, targetAccountId);
101
87
  if (validationResult !== true) {
102
- logger_1.logger.error(validationResult);
88
+ logger_1.uiLogger.error(validationResult.toString());
103
89
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
104
90
  }
105
91
  }
106
92
  else {
107
- const deployBuildIdPromptResponse = await (0, promptUtils_1.promptUser)({
108
- name: 'buildId',
109
- message: (0, lang_1.i18n)(`commands.project.subcommands.deploy.deployBuildIdPrompt`),
110
- default: latestBuild.buildId === deployedBuildId
111
- ? undefined
112
- : latestBuild.buildId,
113
- validate: buildId => validateBuildId(buildId, deployedBuildId, latestBuild.buildId, projectName, targetAccountId),
114
- });
115
- buildIdToDeploy = deployBuildIdPromptResponse.buildId;
93
+ if (deployLatestBuildOption) {
94
+ buildIdToDeploy = latestBuild.buildId;
95
+ }
96
+ else {
97
+ const deployBuildIdPromptResponse = await (0, promptUtils_1.promptUser)({
98
+ name: 'buildId',
99
+ message: en_1.commands.project.deploy.deployBuildIdPrompt,
100
+ default: latestBuild.buildId === deployedBuildId
101
+ ? undefined
102
+ : latestBuild.buildId,
103
+ validate: buildId => validateBuildId(buildId, deployedBuildId, latestBuild.buildId, projectName, targetAccountId),
104
+ });
105
+ buildIdToDeploy = deployBuildIdPromptResponse.buildId;
106
+ }
116
107
  }
117
108
  if (!buildIdToDeploy) {
118
- logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.noBuildId`));
109
+ logger_1.uiLogger.error(en_1.commands.project.deploy.errors.noBuildId);
119
110
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
120
111
  }
121
112
  const { data: deployResp } = await (0, projects_1.deployProject)(targetAccountId, projectName, buildIdToDeploy, (0, buildAndDeploy_1.useV3Api)(projectConfig?.platformVersion), forceOption);
122
- if (!deployResp) {
123
- logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.deploy`));
113
+ if (!deployResp || deployResp.buildResultType !== 'DEPLOY_QUEUED') {
114
+ logger_1.uiLogger.error(en_1.commands.project.deploy.errors.deploy);
124
115
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
125
116
  }
126
- await (0, buildAndDeploy_2.pollDeployStatus)(targetAccountId, projectName, Number(deployResp.id), buildIdToDeploy);
117
+ else if (formatOutputAsJson) {
118
+ jsonOutput.deployId = Number(deployResp.id);
119
+ }
120
+ const deployResult = await (0, buildAndDeploy_2.pollDeployStatus)(targetAccountId, projectName, Number(deployResp.id), buildIdToDeploy);
121
+ if (deployResult.status === constants_1.PROJECT_DEPLOY_TEXT.STATES.SUCCESS) {
122
+ deploySuccess = true;
123
+ }
127
124
  }
128
125
  catch (e) {
129
126
  if ((0, index_1.isHubSpotHttpError)(e) && e.status === 404) {
130
- logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.deploy.errors.projectNotFound`, {
131
- projectName: chalk_1.default.bold(projectName),
132
- accountIdentifier: (0, ui_2.uiAccountDescription)(targetAccountId),
133
- command: (0, ui_2.uiCommandReference)('hs project upload'),
134
- }));
127
+ logger_1.uiLogger.error(en_1.commands.project.deploy.errors.projectNotFound(targetAccountId, projectName));
135
128
  }
136
129
  else if ((0, index_1.isHubSpotHttpError)(e) && e.status === 400) {
137
130
  if (e.data?.message && e.data?.errors) {
138
131
  logDeployErrors(e.data);
139
132
  }
140
133
  else {
141
- logger_1.logger.error(e.message);
134
+ logger_1.uiLogger.error(e.message);
142
135
  }
143
136
  }
144
137
  else {
@@ -149,27 +142,42 @@ async function handler(args) {
149
142
  }
150
143
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
151
144
  }
145
+ if (formatOutputAsJson) {
146
+ logger_1.uiLogger.json(jsonOutput);
147
+ }
148
+ if (deploySuccess) {
149
+ process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
150
+ }
151
+ else {
152
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
153
+ }
152
154
  }
153
155
  function projectDeployBuilder(yargs) {
154
156
  yargs.options({
155
157
  project: {
156
- describe: (0, lang_1.i18n)(`commands.project.subcommands.deploy.options.project.describe`),
158
+ describe: en_1.commands.project.deploy.options.project,
157
159
  type: 'string',
158
160
  },
159
161
  build: {
160
162
  alias: ['build-id'],
161
- describe: (0, lang_1.i18n)(`commands.project.subcommands.deploy.options.build.describe`),
163
+ describe: en_1.commands.project.deploy.options.build,
162
164
  type: 'number',
163
165
  },
166
+ deployLatestBuild: {
167
+ alias: ['deploy-latest-build'],
168
+ describe: en_1.commands.project.deploy.options.deployLatestBuild,
169
+ default: false,
170
+ type: 'boolean',
171
+ },
164
172
  profile: {
165
173
  alias: ['p'],
166
- describe: (0, lang_1.i18n)(`commands.project.subcommands.deploy.options.profile.describe`),
174
+ describe: en_1.commands.project.deploy.options.profile,
167
175
  type: 'string',
168
176
  hidden: true,
169
177
  },
170
178
  force: {
171
179
  alias: ['f'],
172
- describe: (0, lang_1.i18n)(`commands.project.subcommands.deploy.options.force.describe`),
180
+ describe: en_1.commands.project.deploy.options.force,
173
181
  default: false,
174
182
  type: 'boolean',
175
183
  },
@@ -177,13 +185,10 @@ function projectDeployBuilder(yargs) {
177
185
  yargs.conflicts('profile', 'project');
178
186
  yargs.conflicts('profile', 'account');
179
187
  yargs.example([
180
- [
181
- '$0 project deploy',
182
- (0, lang_1.i18n)(`commands.project.subcommands.deploy.examples.default`),
183
- ],
188
+ ['$0 project deploy', en_1.commands.project.deploy.examples.default],
184
189
  [
185
190
  '$0 project deploy --project="my-project" --build=5',
186
- (0, lang_1.i18n)(`commands.project.subcommands.deploy.examples.withOptions`),
191
+ en_1.commands.project.deploy.examples.withOptions,
187
192
  ],
188
193
  ]);
189
194
  return yargs;
@@ -193,6 +198,7 @@ const builder = (0, yargsUtils_1.makeYargsBuilder)(projectDeployBuilder, command
193
198
  useConfigOptions: true,
194
199
  useAccountOptions: true,
195
200
  useEnvironmentOptions: true,
201
+ useJSONOutputOptions: true,
196
202
  });
197
203
  const projectDeployCommand = {
198
204
  command,
@@ -64,11 +64,12 @@ async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTar
64
64
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
65
65
  }
66
66
  let targetTestingAccountId = providedTargetTestingAccountId;
67
- if (profileConfig) {
68
- // Bypass the prompt for the testing account if the user has a profile configured
69
- targetTestingAccountId = profileConfig.accountId;
70
- }
71
- else if (
67
+ // Temporarily removing logic to use profile account as testing account
68
+ // if (profileConfig) {
69
+ // // Bypass the prompt for the testing account if the user has a profile configured
70
+ // targetTestingAccountId = profileConfig.accountId;
71
+ // } else
72
+ if (
72
73
  // Bypass the prompt for the testing account if default account is already a test account
73
74
  !targetTestingAccountId &&
74
75
  targetProjectAccountIsTestAccountOrSandbox) {
@@ -93,7 +94,7 @@ async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTar
93
94
  }
94
95
  else if (devAccountPromptResponse.createNestedAccount) {
95
96
  // Create a new developer test account and automatically add it to the CLI config
96
- targetTestingAccountId = await (0, helpers_1.createDeveloperTestAccountForLocalDev)(targetProjectAccountId, targetProjectAccountConfig, env);
97
+ targetTestingAccountId = await (0, helpers_1.createDeveloperTestAccountForLocalDev)(targetProjectAccountId, targetProjectAccountConfig, env, true);
97
98
  }
98
99
  }
99
100
  else if (accountType === config_1.HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX) {
@@ -29,9 +29,6 @@ describe('commands/testAccount/createConfig', () => {
29
29
  expect(optionSpy).toHaveBeenCalledWith('description', expect.objectContaining({
30
30
  type: 'string',
31
31
  }));
32
- expect(optionSpy).toHaveBeenCalledWith('tiers', expect.objectContaining({
33
- type: 'array',
34
- }));
35
32
  expect(optionSpy).toHaveBeenCalledWith('path', expect.objectContaining({
36
33
  type: 'string',
37
34
  }));
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_extra_1 = __importDefault(require("fs-extra"));
7
7
  const path_1 = __importDefault(require("path"));
8
- const developerTestAccounts_1 = require("@hubspot/local-dev-lib/api/developerTestAccounts");
9
8
  const path_2 = require("@hubspot/local-dev-lib/path");
10
9
  const yargsUtils_1 = require("../../lib/yargsUtils");
11
10
  const promptUtils_1 = require("../../lib/prompts/promptUtils");
@@ -16,8 +15,8 @@ const validation_1 = require("../../lib/validation");
16
15
  const en_1 = require("../../lang/en");
17
16
  const createDeveloperTestAccountConfigPrompt_1 = require("../../lib/prompts/createDeveloperTestAccountConfigPrompt");
18
17
  const errorHandlers_1 = require("../../lib/errorHandlers");
19
- const polling_1 = require("../../lib/polling");
20
18
  const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
19
+ const buildAccount_1 = require("../../lib/buildAccount");
21
20
  const command = 'create';
22
21
  const describe = en_1.commands.testAccount.create.describe;
23
22
  async function handler(args) {
@@ -73,36 +72,27 @@ async function handler(args) {
73
72
  text: en_1.commands.testAccount.create.polling.start(testAccountConfig.accountName),
74
73
  });
75
74
  try {
76
- const { data } = await (0, developerTestAccounts_1.createDeveloperTestAccount)(derivedAccountId, testAccountConfig);
75
+ const result = await (0, buildAccount_1.createDeveloperTestAccountV3)(derivedAccountId, testAccountConfig);
77
76
  if (formatOutputAsJson) {
78
- jsonOutput.accountName = data.accountName;
79
- jsonOutput.accountId = data.id;
80
- jsonOutput.personalAccessKey = data.personalAccessKey;
77
+ jsonOutput.accountName = result.accountName;
78
+ jsonOutput.accountId = result.accountId;
79
+ jsonOutput.personalAccessKey = result.personalAccessKey;
81
80
  }
82
- testAccountId = data.id;
81
+ testAccountId = result.accountId;
83
82
  }
84
83
  catch (err) {
85
- (0, errorHandlers_1.logError)(err);
86
- process.exit(exitCodes_1.EXIT_CODES.ERROR);
87
- }
88
- SpinniesManager_1.default.update('createTestAccount', {
89
- text: en_1.commands.testAccount.create.polling.syncing,
90
- });
91
- try {
92
- await (0, polling_1.poll)(() => (0, developerTestAccounts_1.fetchDeveloperTestAccountGateSyncStatus)(derivedAccountId, testAccountId), {
93
- successStates: ['SUCCESS'],
94
- errorStates: [],
95
- });
96
- SpinniesManager_1.default.succeed('createTestAccount', {
97
- text: en_1.commands.testAccount.create.polling.success(testAccountConfig.accountName, testAccountId),
84
+ SpinniesManager_1.default.fail('createTestAccount', {
85
+ text: en_1.commands.testAccount.create.polling.createFailure,
98
86
  });
99
- }
100
- catch (err) {
101
- (0, errorHandlers_1.debugError)(err);
87
+ (0, errorHandlers_1.logError)(err);
102
88
  SpinniesManager_1.default.fail('createTestAccount', {
103
- text: en_1.commands.testAccount.create.polling.failure,
89
+ text: en_1.commands.testAccount.create.polling.createFailure,
104
90
  });
91
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
105
92
  }
93
+ SpinniesManager_1.default.succeed('createTestAccount', {
94
+ text: en_1.commands.testAccount.create.polling.success(testAccountConfig.accountName, testAccountId),
95
+ });
106
96
  if (formatOutputAsJson) {
107
97
  logger_1.uiLogger.json(jsonOutput);
108
98
  }
@@ -1,9 +1,7 @@
1
1
  import { CommonArgs, YargsCommandModule } from '../../types/Yargs';
2
- import { HubConfig } from '../../lib/prompts/createDeveloperTestAccountConfigPrompt';
3
2
  type CreateTestAccountConfigArgs = CommonArgs & {
4
3
  name?: string;
5
4
  description?: string;
6
- tiers?: HubConfig[];
7
5
  path?: string;
8
6
  };
9
7
  declare const createTestAccountConfigCommand: YargsCommandModule<unknown, CreateTestAccountConfigArgs>;
@@ -17,20 +17,20 @@ const validation_1 = require("../../lib/validation");
17
17
  const command = 'create-config';
18
18
  const describe = en_1.commands.testAccount.createConfig.describe;
19
19
  async function handler(args) {
20
- const { derivedAccountId, name, tiers, description, path: configPath } = args;
20
+ const { derivedAccountId, name, description, path: configPath } = args;
21
21
  (0, usageTracking_1.trackCommandUsage)('test-account-create-config', {}, derivedAccountId);
22
22
  let accountConfigPath = configPath;
23
23
  const testAccountConfig = await (0, createDeveloperTestAccountConfigPrompt_1.createDeveloperTestAccountConfigPrompt)({
24
24
  name,
25
25
  description,
26
- tiers,
27
26
  });
28
27
  if (!accountConfigPath) {
29
28
  const pathPromptResult = await (0, promptUtils_1.promptUser)({
30
29
  name: 'path',
31
30
  message: en_1.commands.testAccount.createConfig.pathPrompt,
32
31
  type: 'input',
33
- default: 'test-account-config.json',
32
+ default: testAccountConfig.accountName.toLowerCase().replace(/\s+/g, '-') +
33
+ '.json',
34
34
  validate: path => {
35
35
  if (!path) {
36
36
  return en_1.commands.testAccount.createConfig.errors.pathError;
@@ -38,6 +38,9 @@ async function handler(args) {
38
38
  else if (!path.endsWith('.json')) {
39
39
  return en_1.commands.testAccount.createConfig.errors.pathFormatError;
40
40
  }
41
+ else if ((0, validation_1.fileExists)(path)) {
42
+ return en_1.commands.testAccount.createConfig.errors.pathExistsError;
43
+ }
41
44
  return true;
42
45
  },
43
46
  });
@@ -70,17 +73,13 @@ function createTestAccountConfigBuilder(yargs) {
70
73
  type: 'string',
71
74
  description: en_1.commands.testAccount.createConfig.options.description,
72
75
  });
73
- yargs.option('tiers', {
74
- type: 'array',
75
- description: en_1.commands.testAccount.createConfig.options.tiers,
76
- });
77
76
  yargs.option('path', {
78
77
  type: 'string',
79
78
  description: en_1.commands.testAccount.createConfig.options.path,
80
79
  });
81
80
  yargs.example([
82
81
  [
83
- '$0 create-config --name my-account',
82
+ '$0 test-account create-config --name my-account',
84
83
  en_1.commands.testAccount.createConfig.example('my-account'),
85
84
  ],
86
85
  ]);
package/lang/en.d.ts CHANGED
@@ -36,7 +36,6 @@ export declare const commands: {
36
36
  readonly app: "App";
37
37
  readonly cms: "CMS";
38
38
  };
39
- readonly installDependencies: "Would you like to install dependencies now?";
40
39
  readonly uploadProject: "Would you like to upload your project to HubSpot now?";
41
40
  readonly projectCreated: {
42
41
  readonly title: string;
@@ -49,7 +48,6 @@ You can use ${string} to ${string} and ${string} to ${string} your project.`;
49
48
  Projects are what you can use to create apps, themes, and more at HubSpot.
50
49
  Usually you'll use the ${string} command, but we'll go ahead and make one now.`;
51
50
  readonly dependenciesInstalled: "Dependencies installed successfully.";
52
- readonly dependenciesNotInstalled: `Dependencies not installed. Remember to do this later with the command ${string} from the project directory.`;
53
51
  readonly uploadingProject: "Uploading your project to HubSpot...";
54
52
  readonly uploadSuccess: "Project uploaded successfully!";
55
53
  readonly developerOverviewLink: "Open this link to navigate to your HubSpot developer portal";
@@ -1144,16 +1142,16 @@ ${string}`;
1144
1142
  readonly creatingComponent: (projectName: string) => string;
1145
1143
  readonly success: (componentName: string, multiple?: boolean) => string;
1146
1144
  readonly error: {
1147
- readonly failedToDownloadComponent: "Failed to download project component. Please try again later.";
1145
+ readonly failedToDownloadComponent: "Failed to download project. Please try again later.";
1148
1146
  readonly maxExceeded: (maxCount: number) => string;
1149
1147
  readonly authTypeNotAllowed: (authType: string) => string;
1150
1148
  readonly distributionNotAllowed: (dist: string) => string;
1151
1149
  readonly locationInProject: "This command must be run from within a project directory.";
1152
- readonly failedToFetchComponentList: "Failed to fetch the list of available components. Please try again later.";
1150
+ readonly failedToFetchComponentList: "Failed to fetch the list of available features. Please try again later.";
1153
1151
  readonly projectContainsPublicApp: "This project contains a public app. This command is currently only compatible with projects that contain private apps.";
1154
1152
  };
1155
1153
  readonly examples: {
1156
- readonly default: "Create a component within your project";
1154
+ readonly default: "Create an app feature within your project";
1157
1155
  readonly withFlags: "Use --name and --type flags to bypass the prompt.";
1158
1156
  };
1159
1157
  };
@@ -1164,25 +1162,24 @@ ${string}`;
1164
1162
  readonly deploying: (path: string) => string;
1165
1163
  };
1166
1164
  readonly errors: {
1167
- readonly deploy: (details: string) => string;
1165
+ readonly deploy: "Deploy error: an unknown error occurred.";
1168
1166
  readonly noBuilds: "Deploy error: no builds for this project were found.";
1169
1167
  readonly noBuildId: "You must specify a build to deploy";
1170
- readonly projectNotFound: (projectName: string, accountIdentifier: string, command: string) => string;
1171
- readonly buildIdDoesNotExist: (buildId: string, projectName: string, linkToProject: string) => string;
1172
- readonly buildAlreadyDeployed: (buildId: string, linkToProject: string) => string;
1173
- readonly viewProjectsBuilds: "View project builds in HubSpot";
1168
+ readonly projectNotFound: (accountId: number, projectName: string) => string;
1169
+ readonly buildIdDoesNotExist: (accountId: number, buildId: number, projectName: string) => string;
1170
+ readonly buildAlreadyDeployed: (accountId: number, buildId: number, projectName: string) => string;
1171
+ readonly deployContainsRemovals: (componentName: string) => string;
1174
1172
  };
1175
1173
  readonly examples: {
1176
1174
  readonly default: "Deploy the latest build of the current project";
1177
1175
  readonly withOptions: "Deploy build 5 of the project my-project";
1178
1176
  };
1179
1177
  readonly options: {
1180
- readonly build: {
1181
- readonly describe: "Project build ID to be deployed";
1182
- };
1183
- readonly project: {
1184
- readonly describe: "Project name";
1185
- };
1178
+ readonly build: "Project build ID to be deployed";
1179
+ readonly project: "Project name";
1180
+ readonly profile: "The profile to target with this deploy";
1181
+ readonly force: "Skip warnings and force deploy. Use this carefully as it will bypass warnings for destructive actions.";
1182
+ readonly deployLatestBuild: "Deploy the latest build of the current project";
1186
1183
  };
1187
1184
  };
1188
1185
  readonly listBuilds: {
@@ -1503,6 +1500,28 @@ ${string}`;
1503
1500
  readonly app: {
1504
1501
  readonly describe: "Commands for managing apps.";
1505
1502
  readonly subcommands: {
1503
+ readonly install: {
1504
+ readonly describe: "Install an OAuth app into a test account.";
1505
+ readonly options: {
1506
+ readonly appUid: "The uid of the app to install";
1507
+ readonly projectName: "The name of the project that contains the app";
1508
+ };
1509
+ readonly positionals: {
1510
+ readonly testAccountId: "The id of the test account to install the app into";
1511
+ };
1512
+ readonly errors: {
1513
+ readonly mustSpecifyProjectName: `You must specify a project name. Use the ${string} flag to specify the project name or run this command from within a project directory.`;
1514
+ readonly noAppUidFound: `No app uid found. Please specify the app uid with the ${string} flag or run this command from within a project that contains an app.`;
1515
+ readonly appMustBeOauth: "This command only supports installing oauth apps. Please specify an app with oauth auth type.";
1516
+ };
1517
+ readonly polling: {
1518
+ readonly start: "Installing app...";
1519
+ readonly success: "App installed successfully";
1520
+ readonly failure: "App installation failed";
1521
+ readonly error: "Error installing app";
1522
+ };
1523
+ readonly example: "Install the app with uid my-app-uid from the project named \"my-project\" into the target account with id 1234567890";
1524
+ };
1506
1525
  readonly secret: {
1507
1526
  readonly describe: "Commands for managing secrets.";
1508
1527
  readonly subcommands: {
@@ -1812,7 +1831,7 @@ ${string}`;
1812
1831
  readonly start: (testAccountName: string) => string;
1813
1832
  readonly syncing: "Test account created! Syncing account data... (may take a few minutes - you can exit and the sync will continue)";
1814
1833
  readonly success: (testAccountName: string, testAccountId: number) => string;
1815
- readonly failure: "Failed to sync data into test account. The account may not be ready to use.";
1834
+ readonly createFailure: "Failed to create test account.";
1816
1835
  };
1817
1836
  readonly options: {
1818
1837
  readonly configPath: "The path to the test account config";
@@ -1821,7 +1840,7 @@ ${string}`;
1821
1840
  };
1822
1841
  readonly createConfig: {
1823
1842
  readonly describe: "Create a test account config file.";
1824
- readonly pathPrompt: "[--path] What is the path to the test account config?";
1843
+ readonly pathPrompt: "[--path] Enter the name of the Test Account config file: ";
1825
1844
  readonly errors: {
1826
1845
  readonly pathError: "Path is required";
1827
1846
  readonly pathFormatError: "Path must end with .json";
@@ -1834,7 +1853,6 @@ ${string}`;
1834
1853
  readonly options: {
1835
1854
  readonly name: "The name of the test account";
1836
1855
  readonly description: "The description of the test account";
1837
- readonly tiers: "The tiers of the test account";
1838
1856
  readonly path: "The path to the test account config";
1839
1857
  };
1840
1858
  readonly example: (name: string) => string;
@@ -2764,6 +2782,12 @@ Run ${string} to upgrade to version ${string}`;
2764
2782
  readonly noLogsFound: "No logs found.";
2765
2783
  };
2766
2784
  };
2785
+ readonly buildAccount: {
2786
+ readonly createDeveloperTestAccountV3: {
2787
+ readonly syncFailure: "Failed to sync developer test account";
2788
+ readonly pakFailure: "Failed to generate personal access key for developer test account";
2789
+ };
2790
+ };
2767
2791
  readonly configOptions: {
2768
2792
  readonly enableOrDisableBooleanFieldPrompt: {
2769
2793
  readonly message: (fieldName: string) => string;
@@ -2846,11 +2870,25 @@ Run ${string} to upgrade to version ${string}`;
2846
2870
  readonly keepingCurrentDefault: (accountName: string) => string;
2847
2871
  };
2848
2872
  readonly createDeveloperTestAccountConfigPrompt: {
2849
- readonly namePrompt: "[--name] What is the name of the test account?";
2850
- readonly descriptionPrompt: "[--description] What is the description of the test account?";
2851
- readonly tiersPrompt: "[--tiers] Which product tiers should the test account have?";
2873
+ readonly namePrompt: (withFlag?: boolean) => string;
2874
+ readonly descriptionPrompt: (withFlag?: boolean) => string;
2875
+ readonly useDefaultAccountLevelsPrompt: {
2876
+ readonly message: "Would you like to create a default Test Account, or customize your own?";
2877
+ readonly default: "Default (All Hubs, ENTERPRISE)";
2878
+ readonly manual: "Customize my own";
2879
+ };
2880
+ readonly tiersPrompt: "Select an option per hub to customize tiers. If left blank, default is ENTERPRISE";
2881
+ readonly hubTypes: {
2882
+ readonly marketing: "Marketing";
2883
+ readonly ops: "Ops";
2884
+ readonly service: "Service";
2885
+ readonly sales: "Sales";
2886
+ readonly content: "Content";
2887
+ };
2852
2888
  readonly errors: {
2889
+ readonly allHubsRequired: "Select a tier for each hub";
2853
2890
  readonly tiersError: "Cannot have more than one tier per hub";
2891
+ readonly nameRequired: "The name may not be blank. Please add a name for the Test Account.";
2854
2892
  };
2855
2893
  };
2856
2894
  readonly accountNamePrompt: {
@@ -2973,7 +3011,7 @@ Run ${string} to upgrade to version ${string}`;
2973
3011
  };
2974
3012
  };
2975
3013
  readonly projectAddPrompt: {
2976
- readonly selectType: "[--type] Select a component to add: ";
3014
+ readonly selectType: "[--type] Select an app feature to add: ";
2977
3015
  readonly enterName: "[--name] Give your component a name: ";
2978
3016
  readonly errors: {
2979
3017
  readonly nameRequired: "A component name is required";