@hubspot/cli 8.2.0-experimental.2 → 8.2.1-experimental.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 (147) 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/config/set.js +24 -5
  9. package/commands/customObject/createSchema.js +2 -3
  10. package/commands/customObject/updateSchema.js +2 -3
  11. package/commands/getStarted.js +1 -0
  12. package/commands/hubdb/list.d.ts +1 -1
  13. package/commands/hubdb/list.js +7 -8
  14. package/commands/mcp/setup.d.ts +2 -0
  15. package/commands/mcp/setup.js +29 -1
  16. package/commands/project/appInstallStatus.d.ts +2 -1
  17. package/commands/project/appInstallStatus.js +21 -19
  18. package/commands/project/create.js +0 -1
  19. package/commands/project/deploy.d.ts +2 -1
  20. package/commands/project/deploy.js +31 -14
  21. package/commands/project/dev/index.js +18 -64
  22. package/commands/project/dev/unifiedFlow.js +3 -1
  23. package/commands/project/info.d.ts +2 -1
  24. package/commands/project/info.js +8 -6
  25. package/commands/project/installApp.d.ts +2 -1
  26. package/commands/project/installApp.js +26 -27
  27. package/commands/project/list.js +1 -1
  28. package/commands/project/listBuilds.d.ts +1 -1
  29. package/commands/project/listBuilds.js +8 -6
  30. package/commands/project/logs.js +2 -4
  31. package/commands/project/profile/add.d.ts +2 -1
  32. package/commands/project/profile/add.js +22 -1
  33. package/commands/project/profile/delete.d.ts +1 -1
  34. package/commands/project/release/create.d.ts +2 -1
  35. package/commands/project/release/create.js +68 -69
  36. package/commands/project/release/info.d.ts +2 -1
  37. package/commands/project/release/info.js +7 -6
  38. package/commands/project/release/list.d.ts +2 -1
  39. package/commands/project/release/list.js +15 -7
  40. package/commands/project/upload.d.ts +4 -1
  41. package/commands/project/upload.js +48 -21
  42. package/commands/project/validate.d.ts +1 -1
  43. package/commands/project/watch.js +3 -2
  44. package/commands/project.js +2 -2
  45. package/commands/sandbox/delete.js +2 -3
  46. package/commands/testAccount/create.d.ts +2 -1
  47. package/commands/testAccount/create.js +7 -7
  48. package/commands/testAccount/importData.d.ts +1 -1
  49. package/lang/en.d.ts +61 -33
  50. package/lang/en.js +77 -48
  51. package/lib/app/urls.js +2 -3
  52. package/lib/commonOpts.js +6 -1
  53. package/lib/configOptions.d.ts +10 -10
  54. package/lib/configOptions.js +10 -11
  55. package/lib/constants.d.ts +2 -0
  56. package/lib/constants.js +2 -0
  57. package/lib/dependencyManagement.js +7 -7
  58. package/lib/getStartedV2Actions.js +2 -1
  59. package/lib/importData.js +3 -4
  60. package/lib/jsonOutput.d.ts +109 -0
  61. package/lib/jsonOutput.js +94 -0
  62. package/lib/links.js +6 -5
  63. package/lib/mcp/clients.d.ts +1 -1
  64. package/lib/mcp/clients.js +8 -1
  65. package/lib/mcp/setup.d.ts +9 -4
  66. package/lib/mcp/setup.js +115 -35
  67. package/lib/npm/npmCli.d.ts +1 -0
  68. package/lib/npm/npmCli.js +13 -0
  69. package/lib/projects/builds.d.ts +2 -0
  70. package/lib/projects/builds.js +22 -0
  71. package/lib/projects/create/v2.js +1 -0
  72. package/lib/projects/installApp.d.ts +1 -1
  73. package/lib/projects/installApp.js +8 -3
  74. package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
  75. package/lib/projects/localDev/DevSessionManager.js +4 -30
  76. package/lib/projects/localDev/LocalDevProcess.js +7 -5
  77. package/lib/projects/localDev/helpers/account.d.ts +0 -7
  78. package/lib/projects/localDev/helpers/account.js +1 -80
  79. package/lib/projects/localDev/helpers/project.js +3 -2
  80. package/lib/projects/release.d.ts +4 -0
  81. package/lib/projects/release.js +90 -0
  82. package/lib/projects/ui.d.ts +1 -0
  83. package/lib/projects/ui.js +14 -0
  84. package/lib/projects/upload.d.ts +10 -2
  85. package/lib/projects/upload.js +14 -7
  86. package/lib/projects/urls.d.ts +0 -1
  87. package/lib/projects/urls.js +6 -13
  88. package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
  89. package/lib/yargs/makeWrappedYargsHandler.js +123 -65
  90. package/mcp-server/Tool.d.ts +8 -3
  91. package/mcp-server/Tool.js +58 -32
  92. package/mcp-server/server.js +10 -6
  93. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
  94. package/mcp-server/tools/cms/HsCreateFunctionTool.js +10 -17
  95. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  96. package/mcp-server/tools/cms/HsCreateModuleTool.js +12 -18
  97. package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +2 -2
  98. package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -10
  99. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +2 -2
  100. package/mcp-server/tools/cms/HsFunctionLogsTool.js +9 -9
  101. package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +2 -2
  102. package/mcp-server/tools/cms/HsListFunctionsTool.js +7 -7
  103. package/mcp-server/tools/cms/HsListTool.d.ts +2 -2
  104. package/mcp-server/tools/cms/HsListTool.js +6 -10
  105. package/mcp-server/tools/index.js +2 -0
  106. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -2
  107. package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -9
  108. package/mcp-server/tools/project/AuthAccountTool.d.ts +18 -0
  109. package/mcp-server/tools/project/AuthAccountTool.js +78 -0
  110. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -2
  111. package/mcp-server/tools/project/CreateProjectTool.js +13 -12
  112. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +2 -2
  113. package/mcp-server/tools/project/CreateTestAccountTool.js +14 -15
  114. package/mcp-server/tools/project/DeployProjectTool.d.ts +2 -2
  115. package/mcp-server/tools/project/DeployProjectTool.js +10 -10
  116. package/mcp-server/tools/project/DocFetchTool.js +1 -1
  117. package/mcp-server/tools/project/DocsSearchTool.js +8 -7
  118. package/mcp-server/tools/project/FindProjectsTool.js +1 -1
  119. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +2 -1
  120. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -8
  121. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +2 -1
  122. package/mcp-server/tools/project/GetApplicationInfoTool.js +12 -9
  123. package/mcp-server/tools/project/GetBuildLogsTool.js +11 -7
  124. package/mcp-server/tools/project/GetBuildStatusTool.js +11 -7
  125. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +2 -1
  126. package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
  127. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  128. package/mcp-server/tools/project/UploadProjectTools.d.ts +2 -2
  129. package/mcp-server/tools/project/UploadProjectTools.js +9 -8
  130. package/mcp-server/tools/project/ValidateProjectTool.d.ts +2 -2
  131. package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
  132. package/mcp-server/tools/project/constants.d.ts +1 -0
  133. package/mcp-server/tools/project/constants.js +2 -1
  134. package/mcp-server/utils/command.d.ts +25 -2
  135. package/mcp-server/utils/command.js +67 -17
  136. package/mcp-server/utils/config.js +5 -0
  137. package/mcp-server/utils/logger.d.ts +3 -0
  138. package/mcp-server/utils/logger.js +30 -0
  139. package/mcp-server/utils/toolUsageTracking.js +18 -3
  140. package/package.json +11 -9
  141. package/types/Yargs.d.ts +3 -1
  142. package/commands/project/dev/deprecatedFlow.d.ts +0 -11
  143. package/commands/project/dev/deprecatedFlow.js +0 -180
  144. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
  145. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
  146. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
  147. 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
  }
@@ -2,6 +2,7 @@ import { promptUser } from '../../lib/prompts/promptUtils.js';
2
2
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
3
3
  import { setDefaultCmsPublishMode, setHttpTimeout, setAllowUsageTracking, setAllowAutoUpdates, setAutoOpenBrowser, } from '../../lib/configOptions.js';
4
4
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
5
+ import { trackCommandMetadataUsage } from '../../lib/usageTracking.js';
5
6
  import { commands } from '../../lang/en.js';
6
7
  import { makeYargsBuilder, strictEnforceBoolean, } from '../../lib/yargsUtils.js';
7
8
  import { logError } from '../../lib/errorHandlers/index.js';
@@ -30,21 +31,39 @@ async function selectOptions() {
30
31
  }
31
32
  async function handleConfigUpdate(accountId, args) {
32
33
  const { allowAutoUpdates, allowUsageTracking, defaultCmsPublishMode, httpTimeout, autoOpenBrowser, } = args;
34
+ // Emit one metadata event per setting so each field:value pair surfaces as its
35
+ // own entry in Amplitude instead of a combined string that fragments the charts.
36
+ const trackingRequests = [];
37
+ const trackAction = (action) => {
38
+ trackingRequests.push(trackCommandMetadataUsage('config-set', { action }, accountId));
39
+ };
33
40
  if (allowAutoUpdates !== undefined) {
34
- await setAllowAutoUpdates({ allowAutoUpdates, accountId });
41
+ const value = await setAllowAutoUpdates({ allowAutoUpdates, accountId });
42
+ trackAction(`allowAutoUpdates:${value}`);
35
43
  }
36
44
  if (allowUsageTracking !== undefined) {
37
- await setAllowUsageTracking({ allowUsageTracking, accountId });
45
+ const value = await setAllowUsageTracking({
46
+ allowUsageTracking,
47
+ accountId,
48
+ });
49
+ trackAction(`allowUsageTracking:${value}`);
38
50
  }
39
51
  if (autoOpenBrowser !== undefined) {
40
- await setAutoOpenBrowser({ autoOpenBrowser, accountId });
52
+ const value = await setAutoOpenBrowser({ autoOpenBrowser, accountId });
53
+ trackAction(`autoOpenBrowser:${value}`);
41
54
  }
42
55
  if (defaultCmsPublishMode !== undefined) {
43
- await setDefaultCmsPublishMode({ defaultCmsPublishMode, accountId });
56
+ const value = await setDefaultCmsPublishMode({
57
+ defaultCmsPublishMode,
58
+ accountId,
59
+ });
60
+ trackAction(`defaultCmsPublishMode:${value}`);
44
61
  }
45
62
  if (httpTimeout !== undefined) {
46
- await setHttpTimeout({ httpTimeout, accountId });
63
+ const value = await setHttpTimeout({ httpTimeout, accountId });
64
+ trackAction(`httpTimeout:${value}`);
47
65
  }
66
+ await Promise.all(trackingRequests);
48
67
  }
49
68
  async function handler(args) {
50
69
  const { derivedAccountId, allowAutoUpdates, allowUsageTracking, defaultCmsPublishMode, httpTimeout, autoOpenBrowser, exit, } = args;
@@ -1,8 +1,7 @@
1
1
  import { uiLogger } from '../../lib/ui/logger.js';
2
- import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
3
2
  import { getAbsoluteFilePath } from '@hubspot/local-dev-lib/path';
4
3
  import { createObjectSchema } from '@hubspot/local-dev-lib/api/customObjects';
5
- import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
4
+ import { getHubSpotWebsiteOriginByAccountId } from '@hubspot/local-dev-lib/urls';
6
5
  import { logError } from '../../lib/errorHandlers/index.js';
7
6
  import { checkAndConvertToJson } from '../../lib/validation.js';
8
7
  import { commands } from '../../lang/en.js';
@@ -22,7 +21,7 @@ async function handler(args) {
22
21
  }
23
22
  try {
24
23
  const { data } = await createObjectSchema(derivedAccountId, schemaJson);
25
- uiLogger.success(commands.customObject.subcommands.createSchema.success.schemaViewable(`${getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId))}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
24
+ uiLogger.success(commands.customObject.subcommands.createSchema.success.schemaViewable(`${getHubSpotWebsiteOriginByAccountId(derivedAccountId)}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
26
25
  }
27
26
  catch (e) {
28
27
  logError(e, { accountId: derivedAccountId });
@@ -1,8 +1,7 @@
1
1
  import { fetchObjectSchemas, updateObjectSchema, } from '@hubspot/local-dev-lib/api/customObjects';
2
2
  import { uiLogger } from '../../lib/ui/logger.js';
3
3
  import { getAbsoluteFilePath } from '@hubspot/local-dev-lib/path';
4
- import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
5
- import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
4
+ import { getHubSpotWebsiteOriginByAccountId } from '@hubspot/local-dev-lib/urls';
6
5
  import { listPrompt } from '../../lib/prompts/promptUtils.js';
7
6
  import { logError } from '../../lib/errorHandlers/index.js';
8
7
  import { checkAndConvertToJson } from '../../lib/validation.js';
@@ -32,7 +31,7 @@ async function handler(args) {
32
31
  choices: schemaNames,
33
32
  });
34
33
  const { data } = await updateObjectSchema(derivedAccountId, name, schemaJson);
35
- uiLogger.success(commands.customObject.subcommands.updateSchema.success.viewAtUrl(`${getHubSpotWebsiteOrigin(getConfigAccountEnvironment(derivedAccountId))}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
34
+ uiLogger.success(commands.customObject.subcommands.updateSchema.success.viewAtUrl(`${getHubSpotWebsiteOriginByAccountId(derivedAccountId)}/contacts/${derivedAccountId}/objects/${data.objectTypeId}`));
36
35
  }
37
36
  catch (e) {
38
37
  logError(e, { accountId: derivedAccountId });
@@ -207,6 +207,7 @@ async function handler(args) {
207
207
  isUploadCommand: false,
208
208
  sendIR: !isLegacyProject(newProjectConfig.platformVersion),
209
209
  skipValidation: false,
210
+ force: true,
210
211
  });
211
212
  if (uploadError) {
212
213
  // Track upload failure
@@ -1,4 +1,4 @@
1
1
  import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- type HubdbListArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs;
2
+ export type HubdbListArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs;
3
3
  declare const hubdbListCommand: YargsCommandModule<unknown, HubdbListArgs>;
4
4
  export default hubdbListCommand;
@@ -2,11 +2,12 @@ import { fetchTables } from '@hubspot/local-dev-lib/api/hubdb';
2
2
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
3
3
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
4
4
  import { uiLogger } from '../../lib/ui/logger.js';
5
+ import { uiLine } from '../../lib/ui/index.js';
5
6
  import { logError } from '../../lib/errorHandlers/index.js';
6
7
  import { commands } from '../../lang/en.js';
7
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
8
9
  import { renderTable } from '../../ui/render.js';
9
- import { getBaseHubSpotUrlForAccount } from '../../lib/projects/urls.js';
10
+ import { getHubSpotWebsiteOriginByAccountId } from '@hubspot/local-dev-lib/urls';
10
11
  const command = ['list', 'ls'];
11
12
  const describe = commands.hubdb.subcommands.list.describe;
12
13
  async function getTableData(accountId) {
@@ -44,22 +45,20 @@ async function handler(args) {
44
45
  commands.hubdb.subcommands.list.labels.rows,
45
46
  ];
46
47
  uiLogger.success(commands.hubdb.subcommands.list.success(derivedAccountId));
47
- uiLogger.log(' ');
48
- // link devs to the hubdb page in hubspot for easy access
49
- const baseUrl = getBaseHubSpotUrlForAccount(derivedAccountId);
50
- uiLogger.log(commands.hubdb.subcommands.list.viewTablesLink(baseUrl, derivedAccountId));
51
48
  // don't bother showing an empty list of tables
52
49
  if (tables.length > 0) {
50
+ uiLogger.log(commands.hubdb.subcommands.list.tables);
51
+ renderTable(tableHeader, tableUIData);
53
52
  // if truncated is 0, it will be interpreted as falsy
54
53
  const truncated = total - tables.length;
54
+ uiLine();
55
55
  uiLogger.log(commands.hubdb.subcommands.list.tablesDisplayed(tables.length, total, truncated));
56
- uiLogger.log('--------------------------------');
57
- uiLogger.log(commands.hubdb.subcommands.list.tables);
58
- renderTable(tableHeader, tableUIData);
59
56
  }
60
57
  else {
61
58
  uiLogger.log(commands.hubdb.subcommands.list.noTables(derivedAccountId));
62
59
  }
60
+ // link devs to the hubdb page in hubspot for easy access
61
+ uiLogger.log(commands.hubdb.subcommands.list.viewTablesLink(getHubSpotWebsiteOriginByAccountId(derivedAccountId), derivedAccountId));
63
62
  return exit(EXIT_CODES.SUCCESS);
64
63
  }
65
64
  function hubdbListBuilder(yargs) {
@@ -1,6 +1,8 @@
1
1
  import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
2
2
  interface MCPSetupArgs extends CommonArgs {
3
3
  client?: string[];
4
+ standalone?: boolean;
5
+ cliVersion?: string;
4
6
  }
5
7
  declare const mcpSetupCommand: YargsCommandModule<unknown, MCPSetupArgs>;
6
8
  export default mcpSetupCommand;
@@ -8,7 +8,11 @@ const describe = commands.mcp.setup.describe;
8
8
  async function handler(args) {
9
9
  const { exit } = args;
10
10
  try {
11
- await configureMcpServer(args.client);
11
+ await configureMcpServer({
12
+ targets: args.client,
13
+ standalone: args.standalone,
14
+ cliVersion: args.cliVersion,
15
+ });
12
16
  }
13
17
  catch (e) {
14
18
  return exit(EXIT_CODES.ERROR);
@@ -21,6 +25,30 @@ function setupBuilder(yargs) {
21
25
  type: 'array',
22
26
  choices: [...supportedTools.map(tool => tool.value)],
23
27
  });
28
+ yargs.option('standalone', {
29
+ describe: commands.mcp.setup.args.standalone,
30
+ type: 'boolean',
31
+ });
32
+ yargs.option('cli-version', {
33
+ describe: commands.mcp.setup.args.cliVersion,
34
+ type: 'string',
35
+ });
36
+ yargs.check(argv => {
37
+ if (argv.cliVersion !== undefined && argv.standalone !== true) {
38
+ throw new Error(commands.mcp.setup.errors.cliVersionRequiresStandalone);
39
+ }
40
+ return true;
41
+ });
42
+ yargs.example([
43
+ [
44
+ '$0 mcp setup --client claude --no-standalone',
45
+ commands.mcp.setup.examples.nonInteractive,
46
+ ],
47
+ [
48
+ '$0 mcp setup --client cursor --standalone --cli-version 8.0.1',
49
+ commands.mcp.setup.examples.standalone,
50
+ ],
51
+ ]);
24
52
  return yargs;
25
53
  }
26
54
  const builder = makeYargsBuilder(setupBuilder, command, describe, {
@@ -1,4 +1,5 @@
1
1
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
2
- 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);
@@ -28,12 +29,12 @@ async function handler(args) {
28
29
  }
29
30
  let appNode;
30
31
  try {
31
- const { intermediateNodesIndexedByUid } = await translateForLocalDev({
32
+ const { intermediateRepresentation } = await translateForLocalDev({
32
33
  projectSourceDir: path.join(projectDir, projectConfig.srcDir),
33
34
  platformVersion: projectConfig.platformVersion,
34
35
  accountId: derivedAccountId,
35
36
  }, { skipValidation: true });
36
- appNode = Object.values(intermediateNodesIndexedByUid).find(isAppIRNode);
37
+ appNode = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).find(isAppIRNode);
37
38
  }
38
39
  catch (error) {
39
40
  debugError(error);
@@ -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;