@hubspot/cli 8.11.0-beta.0 → 8.12.0

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 (57) hide show
  1. package/commands/account/clean.js +1 -1
  2. package/commands/account/list.js +1 -1
  3. package/commands/account/remove.js +1 -1
  4. package/commands/account/rename.js +1 -1
  5. package/commands/account/use.js +1 -1
  6. package/commands/api.d.ts +4 -1
  7. package/commands/api.js +11 -14
  8. package/commands/project/appInstallStatus.d.ts +2 -1
  9. package/commands/project/appInstallStatus.js +19 -17
  10. package/commands/project/create.js +0 -1
  11. package/commands/project/deploy.d.ts +2 -1
  12. package/commands/project/deploy.js +31 -14
  13. package/commands/project/dev/index.js +18 -64
  14. package/commands/project/info.d.ts +2 -1
  15. package/commands/project/info.js +8 -6
  16. package/commands/project/installApp.d.ts +2 -1
  17. package/commands/project/installApp.js +25 -26
  18. package/commands/project/list.js +1 -1
  19. package/commands/project/release/create.d.ts +2 -1
  20. package/commands/project/release/create.js +68 -69
  21. package/commands/project/release/info.d.ts +2 -1
  22. package/commands/project/release/info.js +7 -6
  23. package/commands/project/release/list.d.ts +2 -1
  24. package/commands/project/release/list.js +14 -6
  25. package/commands/project/upload.d.ts +2 -1
  26. package/commands/project/upload.js +23 -20
  27. package/commands/project.js +2 -2
  28. package/commands/testAccount/create.d.ts +2 -1
  29. package/commands/testAccount/create.js +7 -7
  30. package/lang/en.d.ts +21 -28
  31. package/lang/en.js +30 -37
  32. package/lib/commonOpts.js +6 -1
  33. package/lib/constants.d.ts +1 -0
  34. package/lib/constants.js +1 -0
  35. package/lib/jsonOutput.d.ts +109 -0
  36. package/lib/jsonOutput.js +94 -0
  37. package/lib/projects/builds.d.ts +2 -0
  38. package/lib/projects/builds.js +22 -0
  39. package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
  40. package/lib/projects/localDev/DevSessionManager.js +4 -30
  41. package/lib/projects/localDev/helpers/account.d.ts +0 -7
  42. package/lib/projects/localDev/helpers/account.js +1 -80
  43. package/lib/projects/release.d.ts +4 -0
  44. package/lib/projects/release.js +90 -0
  45. package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
  46. package/lib/yargs/makeWrappedYargsHandler.js +123 -65
  47. package/mcp-server/Tool.js +32 -26
  48. package/mcp-server/utils/logger.d.ts +3 -0
  49. package/mcp-server/utils/logger.js +30 -0
  50. package/package.json +10 -8
  51. package/types/Yargs.d.ts +3 -1
  52. package/commands/project/dev/deprecatedFlow.d.ts +0 -11
  53. package/commands/project/dev/deprecatedFlow.js +0 -180
  54. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
  55. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
  56. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
  57. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +0 -394
@@ -120,7 +120,7 @@ const builder = makeYargsBuilder(accountCleanBuilder, command, describe, {
120
120
  const accountCleanCommand = {
121
121
  command,
122
122
  describe,
123
- handler: makeWrappedYargsHandler('accounts-clean', handler),
123
+ handler: makeWrappedYargsHandler('account-clean', handler),
124
124
  builder,
125
125
  };
126
126
  export default accountCleanCommand;
@@ -57,7 +57,7 @@ const builder = makeYargsBuilder(accountListBuilder, command, describe, {
57
57
  const accountListCommand = {
58
58
  command,
59
59
  describe,
60
- handler: makeWrappedYargsHandler('accounts-list', handler),
60
+ handler: makeWrappedYargsHandler('account-list', handler),
61
61
  builder,
62
62
  };
63
63
  export default accountListCommand;
@@ -82,7 +82,7 @@ const builder = makeYargsBuilder(accountRemoveBuilder, command, describe, {
82
82
  const accountRemoveCommand = {
83
83
  command,
84
84
  describe,
85
- handler: makeWrappedYargsHandler('accounts-remove', handler),
85
+ handler: makeWrappedYargsHandler('account-remove', handler),
86
86
  builder,
87
87
  };
88
88
  export default accountRemoveCommand;
@@ -44,7 +44,7 @@ const builder = makeYargsBuilder(accountRenameBuilder, command, describe, {
44
44
  const accountRenameCommand = {
45
45
  command,
46
46
  describe,
47
- handler: makeWrappedYargsHandler('accounts-rename', handler),
47
+ handler: makeWrappedYargsHandler('account-rename', handler),
48
48
  builder,
49
49
  };
50
50
  export default accountRenameCommand;
@@ -146,7 +146,7 @@ const builder = makeYargsBuilder(accountUseBuilder, command, describe, {
146
146
  const accountUseCommand = {
147
147
  command,
148
148
  describe,
149
- handler: makeWrappedYargsHandler('accounts-use', handler),
149
+ handler: makeWrappedYargsHandler('account-use', handler),
150
150
  builder,
151
151
  };
152
152
  export default accountUseCommand;
package/commands/api.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { CommonArgs, ConfigArgs, EnvironmentArgs, AccountArgs, JSONOutputArgs, YargsCommandModule } from '../types/Yargs.js';
2
2
  declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
3
3
  type HttpMethod = (typeof HTTP_METHODS)[number];
4
- export type ApiArgs = CommonArgs & ConfigArgs & EnvironmentArgs & AccountArgs & JSONOutputArgs & {
4
+ type JSONValue = string | number | boolean | null | {
5
+ [key: string]: JSONValue;
6
+ } | Array<JSONValue>;
7
+ export type ApiArgs = CommonArgs & ConfigArgs & EnvironmentArgs & AccountArgs & JSONOutputArgs<Record<string, JSONValue>> & {
5
8
  endpoint: string;
6
9
  method?: HttpMethod;
7
10
  data?: string;
package/commands/api.js CHANGED
@@ -29,7 +29,7 @@ function normalizeEndpoint(endpoint) {
29
29
  return endpoint.startsWith('/') ? endpoint.slice(1) : endpoint;
30
30
  }
31
31
  async function handler(args) {
32
- const { endpoint, data, derivedAccountId, json: formatOutputAsJson, exit, addUsageMetadata, } = args;
32
+ const { endpoint, data, derivedAccountId, json: formatOutputAsJson, exit, addUsageMetadata, addJsonOutput, } = args;
33
33
  const method = resolveMethod(args);
34
34
  addUsageMetadata({ action: method });
35
35
  let parsedData;
@@ -79,10 +79,8 @@ async function handler(args) {
79
79
  }
80
80
  if (response !== undefined) {
81
81
  const responseData = response.data;
82
- if (formatOutputAsJson) {
83
- uiLogger.json(responseData);
84
- }
85
- else {
82
+ addJsonOutput(responseData);
83
+ if (!formatOutputAsJson) {
86
84
  uiLogger.log(commands.api.responseLog);
87
85
  uiLogger.log(JSON.stringify(responseData, null, 2));
88
86
  }
@@ -99,20 +97,19 @@ async function handler(args) {
99
97
  }
100
98
  debugError(error, errorContext);
101
99
  const errorData = error.data;
102
- if (formatOutputAsJson && errorData) {
103
- uiLogger.json(errorData);
100
+ if (errorData) {
101
+ addJsonOutput(errorData);
104
102
  }
105
- else if (errorData) {
103
+ if (!formatOutputAsJson) {
106
104
  if (error.status && error.statusText) {
107
105
  uiLogger.error(commands.api.errors.statusLine(error.status, error.statusText));
108
106
  }
109
- uiLogger.log(JSON.stringify(errorData, null, 2));
110
- }
111
- else {
112
- if (error.status && error.statusText) {
113
- uiLogger.error(commands.api.errors.statusLine(error.status, error.statusText));
107
+ if (errorData) {
108
+ uiLogger.log(JSON.stringify(errorData, null, 2));
109
+ }
110
+ else {
111
+ uiLogger.error(error.message);
114
112
  }
115
- uiLogger.error(error.message);
116
113
  }
117
114
  return exit(EXIT_CODES.ERROR);
118
115
  }
@@ -1,4 +1,5 @@
1
1
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- export type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
2
+ import { InstallStatusJsonOutput } from '../../lib/jsonOutput.js';
3
+ export type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<InstallStatusJsonOutput>;
3
4
  declare const projectInstallStatusCommand: YargsCommandModule<unknown, ProjectInstallStatusArgs>;
4
5
  export default projectInstallStatusCommand;
@@ -5,6 +5,7 @@ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
5
5
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
6
6
  import { translateForLocalDev } from '@hubspot/project-parsing-lib/translate';
7
7
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
8
+ import { InstallStatusSchema, } from '../../lib/jsonOutput.js';
8
9
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
10
  import { uiLogger } from '../../lib/ui/logger.js';
10
11
  import { ApiErrorContext, debugError, logError, } from '../../lib/errorHandlers/index.js';
@@ -16,7 +17,7 @@ import { APP_AUTH_TYPES } from '../../lib/constants.js';
16
17
  const command = 'app-install-status';
17
18
  const describe = commands.project.installStatus.describe;
18
19
  async function handler(args) {
19
- const { derivedAccountId, formatOutputAsJson, exit } = args;
20
+ const { derivedAccountId, formatOutputAsJson, exit, addJsonOutput } = args;
20
21
  const { projectConfig, projectDir } = await getProjectConfig();
21
22
  if (!projectConfig || !projectDir) {
22
23
  uiLogger.error(commands.project.installStatus.errors.noProjectConfig);
@@ -80,25 +81,24 @@ async function handler(args) {
80
81
  }
81
82
  }
82
83
  const isInstalled = isInstalledWithScopeGroups || previouslyAuthorizedScopeGroups.length > 0;
84
+ addJsonOutput({
85
+ appId,
86
+ appUid: appNode.uid,
87
+ accountId: derivedAccountId,
88
+ projectId,
89
+ isInstalled,
90
+ isInstalledWithCurrentScopes: isInstalledWithScopeGroups,
91
+ previouslyAuthorizedScopeGroups,
92
+ });
83
93
  if (formatOutputAsJson) {
84
- uiLogger.json({
85
- appId,
86
- appUid: appNode.uid,
87
- accountId: derivedAccountId,
88
- projectId,
89
- isInstalled,
90
- isInstalledWithCurrentScopes: isInstalledWithScopeGroups,
91
- previouslyAuthorizedScopeGroups,
92
- });
93
94
  return exit(isInstalled ? EXIT_CODES.SUCCESS : EXIT_CODES.WARNING);
94
95
  }
96
+ if (isInstalledWithScopeGroups) {
97
+ uiLogger.success(commands.project.installStatus.success.installed(appNode.config.name, derivedAccountId));
98
+ return exit(EXIT_CODES.SUCCESS);
99
+ }
95
100
  if (isInstalled) {
96
- if (isInstalledWithScopeGroups) {
97
- uiLogger.success(commands.project.installStatus.success.installed(appNode.config.name, derivedAccountId));
98
- }
99
- else {
100
- uiLogger.success(commands.project.installStatus.success.installedWithOutdatedScopes(appNode.config.name, derivedAccountId));
101
- }
101
+ uiLogger.success(commands.project.installStatus.success.installedWithOutdatedScopes(appNode.config.name, derivedAccountId));
102
102
  return exit(EXIT_CODES.SUCCESS);
103
103
  }
104
104
  uiLogger.log(commands.project.installStatus.notInstalled(appNode.config.name, derivedAccountId));
@@ -127,7 +127,9 @@ const builder = makeYargsBuilder(projectInstallStatusBuilder, command, describe,
127
127
  const projectInstallStatusCommand = {
128
128
  command,
129
129
  describe,
130
- handler: makeWrappedYargsHandler('project-app-install-status', handler),
130
+ handler: makeWrappedYargsHandler('project-app-install-status', handler, {
131
+ jsonOutputSchema: InstallStatusSchema,
132
+ }),
131
133
  builder,
132
134
  };
133
135
  export default projectInstallStatusCommand;
@@ -133,7 +133,6 @@ function projectCreateBuilder(yargs) {
133
133
  describe: commands.project.create.options.platformVersion.describe,
134
134
  type: 'string',
135
135
  choices: [
136
- PLATFORM_VERSIONS.v2025_1,
137
136
  PLATFORM_VERSIONS.v2025_2,
138
137
  PLATFORM_VERSIONS.v2026_03_BETA,
139
138
  PLATFORM_VERSIONS.v2026_03,
@@ -1,5 +1,6 @@
1
1
  import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- export type ProjectDeployArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
2
+ import { DeployJsonOutput } from '../../lib/jsonOutput.js';
3
+ export type ProjectDeployArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<DeployJsonOutput> & {
3
4
  project?: string;
4
5
  build?: number;
5
6
  buildId?: number;
@@ -1,6 +1,6 @@
1
1
  import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
2
2
  import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
3
- import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
3
+ import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
4
4
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
5
5
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
6
6
  import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
@@ -10,19 +10,21 @@ import { promptUser } from '../../lib/prompts/promptUtils.js';
10
10
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
11
11
  import { uiLogger } from '../../lib/ui/logger.js';
12
12
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
13
+ import { DeploySchema } from '../../lib/jsonOutput.js';
13
14
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
14
15
  import { loadProfile } from '../../lib/projects/projectProfiles.js';
15
16
  import { PROJECT_DEPLOY_TEXT } from '../../lib/constants.js';
16
17
  import { commands } from '../../lang/en.js';
17
18
  import { handleProjectDeploy, validateBuildIdForDeploy, logDeployErrors, } from '../../lib/projects/deploy.js';
19
+ import { validateBuildForRelease } from '../../lib/projects/release.js';
20
+ import { getLastSuccessfulBuild } from '../../lib/projects/builds.js';
18
21
  const command = 'deploy';
19
22
  const describe = commands.project.deploy.describe;
20
23
  async function handler(args) {
21
- const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, json: formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, exit, addUsageMetadata, } = args;
24
+ const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, profile: profileOption, useEnv: useEnvOption, exit, addUsageMetadata, addJsonOutput, } = args;
22
25
  const accountConfig = getConfigAccountById(derivedAccountId);
23
26
  const accountType = accountConfig && accountConfig.accountType;
24
27
  let targetAccountId;
25
- const jsonOutput = {};
26
28
  const { projectConfig, projectDir } = await getProjectConfig();
27
29
  let isInProjectDirectory = false;
28
30
  // Validate project config, but it's valid to run this command from outside a project dir
@@ -79,16 +81,21 @@ async function handler(args) {
79
81
  }
80
82
  }
81
83
  else {
84
+ const lastSuccessfulBuild = await getLastSuccessfulBuild(targetAccountId, projectName, latestBuild);
85
+ if (!lastSuccessfulBuild) {
86
+ uiLogger.error(commands.project.deploy.errors.noSuccessfulBuilds);
87
+ return exit(EXIT_CODES.ERROR);
88
+ }
82
89
  if (deployLatestBuildOption) {
83
- buildIdToDeploy = latestBuild.buildId;
90
+ buildIdToDeploy = lastSuccessfulBuild.buildId;
84
91
  }
85
92
  else {
86
93
  const deployBuildIdPromptResponse = await promptUser({
87
94
  name: 'buildId',
88
95
  message: commands.project.deploy.deployBuildIdPrompt,
89
- default: latestBuild.buildId === deployedBuildId
96
+ default: lastSuccessfulBuild.buildId === deployedBuildId
90
97
  ? undefined
91
- : latestBuild.buildId,
98
+ : lastSuccessfulBuild.buildId,
92
99
  validate: buildId => validateBuildIdForDeploy(buildId, deployedBuildId, latestBuild.buildId, projectName, targetAccountId),
93
100
  });
94
101
  buildIdToDeploy = deployBuildIdPromptResponse.buildId;
@@ -98,22 +105,33 @@ async function handler(args) {
98
105
  uiLogger.error(commands.project.deploy.errors.noBuildId);
99
106
  return exit(EXIT_CODES.ERROR);
100
107
  }
108
+ try {
109
+ const supportsReleases = await validateBuildForRelease(targetAccountId, projectName, buildIdToDeploy);
110
+ // The deploy verb is not compatible with builds that leverage releases. Use release create instead.
111
+ if (supportsReleases) {
112
+ uiLogger.error(commands.project.deploy.errors.notSupportedForBuildVersion);
113
+ return exit(EXIT_CODES.ERROR);
114
+ }
115
+ }
116
+ catch {
117
+ return exit(EXIT_CODES.ERROR);
118
+ }
101
119
  const deployResult = await handleProjectDeploy(targetAccountId, projectName, buildIdToDeploy, isLegacyProject(projectConfig?.platformVersion), forceOption);
102
120
  if (!deployResult) {
103
121
  return exit(EXIT_CODES.ERROR);
104
122
  }
105
- else if (formatOutputAsJson) {
106
- jsonOutput.deployId = deployResult.deployId;
123
+ else {
124
+ addJsonOutput({ deployId: deployResult.deployId });
107
125
  }
108
126
  if (deployResult.status === PROJECT_DEPLOY_TEXT.STATES.SUCCESS) {
109
127
  deploySuccess = true;
110
128
  }
111
129
  }
112
130
  catch (e) {
113
- if (isHubSpotHttpError(e) && e.status === 404) {
131
+ if (isSpecifiedError(e, { statusCode: 404 })) {
114
132
  uiLogger.error(commands.project.deploy.errors.projectNotFound(targetAccountId, projectName));
115
133
  }
116
- else if (isHubSpotHttpError(e) && e.status === 400) {
134
+ else if (isSpecifiedError(e, { statusCode: 400 })) {
117
135
  if (e.data?.message && e.data?.errors) {
118
136
  logDeployErrors(e.data);
119
137
  }
@@ -129,9 +147,6 @@ async function handler(args) {
129
147
  }
130
148
  return exit(EXIT_CODES.ERROR);
131
149
  }
132
- if (formatOutputAsJson) {
133
- uiLogger.json(jsonOutput);
134
- }
135
150
  if (deploySuccess) {
136
151
  return exit(EXIT_CODES.SUCCESS);
137
152
  }
@@ -194,6 +209,8 @@ const projectDeployCommand = {
194
209
  command,
195
210
  describe,
196
211
  builder,
197
- handler: makeWrappedYargsHandler('project-deploy', handler),
212
+ handler: makeWrappedYargsHandler('project-deploy', handler, {
213
+ jsonOutputSchema: DeploySchema,
214
+ }),
198
215
  };
199
216
  export default projectDeployCommand;
@@ -3,7 +3,6 @@ import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/
3
3
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
4
4
  import { uiLine } from '../../../lib/ui/index.js';
5
5
  import { makeWrappedYargsHandler } from '../../../lib/yargs/makeWrappedYargsHandler.js';
6
- import { deprecatedProjectDevFlow } from './deprecatedFlow.js';
7
6
  import { unifiedProjectDevFlow } from './unifiedFlow.js';
8
7
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
9
8
  import { makeYargsBuilder } from '../../../lib/yargsUtils.js';
@@ -16,17 +15,8 @@ import { isPromptExitError } from '../../../lib/errors/PromptExitError.js';
16
15
  import { LOCAL_DEV_DEFAULT_PORT } from '../../../lib/constants.js';
17
16
  const command = 'dev';
18
17
  const describe = commands.project.dev.describe;
19
- function validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV2) {
20
- // Legacy projects do not support targetTestingAccount and targetProjectAccount
21
- if (testingAccount && projectAccount && !useV2) {
22
- throw new Error(commands.project.dev.errors.unsupportedAccountFlagLegacy);
23
- }
24
- if (userProvidedAccount && useV2) {
25
- throw new Error(commands.project.dev.errors.unsupportedAccountFlagV2);
26
- }
27
- }
28
18
  async function handler(args) {
29
- const { derivedAccountId, userProvidedAccount, testingAccount, projectAccount, profile: profileOption, exit, addUsageMetadata, } = args;
19
+ const { derivedAccountId, testingAccount, projectAccount, profile: profileOption, exit, addUsageMetadata, } = args;
30
20
  const { projectConfig, projectDir } = await getProjectConfig();
31
21
  try {
32
22
  validateProjectConfig(projectConfig, projectDir);
@@ -35,28 +25,18 @@ async function handler(args) {
35
25
  logError(error);
36
26
  return exit(EXIT_CODES.ERROR);
37
27
  }
38
- const useV2Projects = !isLegacyProject(projectConfig.platformVersion);
39
28
  if (!projectDir) {
40
29
  uiLogger.error(commands.project.dev.errors.noProjectConfig);
41
30
  return exit(EXIT_CODES.ERROR);
42
31
  }
43
- try {
44
- validateAccountFlags(testingAccount, projectAccount, userProvidedAccount, useV2Projects);
45
- }
46
- catch (error) {
47
- logError(error);
32
+ if (isLegacyProject(projectConfig.platformVersion)) {
33
+ uiLogger.error(commands.project.dev.errors.unsupportedPlatformVersion(projectConfig.platformVersion));
48
34
  return exit(EXIT_CODES.ERROR);
49
35
  }
50
36
  uiLogger.log(commands.project.dev.logs.header);
51
- if (useV2Projects) {
52
- uiLogger.log(commands.project.dev.logs.learnMoreMessageV2);
53
- }
54
- else {
55
- uiLogger.log(commands.project.dev.logs.learnMoreMessageLegacy);
56
- }
37
+ uiLogger.log(commands.project.dev.logs.learnMoreMessageV2);
57
38
  let targetProjectAccountId;
58
39
  let profile;
59
- // Using the new --projectAccount flag
60
40
  if (projectAccount) {
61
41
  targetProjectAccountId =
62
42
  getConfigAccountIfExists(projectAccount)?.accountId;
@@ -64,14 +44,8 @@ async function handler(args) {
64
44
  uiLogger.log('');
65
45
  uiLogger.log(commands.project.dev.logs.projectAccountFlagExplanation(targetProjectAccountId));
66
46
  }
67
- // Using the legacy --account flag
68
47
  }
69
- else if (userProvidedAccount && derivedAccountId) {
70
- targetProjectAccountId = derivedAccountId;
71
- }
72
- // Determine profile name: from flag or prompt
73
- if (!targetProjectAccountId &&
74
- !isLegacyProject(projectConfig.platformVersion)) {
48
+ if (!targetProjectAccountId) {
75
49
  const profileName = await projectProfilePrompt(projectDir, projectConfig, profileOption);
76
50
  if (profileName) {
77
51
  try {
@@ -88,36 +62,23 @@ async function handler(args) {
88
62
  }
89
63
  }
90
64
  if (!targetProjectAccountId) {
91
- // The user is not using profile or account flags, so we can use the derived accountId
92
65
  targetProjectAccountId = derivedAccountId;
93
- if (useV2Projects) {
94
- uiLogger.log('');
95
- uiLogger.log(commands.project.dev.logs.defaultProjectAccountExplanation(targetProjectAccountId));
96
- }
66
+ uiLogger.log('');
67
+ uiLogger.log(commands.project.dev.logs.defaultProjectAccountExplanation(targetProjectAccountId));
97
68
  }
98
69
  addUsageMetadata({ accountId: targetProjectAccountId ?? undefined });
99
70
  try {
100
- if (!isLegacyProject(projectConfig.platformVersion)) {
101
- const targetTestingAccountId = testingAccount
102
- ? getConfigAccountIfExists(testingAccount)?.accountId
103
- : undefined;
104
- await unifiedProjectDevFlow({
105
- args,
106
- targetProjectAccountId,
107
- providedTargetTestingAccountId: targetTestingAccountId,
108
- projectConfig,
109
- projectDir,
110
- profileConfig: profile,
111
- });
112
- }
113
- else {
114
- await deprecatedProjectDevFlow({
115
- args,
116
- accountId: targetProjectAccountId,
117
- projectConfig,
118
- projectDir,
119
- });
120
- }
71
+ const targetTestingAccountId = testingAccount
72
+ ? getConfigAccountIfExists(testingAccount)?.accountId
73
+ : undefined;
74
+ await unifiedProjectDevFlow({
75
+ args,
76
+ targetProjectAccountId,
77
+ providedTargetTestingAccountId: targetTestingAccountId,
78
+ projectConfig,
79
+ projectDir,
80
+ profileConfig: profile,
81
+ });
121
82
  }
122
83
  catch (e) {
123
84
  if (isPromptExitError(e)) {
@@ -144,19 +105,12 @@ function projectDevBuilder(yargs) {
144
105
  description: commands.project.dev.options.projectAccount,
145
106
  implies: ['testingAccount'],
146
107
  });
147
- yargs.option('account', {
148
- alias: 'a',
149
- describe: '',
150
- type: 'string',
151
- description: commands.project.dev.options.account,
152
- });
153
108
  yargs.option('port', {
154
109
  type: 'number',
155
110
  description: commands.project.dev.options.port,
156
111
  default: LOCAL_DEV_DEFAULT_PORT,
157
112
  });
158
113
  yargs.example([['$0 project dev', commands.project.dev.examples.default]]);
159
- yargs.conflicts('profile', 'account');
160
114
  yargs.conflicts('profile', 'testing-account');
161
115
  yargs.conflicts('profile', 'project-account');
162
116
  return yargs;
@@ -1,4 +1,5 @@
1
1
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- export type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
2
+ import { ProjectInfoJsonOutput } from '../../lib/jsonOutput.js';
3
+ export type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<ProjectInfoJsonOutput>;
3
4
  declare const projectInfoCommand: YargsCommandModule<unknown, ProjectInfoArgs>;
4
5
  export default projectInfoCommand;
@@ -8,11 +8,12 @@ import { commands } from '../../lang/en.js';
8
8
  import { getProjectConfig } from '../../lib/projects/config.js';
9
9
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
10
10
  import { getProjectInfo, logProjectInfo, } from '../../lib/projects/projectInfo.js';
11
+ import { ProjectInfoSchema, } from '../../lib/jsonOutput.js';
11
12
  const command = 'info';
12
13
  const describe = commands.project.info.describe;
13
14
  const verboseDescribe = commands.project.info.verboseDescribe;
14
15
  async function handler(args) {
15
- const { derivedAccountId, formatOutputAsJson, exit } = args;
16
+ const { derivedAccountId, formatOutputAsJson, exit, addJsonOutput } = args;
16
17
  const { projectConfig } = await getProjectConfig();
17
18
  if (!projectConfig) {
18
19
  uiLogger.error(commands.project.info.errors.noProjectConfig);
@@ -39,11 +40,10 @@ async function handler(args) {
39
40
  return exit(EXIT_CODES.ERROR);
40
41
  }
41
42
  const projectInfo = await getProjectInfo(project, projectConfig.platformVersion, derivedAccountId);
42
- if (formatOutputAsJson) {
43
- uiLogger.json(projectInfo);
44
- return;
43
+ addJsonOutput(projectInfo);
44
+ if (!formatOutputAsJson) {
45
+ logProjectInfo(projectInfo);
45
46
  }
46
- logProjectInfo(projectInfo);
47
47
  }
48
48
  function projectInfoBuilder(yargs) {
49
49
  yargs.example([
@@ -62,7 +62,9 @@ const builder = makeYargsBuilder(projectInfoBuilder, command, verboseDescribe, {
62
62
  const projectInfoCommand = {
63
63
  command,
64
64
  describe,
65
- handler: makeWrappedYargsHandler('project-info', handler),
65
+ handler: makeWrappedYargsHandler('project-info', handler, {
66
+ jsonOutputSchema: ProjectInfoSchema,
67
+ }),
66
68
  builder,
67
69
  };
68
70
  export default projectInfoCommand;
@@ -1,5 +1,6 @@
1
1
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- export type ProjectInstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
2
+ import { InstallAppJsonOutput } from '../../lib/jsonOutput.js';
3
+ export type ProjectInstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<InstallAppJsonOutput> & {
3
4
  force: boolean;
4
5
  profile?: string;
5
6
  };
@@ -1,6 +1,7 @@
1
1
  import { getConfigAccountIfExists } from '@hubspot/local-dev-lib/config';
2
2
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
3
3
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
4
+ import { InstallAppSchema, } from '../../lib/jsonOutput.js';
4
5
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
5
6
  import { uiLogger } from '../../lib/ui/logger.js';
6
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -13,7 +14,7 @@ const command = 'install-app';
13
14
  const describe = commands.project.installApp.describe;
14
15
  const verboseDescribe = commands.project.installApp.verboseDescribe;
15
16
  async function handler(args) {
16
- const { derivedAccountId, formatOutputAsJson, force, profile: profileOption, useEnv: useEnvOption, exit, } = args;
17
+ const { derivedAccountId, formatOutputAsJson, force, profile: profileOption, useEnv: useEnvOption, exit, addJsonOutput, } = args;
17
18
  const { projectConfig, projectDir } = await getProjectConfig();
18
19
  if (!projectConfig || !projectDir) {
19
20
  uiLogger.error(commands.project.installApp.errors.noProjectConfig);
@@ -60,18 +61,16 @@ async function handler(args) {
60
61
  const needsReinstall = !isInstalledWithScopeGroups && previouslyAuthorizedScopeGroups.length > 0;
61
62
  const installationState = getAppInstallationState(isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups);
62
63
  if (isInstalledWithScopeGroups) {
63
- if (formatOutputAsJson) {
64
- uiLogger.json({
65
- appId,
66
- appUid: appNode.uid,
67
- accountId: installAccountId,
68
- projectId,
69
- installationState,
70
- installed: true,
71
- reinstalled: false,
72
- });
73
- }
74
- else {
64
+ addJsonOutput({
65
+ appId,
66
+ appUid: appNode.uid,
67
+ accountId: installAccountId,
68
+ projectId,
69
+ installationState,
70
+ installed: true,
71
+ reinstalled: false,
72
+ });
73
+ if (!formatOutputAsJson) {
75
74
  uiLogger.success(commands.project.installApp.alreadyInstalled(appNode.config.name, installAccountId));
76
75
  }
77
76
  return exit(EXIT_CODES.SUCCESS);
@@ -117,18 +116,16 @@ async function handler(args) {
117
116
  if (!installed) {
118
117
  return exit(EXIT_CODES.ERROR);
119
118
  }
120
- if (formatOutputAsJson) {
121
- uiLogger.json({
122
- appId,
123
- appUid: appNode.uid,
124
- accountId: installAccountId,
125
- projectId,
126
- installationState: APP_INSTALLATION_STATES.INSTALLED,
127
- installed: true,
128
- reinstalled: needsReinstall,
129
- });
130
- }
131
- else {
119
+ addJsonOutput({
120
+ appId,
121
+ appUid: appNode.uid,
122
+ accountId: installAccountId,
123
+ projectId,
124
+ installationState: APP_INSTALLATION_STATES.INSTALLED,
125
+ installed: true,
126
+ reinstalled: needsReinstall,
127
+ });
128
+ if (!formatOutputAsJson) {
132
129
  uiLogger.success(commands.project.installApp.success(appNode.config.name, installAccountId));
133
130
  }
134
131
  return exit(EXIT_CODES.SUCCESS);
@@ -175,7 +172,9 @@ const builder = makeYargsBuilder(projectInstallAppBuilder, command, verboseDescr
175
172
  const projectInstallAppCommand = {
176
173
  command,
177
174
  describe,
178
- handler: makeWrappedYargsHandler('project-install-app', handler),
175
+ handler: makeWrappedYargsHandler('project-install-app', handler, {
176
+ jsonOutputSchema: InstallAppSchema,
177
+ }),
179
178
  builder,
180
179
  };
181
180
  export default projectInstallAppCommand;
@@ -57,7 +57,7 @@ const builder = makeYargsBuilder(projectListBuilder, command, describe, {
57
57
  const projectListCommand = {
58
58
  command,
59
59
  describe,
60
- handler: makeWrappedYargsHandler('projects-list', handler),
60
+ handler: makeWrappedYargsHandler('project-list', handler),
61
61
  builder,
62
62
  };
63
63
  export default projectListCommand;
@@ -1,5 +1,6 @@
1
1
  import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../../types/Yargs.js';
2
- export type ProjectReleaseCreateArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
2
+ import { ReleaseJsonOutput } from '../../../lib/jsonOutput.js';
3
+ export type ProjectReleaseCreateArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs<ReleaseJsonOutput> & {
3
4
  build?: number;
4
5
  force: boolean;
5
6
  };