@hubspot/cli 7.10.0 → 7.11.0-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 (211) hide show
  1. package/bin/cli.js +5 -4
  2. package/commands/__tests__/getStarted.test.js +10 -0
  3. package/commands/__tests__/project.test.js +3 -0
  4. package/commands/account/__tests__/rename.test.js +10 -3
  5. package/commands/account/auth.js +10 -14
  6. package/commands/account/clean.js +11 -19
  7. package/commands/account/createOverride.js +15 -11
  8. package/commands/account/info.js +8 -5
  9. package/commands/account/list.js +15 -19
  10. package/commands/account/remove.js +23 -22
  11. package/commands/account/removeOverride.js +6 -6
  12. package/commands/account/rename.js +2 -2
  13. package/commands/account/use.js +19 -8
  14. package/commands/app/__tests__/migrate.test.js +8 -4
  15. package/commands/app/migrate.js +2 -2
  16. package/commands/auth.js +18 -14
  17. package/commands/config/migrate.js +5 -5
  18. package/commands/customObject/createSchema.js +2 -3
  19. package/commands/customObject/updateSchema.js +2 -3
  20. package/commands/getStarted.js +2 -3
  21. package/commands/hubdb/__tests__/list.test.js +1 -0
  22. package/commands/hubdb/list.js +2 -2
  23. package/commands/init.js +36 -32
  24. package/commands/project/__tests__/deploy.test.js +15 -10
  25. package/commands/project/__tests__/devUnifiedFlow.test.js +6 -4
  26. package/commands/project/__tests__/lint.test.js +709 -0
  27. package/commands/project/__tests__/logs.test.js +4 -0
  28. package/commands/project/__tests__/validate.test.js +2 -2
  29. package/commands/project/cloneApp.js +2 -2
  30. package/commands/project/create.js +20 -14
  31. package/commands/project/deploy.js +2 -2
  32. package/commands/project/dev/deprecatedFlow.js +4 -5
  33. package/commands/project/dev/index.js +6 -3
  34. package/commands/project/dev/unifiedFlow.js +11 -6
  35. package/commands/project/lint.d.ts +6 -0
  36. package/commands/project/lint.js +178 -0
  37. package/commands/project/logs.js +2 -3
  38. package/commands/project/migrate.js +4 -13
  39. package/commands/project/profile/add.js +6 -7
  40. package/commands/project/profile/delete.js +2 -2
  41. package/commands/project/upload.js +2 -2
  42. package/commands/project/validate.js +2 -2
  43. package/commands/project.js +2 -0
  44. package/commands/sandbox/__tests__/create.test.js +14 -5
  45. package/commands/sandbox/create.js +4 -5
  46. package/commands/sandbox/delete.js +23 -20
  47. package/commands/testAccount/create.js +2 -2
  48. package/commands/testAccount/delete.js +9 -8
  49. package/lang/en.d.ts +53 -12
  50. package/lang/en.js +63 -16
  51. package/lib/__tests__/buildAccount.test.js +22 -30
  52. package/lib/__tests__/commonOpts.test.js +9 -13
  53. package/lib/__tests__/developerTestAccounts.test.js +29 -17
  54. package/lib/__tests__/importData.test.js +20 -10
  55. package/lib/__tests__/oauth.test.js +19 -8
  56. package/lib/__tests__/sandboxSync.test.js +33 -11
  57. package/lib/__tests__/sandboxes.test.js +30 -19
  58. package/lib/__tests__/usageTracking.test.js +10 -10
  59. package/lib/__tests__/validation.test.js +32 -32
  60. package/lib/accountTypes.d.ts +9 -9
  61. package/lib/accountTypes.js +2 -4
  62. package/lib/app/__tests__/migrate.test.js +15 -0
  63. package/lib/app/__tests__/migrate_legacy.test.js +9 -0
  64. package/lib/app/migrate_legacy.d.ts +2 -2
  65. package/lib/buildAccount.d.ts +4 -4
  66. package/lib/buildAccount.js +7 -14
  67. package/lib/commonOpts.js +3 -3
  68. package/lib/configMigrate.d.ts +2 -2
  69. package/lib/configMigrate.js +42 -18
  70. package/lib/configOptions.js +3 -2
  71. package/lib/developerTestAccounts.d.ts +3 -3
  72. package/lib/developerTestAccounts.js +4 -7
  73. package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -1
  74. package/lib/doctor/DiagnosticInfoBuilder.js +9 -6
  75. package/lib/doctor/Doctor.js +4 -3
  76. package/lib/doctor/__tests__/Diagnosis.test.js +4 -3
  77. package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +17 -9
  78. package/lib/doctor/__tests__/Doctor.test.js +14 -0
  79. package/lib/errorHandlers/index.js +8 -3
  80. package/lib/importData.js +8 -7
  81. package/lib/links.js +5 -5
  82. package/lib/middleware/{__test__ → __tests__}/commandTargetingUtils.test.js +3 -3
  83. package/lib/middleware/{__test__ → __tests__}/configMiddleware.test.js +23 -22
  84. package/lib/middleware/{__test__ → __tests__}/gitMiddleware.test.js +9 -7
  85. package/lib/middleware/autoUpdateMiddleware.js +34 -23
  86. package/lib/middleware/commandTargetingUtils.js +3 -2
  87. package/lib/middleware/configMiddleware.d.ts +6 -1
  88. package/lib/middleware/configMiddleware.js +36 -15
  89. package/lib/middleware/fireAlarmMiddleware.js +4 -15
  90. package/lib/middleware/gitMiddleware.js +8 -4
  91. package/lib/oauth.d.ts +2 -2
  92. package/lib/oauth.js +8 -10
  93. package/lib/projects/__tests__/AppDevModeInterface.test.js +17 -6
  94. package/lib/projects/__tests__/DevServerManager.test.js +1 -0
  95. package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
  96. package/lib/projects/__tests__/components.test.js +2 -22
  97. package/lib/projects/__tests__/deploy.test.js +16 -13
  98. package/lib/projects/__tests__/uieLinting.test.js +640 -0
  99. package/lib/projects/add/__tests__/legacyAddComponent.test.js +1 -1
  100. package/lib/projects/add/__tests__/v2AddComponent.test.js +30 -4
  101. package/lib/projects/add/legacyAddComponent.js +1 -1
  102. package/lib/projects/add/v2AddComponent.js +16 -5
  103. package/lib/projects/components.d.ts +8 -1
  104. package/lib/projects/components.js +91 -8
  105. package/lib/projects/create/__tests__/v2.test.js +11 -0
  106. package/lib/projects/deploy.js +21 -8
  107. package/lib/projects/localDev/AppDevModeInterface.js +2 -2
  108. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +11 -3
  109. package/lib/projects/localDev/LocalDevLogger.js +4 -4
  110. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
  111. package/lib/projects/localDev/helpers/account.d.ts +10 -10
  112. package/lib/projects/localDev/helpers/account.js +6 -11
  113. package/lib/projects/localDev/helpers/process.js +5 -3
  114. package/lib/projects/uieLinting.d.ts +33 -0
  115. package/lib/projects/uieLinting.js +222 -0
  116. package/lib/projects/urls.js +5 -6
  117. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +7 -5
  118. package/lib/prompts/accountNamePrompt.js +3 -3
  119. package/lib/prompts/accountsPrompt.d.ts +1 -1
  120. package/lib/prompts/accountsPrompt.js +6 -7
  121. package/lib/prompts/confirmImportDataPrompt.js +2 -2
  122. package/lib/prompts/downloadProjectPrompt.d.ts +1 -0
  123. package/lib/prompts/downloadProjectPrompt.js +5 -2
  124. package/lib/prompts/importDataTestAccountSelectPrompt.js +4 -5
  125. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  126. package/lib/prompts/projectDevTargetAccountPrompt.d.ts +3 -3
  127. package/lib/prompts/projectDevTargetAccountPrompt.js +5 -7
  128. package/lib/prompts/sandboxesPrompt.js +7 -8
  129. package/lib/prompts/setAsDefaultAccountPrompt.js +7 -6
  130. package/lib/sandboxSync.d.ts +2 -2
  131. package/lib/sandboxSync.js +3 -9
  132. package/lib/sandboxes.d.ts +4 -4
  133. package/lib/sandboxes.js +6 -11
  134. package/lib/serverlessLogs.js +2 -2
  135. package/lib/theme/__tests__/migrate.test.js +15 -0
  136. package/lib/ui/SpinniesManager.d.ts +5 -7
  137. package/lib/ui/SpinniesManager.js +9 -12
  138. package/lib/ui/__tests__/SpinniesManager.test.d.ts +1 -0
  139. package/lib/ui/__tests__/SpinniesManager.test.js +489 -0
  140. package/lib/ui/index.js +6 -3
  141. package/lib/usageTracking.js +15 -8
  142. package/lib/validation.js +13 -11
  143. package/mcp-server/tools/cms/HsCreateFunctionTool.js +4 -2
  144. package/mcp-server/tools/cms/HsCreateModuleTool.js +4 -2
  145. package/mcp-server/tools/cms/HsCreateTemplateTool.js +4 -2
  146. package/mcp-server/tools/cms/HsFunctionLogsTool.js +4 -2
  147. package/mcp-server/tools/cms/HsListFunctionsTool.js +3 -1
  148. package/mcp-server/tools/cms/HsListTool.js +3 -1
  149. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -0
  150. package/mcp-server/tools/index.js +4 -0
  151. package/mcp-server/tools/project/AddFeatureToProjectTool.js +4 -2
  152. package/mcp-server/tools/project/CreateProjectTool.js +4 -2
  153. package/mcp-server/tools/project/CreateTestAccountTool.js +17 -7
  154. package/mcp-server/tools/project/DeployProjectTool.js +3 -1
  155. package/mcp-server/tools/project/DocFetchTool.js +6 -4
  156. package/mcp-server/tools/project/DocsSearchTool.d.ts +1 -1
  157. package/mcp-server/tools/project/DocsSearchTool.js +10 -8
  158. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +1 -1
  159. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -7
  160. package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
  161. package/mcp-server/tools/project/GetBuildLogsTool.d.ts +26 -0
  162. package/mcp-server/tools/project/GetBuildLogsTool.js +125 -0
  163. package/mcp-server/tools/project/GetBuildStatusTool.d.ts +26 -0
  164. package/mcp-server/tools/project/GetBuildStatusTool.js +166 -0
  165. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +1 -1
  166. package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
  167. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +1 -1
  168. package/mcp-server/tools/project/GuidedWalkthroughTool.js +5 -3
  169. package/mcp-server/tools/project/UploadProjectTools.js +3 -1
  170. package/mcp-server/tools/project/ValidateProjectTool.js +4 -2
  171. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +12 -2
  172. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +5 -1
  173. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +23 -11
  174. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +7 -5
  175. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +7 -5
  176. package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.d.ts +1 -0
  177. package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.js +305 -0
  178. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.d.ts +1 -0
  179. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +240 -0
  180. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -6
  181. package/mcp-server/utils/__tests__/content.test.js +21 -20
  182. package/mcp-server/utils/__tests__/feedbackTracking.test.js +34 -28
  183. package/mcp-server/utils/config.d.ts +1 -0
  184. package/mcp-server/utils/config.js +10 -0
  185. package/mcp-server/utils/content.d.ts +1 -1
  186. package/mcp-server/utils/content.js +2 -2
  187. package/mcp-server/utils/feedbackTracking.d.ts +1 -1
  188. package/mcp-server/utils/feedbackTracking.js +3 -3
  189. package/mcp-server/utils/toolUsageTracking.js +4 -3
  190. package/package.json +9 -9
  191. package/ui/components/BoxWithTitle.d.ts +2 -1
  192. package/ui/components/BoxWithTitle.js +2 -2
  193. package/ui/components/StatusMessageBoxes.d.ts +5 -4
  194. package/ui/components/StatusMessageBoxes.js +8 -8
  195. package/lib/middleware/__test__/notificationsMiddleware.test.js +0 -8
  196. package/lib/middleware/notificationsMiddleware.d.ts +0 -1
  197. package/lib/middleware/notificationsMiddleware.js +0 -28
  198. package/lib/ui/boxen.d.ts +0 -5
  199. package/lib/ui/boxen.js +0 -26
  200. package/mcp-server/utils/__tests__/cliConfig.test.js +0 -110
  201. package/mcp-server/utils/cliConfig.d.ts +0 -1
  202. package/mcp-server/utils/cliConfig.js +0 -12
  203. /package/{lib/middleware/__test__/commandTargetingUtils.test.d.ts → commands/project/__tests__/lint.test.d.ts} +0 -0
  204. /package/lib/middleware/{__test__/configMiddleware.test.d.ts → __tests__/commandTargetingUtils.test.d.ts} +0 -0
  205. /package/lib/middleware/{__test__/gitMiddleware.test.d.ts → __tests__/configMiddleware.test.d.ts} +0 -0
  206. /package/lib/middleware/{__test__/notificationsMiddleware.test.d.ts → __tests__/gitMiddleware.test.d.ts} +0 -0
  207. /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.d.ts +0 -0
  208. /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.js +0 -0
  209. /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.d.ts +0 -0
  210. /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.js +0 -0
  211. /package/{mcp-server/utils/__tests__/cliConfig.test.d.ts → lib/projects/__tests__/uieLinting.test.d.ts} +0 -0
@@ -8,6 +8,8 @@ import * as ui from '../../../lib/ui/index.js';
8
8
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
9
9
  import { logError } from '../../../lib/errorHandlers/index.js';
10
10
  import projectLogsCommand from '../logs.js';
11
+ import * as config from '@hubspot/local-dev-lib/config';
12
+ import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
11
13
  vi.mock('../../ui/logger.js');
12
14
  vi.mock('../../../lib/commonOpts');
13
15
  vi.mock('../../../lib/usageTracking');
@@ -25,6 +27,7 @@ const projectLogsManagerGetFunctionNamesSpy = vi.spyOn(ProjectLogsManager, 'getF
25
27
  const projectLogsManagerInitSpy = vi.spyOn(ProjectLogsManager, 'init');
26
28
  const getTableHeaderSpy = vi.spyOn(table, 'getTableHeader');
27
29
  const getTableContentsSpy = vi.spyOn(table, 'getTableContents');
30
+ const getConfigAccountEnvironmentSpy = vi.spyOn(config, 'getConfigAccountEnvironment');
28
31
  const optionsSpy = vi
29
32
  .spyOn(yargs, 'options')
30
33
  .mockReturnValue(yargs);
@@ -34,6 +37,7 @@ const conflictsSpy = vi
34
37
  const exampleSpy = vi
35
38
  .spyOn(yargs, 'example')
36
39
  .mockReturnValue(yargs);
40
+ getConfigAccountEnvironmentSpy.mockReturnValue(ENVIRONMENTS.PROD);
37
41
  describe('commands/project/logs', () => {
38
42
  beforeEach(() => {
39
43
  // @ts-expect-error Doesn't match the actual signature because then the linter complains about unused variables
@@ -7,7 +7,7 @@ import { commands } from '../../../lang/en.js';
7
7
  import { isV2Project } from '../../../lib/projects/platformVersion.js';
8
8
  import { loadAndValidateProfile } from '../../../lib/projectProfiles.js';
9
9
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
10
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
10
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
11
11
  import { handleTranslate } from '../../../lib/projects/upload.js';
12
12
  import projectValidateCommand from '../validate.js';
13
13
  // Mock dependencies
@@ -79,7 +79,7 @@ describe('commands/project/validate', () => {
79
79
  vi.mocked(isV2Project).mockReturnValue(true);
80
80
  vi.mocked(validateProjectConfig).mockReturnValue(undefined);
81
81
  vi.mocked(loadAndValidateProfile).mockResolvedValue(123);
82
- vi.mocked(getAccountConfig).mockReturnValue({
82
+ vi.mocked(getConfigAccountById).mockReturnValue({
83
83
  accountType: 'STANDARD',
84
84
  accountId: 123,
85
85
  env: 'prod',
@@ -14,7 +14,7 @@ import { cloneApp, checkCloneStatus, downloadClonedProject, } from '@hubspot/loc
14
14
  import { getCwd, sanitizeFileName } from '@hubspot/local-dev-lib/path';
15
15
  import { uiLogger } from '../../lib/ui/logger.js';
16
16
  import { extractZipArchive } from '@hubspot/local-dev-lib/archive';
17
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
17
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
18
18
  import SpinniesManager from '../../lib/ui/SpinniesManager.js';
19
19
  import { logInvalidAccountError } from '../../lib/app/migrate.js';
20
20
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
@@ -25,7 +25,7 @@ const deprecated = true;
25
25
  async function handler(args) {
26
26
  const { derivedAccountId } = args;
27
27
  await trackCommandUsage('clone-app', {}, derivedAccountId);
28
- const accountConfig = getAccountConfig(derivedAccountId);
28
+ const accountConfig = getConfigAccountById(derivedAccountId);
29
29
  const accountName = uiAccountDescription(derivedAccountId);
30
30
  if (!accountConfig) {
31
31
  throw new Error(commands.project.cloneApp.errors.noAccountConfig(derivedAccountId));
@@ -7,7 +7,6 @@ import { writeProjectConfig, getProjectConfig, } from '../../lib/projects/config
7
7
  import { EMPTY_PROJECT_TEMPLATE_NAME } from '../../lib/projects/create/legacy.js';
8
8
  import { generateComponentPaths } from '../../lib/projects/create/v2.js';
9
9
  import { PROJECT_WITH_APP, EMPTY_PROJECT } from '../../lib/constants.js';
10
- import { uiFeatureHighlight } from '../../lib/ui/index.js';
11
10
  import { debugError, logError } from '../../lib/errorHandlers/index.js';
12
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
13
12
  import { PROJECT_CONFIG_FILE, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, marketplaceDistribution, privateDistribution, oAuth, staticAuth, DEFAULT_PROJECT_TEMPLATE_BRANCH, } from '../../lib/constants.js';
@@ -18,6 +17,7 @@ import { uiLogger } from '../../lib/ui/logger.js';
18
17
  import { handleProjectCreationFlow, } from '../../lib/projects/create/index.js';
19
18
  import { getProjectMetadata, } from '@hubspot/project-parsing-lib/src/lib/project.js';
20
19
  import { updateHsMetaFilesWithAutoGeneratedFields } from '../../lib/projects/components.js';
20
+ import SpinniesManager from '../../lib/ui/SpinniesManager.js';
21
21
  const command = ['create', 'init'];
22
22
  const describe = commands.project.create.describe;
23
23
  const { v2023_2, v2025_1, v2025_2 } = PLATFORM_VERSIONS;
@@ -61,6 +61,12 @@ async function handler(args) {
61
61
  authType,
62
62
  distribution,
63
63
  });
64
+ const isProjectEmpty = selectProjectTemplatePromptResponse.projectTemplate?.name ===
65
+ EMPTY_PROJECT_TEMPLATE_NAME || projectContents === EMPTY_PROJECT;
66
+ SpinniesManager.init();
67
+ SpinniesManager.add('project-create', {
68
+ text: commands.project.create.creatingComponent(isProjectEmpty, projectNameAndDestPromptResponse.name),
69
+ });
64
70
  try {
65
71
  await cloneGithubRepo(repo, projectDest, {
66
72
  sourceDir: selectProjectTemplatePromptResponse.projectTemplate?.path || components,
@@ -69,6 +75,9 @@ async function handler(args) {
69
75
  });
70
76
  }
71
77
  catch (err) {
78
+ SpinniesManager.fail('project-create', {
79
+ text: commands.project.create.failure(isProjectEmpty, projectNameAndDestPromptResponse.name),
80
+ });
72
81
  debugError(err);
73
82
  uiLogger.error(commands.project.create.errors.failedToDownloadProject);
74
83
  process.exit(EXIT_CODES.ERROR);
@@ -80,23 +89,20 @@ async function handler(args) {
80
89
  ...parsedConfigFile,
81
90
  name: projectName,
82
91
  });
92
+ SpinniesManager.succeed('project-create', {
93
+ text: commands.project.create.success(isProjectEmpty, projectName),
94
+ });
83
95
  const projectMetadata = await getProjectMetadata(path.join(projectDest, parsedConfigFile.srcDir));
84
- updateHsMetaFilesWithAutoGeneratedFields(projectName, projectMetadata.hsMetaFiles);
96
+ await updateHsMetaFilesWithAutoGeneratedFields(projectName, projectMetadata.hsMetaFiles, [], {
97
+ updatedProjectMetadata: projectMetadata,
98
+ showSuccessMessage: true,
99
+ isProjectEmpty,
100
+ projectDest,
101
+ });
85
102
  // If the template is 'no-template', we need to manually create a src directory
86
- if (selectProjectTemplatePromptResponse.projectTemplate?.name ===
87
- EMPTY_PROJECT_TEMPLATE_NAME ||
88
- projectContents === EMPTY_PROJECT) {
103
+ if (isProjectEmpty) {
89
104
  fs.ensureDirSync(path.join(projectDest, 'src'));
90
105
  }
91
- uiLogger.success(commands.project.create.logs.success(projectNameAndDestPromptResponse.name, projectDest));
92
- uiLogger.log(commands.project.create.logs.welcomeMessage);
93
- uiFeatureHighlight([
94
- 'projectCommandTip',
95
- 'projectUploadCommand',
96
- 'projectDevCommand',
97
- 'projectHelpCommand',
98
- 'feedbackCommand',
99
- ]);
100
106
  process.exit(EXIT_CODES.SUCCESS);
101
107
  }
102
108
  function projectCreateBuilder(yargs) {
@@ -1,5 +1,5 @@
1
1
  import { fetchProject } from '@hubspot/local-dev-lib/api/projects';
2
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
3
3
  import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
4
4
  import { isV2Project } from '../../lib/projects/platformVersion.js';
5
5
  import { trackCommandUsage } from '../../lib/usageTracking.js';
@@ -19,7 +19,7 @@ const command = 'deploy';
19
19
  const describe = commands.project.deploy.describe;
20
20
  async function handler(args) {
21
21
  const { derivedAccountId, project: projectOption, buildId: buildIdOption, force: forceOption, deployLatestBuild: deployLatestBuildOption, json: formatOutputAsJson, } = args;
22
- const accountConfig = getAccountConfig(derivedAccountId);
22
+ const accountConfig = getConfigAccountById(derivedAccountId);
23
23
  const accountType = accountConfig && accountConfig.accountType;
24
24
  let targetAccountId;
25
25
  const jsonOutput = {};
@@ -1,5 +1,4 @@
1
- import { getAccountConfig, getConfigAccounts, getEnv, } from '@hubspot/local-dev-lib/config';
2
- import { getValidEnv } from '@hubspot/local-dev-lib/environment';
1
+ import { getConfigAccountById, getAllConfigAccounts, getConfigAccountEnvironment, } from '@hubspot/local-dev-lib/config';
3
2
  import { findProjectComponents, getProjectComponentTypes, } from '../../../lib/projects/structure.js';
4
3
  import { ComponentTypes } from '../../../types/Projects.js';
5
4
  import { commands } from '../../../lang/en.js';
@@ -14,13 +13,13 @@ import { isSandbox, isDeveloperTestAccount, } from '../../../lib/accountTypes.js
14
13
  import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
15
14
  export async function deprecatedProjectDevFlow({ args, accountId, projectConfig, projectDir, }) {
16
15
  const { userProvidedAccount, derivedAccountId } = args;
17
- const env = getValidEnv(getEnv(derivedAccountId));
16
+ const env = getConfigAccountEnvironment(derivedAccountId);
18
17
  const components = await findProjectComponents(projectDir);
19
18
  const runnableComponents = components.filter(component => component.runnable);
20
19
  const componentTypes = getProjectComponentTypes(runnableComponents);
21
20
  const hasPrivateApps = !!componentTypes[ComponentTypes.PrivateApp];
22
21
  const hasPublicApps = !!componentTypes[ComponentTypes.PublicApp];
23
- const accountConfig = getAccountConfig(accountId);
22
+ const accountConfig = getConfigAccountById(accountId);
24
23
  if (!accountConfig) {
25
24
  uiLogger.error(commands.project.dev.errors.noAccount(accountId));
26
25
  process.exit(EXIT_CODES.ERROR);
@@ -33,7 +32,7 @@ export async function deprecatedProjectDevFlow({ args, accountId, projectConfig,
33
32
  uiLogger.error(commands.project.dev.errors.invalidProjectComponents);
34
33
  process.exit(EXIT_CODES.SUCCESS);
35
34
  }
36
- const accounts = getConfigAccounts();
35
+ const accounts = getAllConfigAccounts();
37
36
  if (!accounts) {
38
37
  uiLogger.error(commands.project.dev.errors.noAccountsInConfig);
39
38
  process.exit(EXIT_CODES.ERROR);
@@ -1,5 +1,5 @@
1
1
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
2
- import { getAccountId } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountIfExists } from '@hubspot/local-dev-lib/config';
3
3
  import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
4
4
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
5
5
  import { uiLine } from '../../../lib/ui/index.js';
@@ -51,7 +51,8 @@ async function handler(args) {
51
51
  let profile;
52
52
  // Using the new --projectAccount flag
53
53
  if (projectAccount) {
54
- targetProjectAccountId = getAccountId(projectAccount);
54
+ targetProjectAccountId =
55
+ getConfigAccountIfExists(projectAccount)?.accountId;
55
56
  if (targetProjectAccountId) {
56
57
  uiLogger.log('');
57
58
  uiLogger.log(commands.project.dev.logs.projectAccountFlagExplanation(targetProjectAccountId));
@@ -87,7 +88,9 @@ async function handler(args) {
87
88
  }
88
89
  trackCommandUsage('project-dev', {}, targetProjectAccountId);
89
90
  if (isV2Project(projectConfig.platformVersion)) {
90
- const targetTestingAccountId = (testingAccount && getAccountId(testingAccount)) || undefined;
91
+ const targetTestingAccountId = testingAccount
92
+ ? getConfigAccountIfExists(testingAccount)?.accountId
93
+ : undefined;
91
94
  await unifiedProjectDevFlow({
92
95
  args,
93
96
  targetProjectAccountId,
@@ -4,8 +4,7 @@ import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
4
4
  import { startPortManagerServer, stopPortManagerServer, } from '@hubspot/local-dev-lib/portManager';
5
5
  import { isTranslationError } from '@hubspot/project-parsing-lib/src/lib/errors.js';
6
6
  import { translateForLocalDev } from '@hubspot/project-parsing-lib';
7
- import { getEnv, getConfigAccounts, getAccountConfig, } from '@hubspot/local-dev-lib/config';
8
- import { getValidEnv } from '@hubspot/local-dev-lib/environment';
7
+ import { getConfigAccountEnvironment, getAllConfigAccounts, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
9
8
  import { logError } from '../../../lib/errorHandlers/index.js';
10
9
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
11
10
  import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
@@ -23,7 +22,7 @@ import LocalDevWebsocketServer from '../../../lib/projects/localDev/LocalDevWebs
23
22
  import { confirmLocalDevIsNotRunning } from '../../../lib/projects/localDev/helpers/process.js';
24
23
  export async function unifiedProjectDevFlow({ args, targetProjectAccountId, providedTargetTestingAccountId, projectConfig, projectDir, }) {
25
24
  await confirmLocalDevIsNotRunning();
26
- const env = getValidEnv(getEnv(targetProjectAccountId));
25
+ const env = getConfigAccountEnvironment(targetProjectAccountId);
27
26
  let projectNodes;
28
27
  let projectProfileData;
29
28
  // Get IR
@@ -50,12 +49,12 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
50
49
  uiLogger.error(commands.project.dev.errors.noRunnableComponents);
51
50
  process.exit(EXIT_CODES.SUCCESS);
52
51
  }
53
- const targetProjectAccountConfig = getAccountConfig(targetProjectAccountId);
52
+ const targetProjectAccountConfig = getConfigAccountById(targetProjectAccountId);
54
53
  if (!targetProjectAccountConfig) {
55
54
  uiLogger.error(commands.project.dev.errors.noAccount(targetProjectAccountId));
56
55
  process.exit(EXIT_CODES.ERROR);
57
56
  }
58
- const accounts = getConfigAccounts();
57
+ const accounts = getAllConfigAccounts();
59
58
  const accountIsCombined = await isUnifiedAccount(targetProjectAccountConfig);
60
59
  const targetProjectAccountIsTestAccountOrSandbox = isTestAccountOrSandbox(targetProjectAccountConfig);
61
60
  if (!accountIsCombined) {
@@ -124,7 +123,13 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
124
123
  // Check for missing/outdated dependencies
125
124
  await checkAndInstallDependencies();
126
125
  // End setup, start local dev process
127
- await startPortManagerServer();
126
+ try {
127
+ await startPortManagerServer();
128
+ }
129
+ catch (e) {
130
+ logError(e);
131
+ process.exit(EXIT_CODES.ERROR);
132
+ }
128
133
  const localDevProcess = new LocalDevProcess({
129
134
  initialProjectNodes: projectNodes,
130
135
  initialProjectProfileData: projectProfileData,
@@ -0,0 +1,6 @@
1
+ import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
2
+ export type ProjectLintArgs = CommonArgs & {
3
+ installMissingDeps?: boolean;
4
+ };
5
+ declare const projectLintCommand: YargsCommandModule<unknown, ProjectLintArgs>;
6
+ export default projectLintCommand;
@@ -0,0 +1,178 @@
1
+ import path from 'path';
2
+ import { getProjectPackageJsonLocations, installPackages, } from '../../lib/dependencyManagement.js';
3
+ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
4
+ import { getProjectConfig } from '../../lib/projects/config.js';
5
+ import { commands } from '../../lang/en.js';
6
+ import { uiLogger } from '../../lib/ui/logger.js';
7
+ import { trackCommandUsage } from '../../lib/usageTracking.js';
8
+ import { logError } from '../../lib/errorHandlers/index.js';
9
+ import { makeYargsBuilder } from '../../lib/yargsUtils.js';
10
+ import { promptUser } from '../../lib/prompts/promptUtils.js';
11
+ import SpinniesManager from '../../lib/ui/SpinniesManager.js';
12
+ import { areAllLintPackagesInstalled, getMissingLintPackages, lintPackages, displayLintResults, hasEslintConfig, hasDeprecatedEslintConfig, getDeprecatedEslintConfigFiles, createEslintConfig, REQUIRED_PACKAGES_AND_MIN_VERSIONS, } from '../../lib/projects/uieLinting.js';
13
+ const command = 'lint';
14
+ const describe = commands.project.lint.help.describe;
15
+ async function handler(args) {
16
+ const { derivedAccountId, installMissingDeps } = args;
17
+ try {
18
+ trackCommandUsage('project-lint', undefined, derivedAccountId);
19
+ const projectConfig = await getProjectConfig();
20
+ if (!projectConfig || !projectConfig.projectDir) {
21
+ uiLogger.error(commands.project.lint.noProjectConfig);
22
+ return process.exit(EXIT_CODES.ERROR);
23
+ }
24
+ SpinniesManager.init({ succeedColor: 'white' });
25
+ SpinniesManager.add('lintCheck', {
26
+ text: commands.project.lint.loading.checking,
27
+ });
28
+ const lintLocations = await getProjectPackageJsonLocations();
29
+ const locationsReadyToLint = [];
30
+ const locationsNeedingPackages = new Map();
31
+ for (const lintLocation of lintLocations) {
32
+ if (areAllLintPackagesInstalled(lintLocation)) {
33
+ locationsReadyToLint.push(lintLocation);
34
+ }
35
+ else {
36
+ const { missingPackages } = getMissingLintPackages(lintLocation);
37
+ if (missingPackages.length > 0) {
38
+ locationsNeedingPackages.set(lintLocation, missingPackages);
39
+ }
40
+ }
41
+ }
42
+ SpinniesManager.succeed('lintCheck');
43
+ if (locationsNeedingPackages.size > 0) {
44
+ const locationsArray = Array.from(locationsNeedingPackages.keys());
45
+ const relativeLocations = locationsArray.map(loc => path.relative(projectConfig.projectDir, loc));
46
+ const allMissingPackages = [];
47
+ for (const packages of locationsNeedingPackages.values()) {
48
+ allMissingPackages.push(...packages);
49
+ }
50
+ let shouldInstallPackages;
51
+ if (installMissingDeps !== undefined) {
52
+ shouldInstallPackages = installMissingDeps;
53
+ }
54
+ else {
55
+ const promptResult = await promptUser([
56
+ {
57
+ name: 'shouldInstallPackages',
58
+ type: 'confirm',
59
+ message: commands.project.lint.installLintPackagesPrompt(relativeLocations, allMissingPackages),
60
+ default: true,
61
+ },
62
+ ]);
63
+ shouldInstallPackages = promptResult.shouldInstallPackages;
64
+ }
65
+ if (shouldInstallPackages) {
66
+ const packagesToInstall = Object.entries(REQUIRED_PACKAGES_AND_MIN_VERSIONS).map(([pkg, version]) => `${pkg}@^${version}`);
67
+ await installPackages({
68
+ packages: packagesToInstall,
69
+ installLocations: locationsArray,
70
+ dev: true,
71
+ });
72
+ // Re-check which locations are now ready
73
+ for (const location of locationsArray) {
74
+ if (areAllLintPackagesInstalled(location)) {
75
+ locationsReadyToLint.push(location);
76
+ }
77
+ }
78
+ }
79
+ else {
80
+ uiLogger.warn(commands.project.lint.skippingDirectoriesWarning(relativeLocations));
81
+ }
82
+ }
83
+ if (locationsReadyToLint.length > 0) {
84
+ // Check for config files and handle deprecated configs
85
+ const deprecatedConfigDetails = [];
86
+ const locationsNeedingConfig = [];
87
+ for (const location of locationsReadyToLint) {
88
+ const hasModernConfig = hasEslintConfig(location);
89
+ const hasDeprecatedConfig = hasDeprecatedEslintConfig(location);
90
+ if (hasDeprecatedConfig) {
91
+ const relativePath = path.relative(projectConfig.projectDir, location);
92
+ const deprecatedFiles = getDeprecatedEslintConfigFiles(location);
93
+ deprecatedConfigDetails.push({
94
+ path: relativePath,
95
+ files: deprecatedFiles,
96
+ });
97
+ }
98
+ if (!hasModernConfig) {
99
+ locationsNeedingConfig.push(location);
100
+ }
101
+ }
102
+ if (deprecatedConfigDetails.length > 0) {
103
+ uiLogger.log('');
104
+ uiLogger.warn(commands.project.lint.deprecatedEslintConfigWarning(deprecatedConfigDetails));
105
+ }
106
+ if (locationsNeedingConfig.length > 0) {
107
+ const relativeLocations = locationsNeedingConfig.map(loc => path.relative(projectConfig.projectDir, loc));
108
+ const { shouldCreateConfig } = await promptUser([
109
+ {
110
+ name: 'shouldCreateConfig',
111
+ type: 'confirm',
112
+ message: commands.project.lint.createEslintConfigPrompt(relativeLocations),
113
+ default: true,
114
+ },
115
+ ]);
116
+ if (shouldCreateConfig) {
117
+ SpinniesManager.add('lintConfigCreate', {
118
+ text: commands.project.lint.loading.creatingConfig,
119
+ });
120
+ const createdConfigs = [];
121
+ for (const location of locationsNeedingConfig) {
122
+ const configPath = createEslintConfig(location);
123
+ createdConfigs.push(configPath);
124
+ }
125
+ SpinniesManager.succeed('lintConfigCreate');
126
+ createdConfigs.forEach(configPath => {
127
+ uiLogger.success(commands.project.lint.eslintConfigCreated(configPath));
128
+ });
129
+ }
130
+ else {
131
+ uiLogger.error(commands.project.lint.eslintConfigRequired);
132
+ return process.exit(EXIT_CODES.ERROR);
133
+ }
134
+ }
135
+ SpinniesManager.add('lintRun', {
136
+ text: commands.project.lint.loading.linting,
137
+ });
138
+ const { success, results } = await lintPackages(locationsReadyToLint, projectConfig.projectDir);
139
+ SpinniesManager.succeed('lintRun');
140
+ displayLintResults(results);
141
+ if (!success) {
142
+ return process.exit(EXIT_CODES.ERROR);
143
+ }
144
+ }
145
+ }
146
+ catch (e) {
147
+ logError(e);
148
+ return process.exit(EXIT_CODES.ERROR);
149
+ }
150
+ }
151
+ function projectLintBuilder(yargs) {
152
+ yargs.example([
153
+ ['$0 project lint', commands.project.lint.help.lintProjectExample],
154
+ [
155
+ '$0 project lint --install-missing-deps',
156
+ commands.project.lint.help.lintProjectWithInstallExample,
157
+ ],
158
+ [
159
+ '$0 project lint --install-missing-deps=false',
160
+ commands.project.lint.help.lintProjectWithoutInstallExample,
161
+ ],
162
+ ]);
163
+ yargs.option('install-missing-deps', {
164
+ type: 'boolean',
165
+ describe: commands.project.lint.help.installMissingDeps,
166
+ });
167
+ return yargs;
168
+ }
169
+ const builder = makeYargsBuilder(projectLintBuilder, command, describe, {
170
+ useGlobalOptions: true,
171
+ });
172
+ const projectLintCommand = {
173
+ command,
174
+ describe,
175
+ handler,
176
+ builder,
177
+ };
178
+ export default projectLintCommand;
@@ -1,6 +1,5 @@
1
- import { getEnv } from '@hubspot/local-dev-lib/config';
1
+ import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
2
2
  import { getHubSpotWebsiteOrigin } from '@hubspot/local-dev-lib/urls';
3
- import { ENVIRONMENTS } from '@hubspot/local-dev-lib/constants/environments';
4
3
  import { trackCommandUsage } from '../../lib/usageTracking.js';
5
4
  import { getTableContents, getTableHeader } from '../../lib/ui/table.js';
6
5
  import { logError } from '../../lib/errorHandlers/index.js';
@@ -12,7 +11,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
12
11
  import { ProjectLogsManager } from '../../lib/projects/ProjectLogsManager.js';
13
12
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
14
13
  function getPrivateAppsUrl(accountId) {
15
- const baseUrl = getHubSpotWebsiteOrigin(getEnv(accountId) === 'qa' ? ENVIRONMENTS.QA : ENVIRONMENTS.PROD);
14
+ const baseUrl = getHubSpotWebsiteOrigin(getConfigAccountEnvironment(accountId));
16
15
  return `${baseUrl}/private-apps/${accountId}`;
17
16
  }
18
17
  function logTable(tableHeader, logsInfo) {
@@ -7,7 +7,6 @@ import { makeYargsBuilder } from '../../lib/yargsUtils.js';
7
7
  import { uiCommandReference } from '../../lib/ui/index.js';
8
8
  import { commands, lib } from '../../lang/en.js';
9
9
  import { uiLogger } from '../../lib/ui/logger.js';
10
- import { logInBox } from '../../lib/ui/boxen.js';
11
10
  import { renderInline } from '../../ui/index.js';
12
11
  import { getWarningBox } from '../../ui/components/StatusMessageBoxes.js';
13
12
  import { getHasMigratableThemes, migrateThemes2025_2, } from '../../lib/theme/migrate.js';
@@ -26,18 +25,10 @@ async function handler(args) {
26
25
  return process.exit(EXIT_CODES.ERROR);
27
26
  }
28
27
  if (projectConfig?.projectConfig) {
29
- if (!process.env.HUBSPOT_ENABLE_INK) {
30
- await logInBox({
31
- contents: lib.migrate.projectMigrationWarning,
32
- options: { title: lib.migrate.projectMigrationWarningTitle },
33
- });
34
- }
35
- else {
36
- await renderInline(getWarningBox({
37
- title: lib.migrate.projectMigrationWarningTitle,
38
- message: lib.migrate.projectMigrationWarning,
39
- }));
40
- }
28
+ await renderInline(getWarningBox({
29
+ title: lib.migrate.projectMigrationWarningTitle,
30
+ message: lib.migrate.projectMigrationWarning,
31
+ }));
41
32
  }
42
33
  try {
43
34
  const { hasMigratableThemes, migratableThemesCount } = await getHasMigratableThemes(projectConfig);
@@ -1,7 +1,6 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
- import { getAccountId, getConfigAccounts } from '@hubspot/local-dev-lib/config';
4
- import { getAccountIdentifier } from '@hubspot/local-dev-lib/config/getAccountIdentifier';
3
+ import { getConfigAccountIfExists, getAllConfigAccounts, } from '@hubspot/local-dev-lib/config';
5
4
  import { getAllHsProfiles, getHsProfileFilename, loadHsProfileFile, } from '@hubspot/project-parsing-lib';
6
5
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
6
  import { getProjectConfig } from '../../../lib/projects/config.js';
@@ -102,9 +101,9 @@ async function handler(args) {
102
101
  profileName = promptResponse.name;
103
102
  }
104
103
  if (targetAccountId) {
105
- const accountId = getAccountId(targetAccountId);
106
- if (accountId) {
107
- targetAccountId = accountId;
104
+ const account = getConfigAccountIfExists(targetAccountId);
105
+ if (account) {
106
+ targetAccountId = account.accountId;
108
107
  }
109
108
  else {
110
109
  uiLogger.error(commands.project.profile.add.errors.invalidTargetAccount);
@@ -113,14 +112,14 @@ async function handler(args) {
113
112
  }
114
113
  }
115
114
  if (!targetAccountId) {
116
- const configuredAccounts = getConfigAccounts();
115
+ const configuredAccounts = getAllConfigAccounts();
117
116
  if (!configuredAccounts || !configuredAccounts.length) {
118
117
  uiLogger.error(commands.project.profile.add.errors.noAccountsConfigured);
119
118
  process.exit(EXIT_CODES.ERROR);
120
119
  }
121
120
  const promptResponse = await listPrompt(commands.project.profile.add.prompts.targetAccountPrompt, {
122
121
  choices: configuredAccounts.map(account => {
123
- const accountId = getAccountIdentifier(account);
122
+ const accountId = account.accountId;
124
123
  return {
125
124
  name: uiAccountDescription(accountId),
126
125
  value: accountId,
@@ -2,7 +2,7 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { getAllHsProfiles, getHsProfileFilename, loadHsProfileFile, } from '@hubspot/project-parsing-lib';
4
4
  import { fetchProject, deleteProject, } from '@hubspot/local-dev-lib/api/projects';
5
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
5
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
6
6
  import { trackCommandUsage } from '../../../lib/usageTracking.js';
7
7
  import { getProjectConfig } from '../../../lib/projects/config.js';
8
8
  import { uiLogger } from '../../../lib/ui/logger.js';
@@ -80,7 +80,7 @@ async function handler(args) {
80
80
  catch (err) {
81
81
  debugError(err);
82
82
  }
83
- const targetAccountConfig = getAccountConfig(targetAccountId);
83
+ const targetAccountConfig = getConfigAccountById(targetAccountId);
84
84
  if (projectExists &&
85
85
  targetAccountConfig &&
86
86
  (isDeveloperTestAccount(targetAccountConfig) ||
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { uiLogger } from '../../lib/ui/logger.js';
3
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
3
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
4
4
  import { isSpecifiedError } from '@hubspot/local-dev-lib/errors/index';
5
5
  import { isV2Project } from '../../lib/projects/platformVersion.js';
6
6
  import { trackCommandUsage } from '../../lib/usageTracking.js';
@@ -32,7 +32,7 @@ async function handler(args) {
32
32
  targetAccountId = await loadAndValidateProfile(projectConfig, projectDir, profile);
33
33
  }
34
34
  targetAccountId = targetAccountId || derivedAccountId;
35
- const accountConfig = getAccountConfig(targetAccountId);
35
+ const accountConfig = getConfigAccountById(targetAccountId);
36
36
  const accountType = accountConfig && accountConfig.accountType;
37
37
  trackCommandUsage('project-upload', { type: accountType, assetType: projectConfig.platformVersion }, targetAccountId);
38
38
  try {
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import { getAccountConfig } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
3
3
  import { isV2Project } from '../../lib/projects/platformVersion.js';
4
4
  import { trackCommandUsage } from '../../lib/usageTracking.js';
5
5
  import { uiLogger } from '../../lib/ui/logger.js';
@@ -32,7 +32,7 @@ async function handler(args) {
32
32
  }
33
33
  let targetAccountId = await loadAndValidateProfile(projectConfig, projectDir, profile);
34
34
  targetAccountId = targetAccountId || derivedAccountId;
35
- const accountConfig = getAccountConfig(targetAccountId);
35
+ const accountConfig = getConfigAccountById(targetAccountId);
36
36
  const accountType = accountConfig && accountConfig.accountType;
37
37
  trackCommandUsage('project-validate', { type: accountType }, targetAccountId);
38
38
  const srcDir = path.resolve(projectDir, projectConfig.srcDir);
@@ -13,6 +13,7 @@ import migrate from './project/migrate.js';
13
13
  import migrateApp from './project/migrateApp.js';
14
14
  import cloneApp from './project/cloneApp.js';
15
15
  import installDeps from './project/installDeps.js';
16
+ import lint from './project/lint.js';
16
17
  import updateDeps from './project/updateDeps.js';
17
18
  import profile from './project/profile.js';
18
19
  import projectValidate from './project/validate.js';
@@ -37,6 +38,7 @@ function projectBuilder(yargs) {
37
38
  .command(migrate)
38
39
  .command(cloneApp)
39
40
  .command(installDeps)
41
+ .command(lint)
40
42
  .command(updateDeps)
41
43
  .command(profile)
42
44
  .command(projectValidate)