@hubspot/cli 8.14.0 → 8.15.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/commands/cms/theme/preview.js +8 -1
  2. package/commands/getStarted.js +16 -21
  3. package/commands/project/add.js +7 -6
  4. package/commands/project/appInstallStatus.d.ts +1 -1
  5. package/commands/project/appInstallStatus.js +8 -4
  6. package/commands/project/create.js +24 -7
  7. package/commands/project/delete.js +1 -1
  8. package/commands/project/deploy.d.ts +1 -1
  9. package/commands/project/deploy.js +14 -12
  10. package/commands/project/dev/index.js +4 -7
  11. package/commands/project/download.d.ts +3 -2
  12. package/commands/project/download.js +18 -5
  13. package/commands/project/info.d.ts +1 -1
  14. package/commands/project/info.js +8 -5
  15. package/commands/project/installApp.d.ts +1 -1
  16. package/commands/project/installApp.js +9 -4
  17. package/commands/project/installDeps.js +6 -5
  18. package/commands/project/lint.js +16 -9
  19. package/commands/project/list.d.ts +3 -2
  20. package/commands/project/list.js +21 -3
  21. package/commands/project/listBuilds.d.ts +1 -1
  22. package/commands/project/listBuilds.js +4 -8
  23. package/commands/project/migrate.js +14 -19
  24. package/commands/project/open.js +15 -7
  25. package/commands/project/profile/add.js +8 -4
  26. package/commands/project/profile/delete.js +8 -4
  27. package/commands/project/release/create.d.ts +1 -1
  28. package/commands/project/release/create.js +5 -7
  29. package/commands/project/release/info.d.ts +1 -1
  30. package/commands/project/release/info.js +4 -4
  31. package/commands/project/release/list.d.ts +1 -1
  32. package/commands/project/release/list.js +4 -4
  33. package/commands/project/updateDeps.js +6 -5
  34. package/commands/project/upload.d.ts +1 -1
  35. package/commands/project/upload.js +26 -15
  36. package/commands/project/validate.d.ts +3 -2
  37. package/commands/project/validate.js +67 -97
  38. package/commands/project/watch.js +8 -11
  39. package/commands/project.js +1 -1
  40. package/commands/testAccount/create.d.ts +1 -1
  41. package/commands/testAccount/create.js +1 -1
  42. package/lang/en.d.ts +9 -19
  43. package/lang/en.js +9 -19
  44. package/lib/app/migrate.js +5 -7
  45. package/lib/constants.d.ts +0 -1
  46. package/lib/constants.js +0 -1
  47. package/lib/dependencyManagement.js +3 -10
  48. package/lib/doctor/DiagnosticInfoBuilder.d.ts +2 -2
  49. package/lib/doctor/DiagnosticInfoBuilder.js +8 -8
  50. package/lib/doctor/Doctor.js +7 -9
  51. package/lib/errors/ProjectErrors.d.ts +0 -6
  52. package/lib/errors/ProjectErrors.js +0 -12
  53. package/lib/errors/ProjectValidationError.d.ts +2 -1
  54. package/lib/errors/ProjectValidationError.js +3 -1
  55. package/lib/filesystem.d.ts +6 -0
  56. package/lib/filesystem.js +9 -0
  57. package/lib/getStartedV2Actions.js +14 -18
  58. package/lib/jsonOutput/appInstallStatus.d.ts +14 -0
  59. package/lib/jsonOutput/appInstallStatus.js +14 -0
  60. package/lib/jsonOutput/createTestAccount.d.ts +7 -0
  61. package/lib/jsonOutput/createTestAccount.js +6 -0
  62. package/lib/jsonOutput/deploy.d.ts +5 -0
  63. package/lib/jsonOutput/deploy.js +4 -0
  64. package/lib/jsonOutput/download.d.ts +7 -0
  65. package/lib/jsonOutput/download.js +6 -0
  66. package/lib/jsonOutput/info.d.ts +21 -0
  67. package/lib/jsonOutput/info.js +19 -0
  68. package/lib/jsonOutput/installApp.d.ts +11 -0
  69. package/lib/jsonOutput/installApp.js +10 -0
  70. package/lib/jsonOutput/listBuilds.d.ts +75 -0
  71. package/lib/jsonOutput/listBuilds.js +65 -0
  72. package/lib/jsonOutput/projectList.d.ts +29 -0
  73. package/lib/jsonOutput/projectList.js +28 -0
  74. package/lib/jsonOutput/release.d.ts +42 -0
  75. package/lib/jsonOutput/release.js +37 -0
  76. package/lib/jsonOutput/upload.d.ts +29 -0
  77. package/lib/jsonOutput/upload.js +23 -0
  78. package/lib/jsonOutput/validate.d.ts +36 -0
  79. package/lib/jsonOutput/validate.js +20 -0
  80. package/lib/npm/packageJson.js +1 -1
  81. package/lib/projects/ProjectLogsManager.js +1 -4
  82. package/lib/projects/config.d.ts +6 -5
  83. package/lib/projects/config.js +7 -38
  84. package/lib/projects/create/tracking.d.ts +1 -0
  85. package/lib/projects/create/tracking.js +27 -0
  86. package/lib/projects/delete.js +14 -1
  87. package/lib/projects/localDev/LocalDevProcess.js +7 -7
  88. package/lib/projects/projectProfiles.d.ts +3 -2
  89. package/lib/projects/projectProfiles.js +8 -3
  90. package/lib/projects/release.js +1 -1
  91. package/lib/projects/uieLinting.d.ts +2 -0
  92. package/lib/projects/uieLinting.js +13 -11
  93. package/lib/projects/upload.d.ts +5 -1
  94. package/lib/projects/upload.js +6 -1
  95. package/lib/projects/validate.d.ts +18 -0
  96. package/lib/projects/validate.js +142 -0
  97. package/lib/projects/validateLintConfigOnUpload.js +6 -5
  98. package/lib/projects/workspaces.js +6 -13
  99. package/lib/theme/migrate.js +1 -4
  100. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +1 -1
  101. package/mcp-server/tools/project/CreateProjectTool.d.ts +1 -1
  102. package/mcp-server/tools/project/GetBuildLogsTool.js +2 -3
  103. package/mcp-server/tools/project/GetBuildStatusTool.js +2 -3
  104. package/mcp-server/tools/project/UploadProjectTools.js +3 -5
  105. package/mcp-server/tools/project/constants.d.ts +1 -1
  106. package/package.json +3 -3
  107. package/types/Projects.d.ts +1 -5
  108. package/lib/jsonOutput.d.ts +0 -182
  109. package/lib/jsonOutput.js +0 -158
@@ -1,112 +1,89 @@
1
- import path from 'path';
2
1
  import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
3
2
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
4
3
  import { uiLogger } from '../../lib/ui/logger.js';
5
- import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
4
+ import { getProjectConfig } from '../../lib/projects/config.js';
6
5
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
7
6
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
8
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
- import { validateSourceDirectory, handleTranslate, } from '../../lib/projects/upload.js';
10
8
  import { commands } from '../../lang/en.js';
11
- import { validateProjectForProfile } from '../../lib/projects/projectProfiles.js';
12
9
  import { logError } from '../../lib/errorHandlers/index.js';
13
- import { getAllHsProfiles } from '@hubspot/project-parsing-lib/profiles';
14
- import SpinniesManager from '../../lib/ui/SpinniesManager.js';
10
+ import { validateProject, toIssue, } from '../../lib/projects/validate.js';
11
+ import { ValidateSchema, } from '../../lib/jsonOutput/validate.js';
15
12
  const command = 'validate';
16
13
  const describe = commands.project.validate.describe;
17
- async function handler(args) {
18
- const { derivedAccountId, profile, exit, addUsageMetadata } = args;
19
- const { projectConfig, projectDir } = await getProjectConfig();
20
- const accountConfig = getConfigAccountById(derivedAccountId);
21
- const accountType = accountConfig && accountConfig.accountType;
22
- addUsageMetadata({ type: accountType });
23
- if (!projectConfig || !projectDir) {
24
- uiLogger.error(commands.project.validate.mustBeRanWithinAProject);
25
- return exit(EXIT_CODES.ERROR);
14
+ function generateJson({ result, projectConfig, profile, }) {
15
+ const { valid, errors, warnings, profiles } = result;
16
+ const output = { valid, errors, warnings };
17
+ if (projectConfig) {
18
+ output.projectName = projectConfig.name;
19
+ output.platformVersion = projectConfig.platformVersion;
26
20
  }
27
- if (isLegacyProject(projectConfig.platformVersion)) {
28
- uiLogger.error(commands.project.validate.badVersion);
29
- return exit(EXIT_CODES.ERROR);
21
+ if (profile) {
22
+ output.profile = profile;
23
+ }
24
+ if (profiles.length > 0) {
25
+ output.profiles = profiles;
26
+ }
27
+ return output;
28
+ }
29
+ async function handler(args) {
30
+ const { derivedAccountId, profile, exit, addUsageMetadata, formatOutputAsJson, addJsonOutput, } = args;
31
+ let projectConfig;
32
+ let projectDir;
33
+ function outputError(error) {
34
+ logError(error);
35
+ addJsonOutput(generateJson({
36
+ result: {
37
+ valid: false,
38
+ errors: [toIssue(error)],
39
+ warnings: [],
40
+ profiles: [],
41
+ },
42
+ projectConfig,
43
+ profile,
44
+ }));
30
45
  }
31
46
  try {
32
- validateProjectConfig(projectConfig, projectDir);
47
+ const accountConfig = getConfigAccountById(derivedAccountId);
48
+ const accountType = accountConfig && accountConfig.accountType;
49
+ addUsageMetadata({ type: accountType });
50
+ ({ projectConfig, projectDir } = getProjectConfig());
33
51
  }
34
52
  catch (error) {
35
- logError(error);
53
+ outputError(error);
36
54
  return exit(EXIT_CODES.ERROR);
37
55
  }
38
- let validationSucceeded = true;
39
- const srcDir = path.resolve(projectDir, projectConfig.srcDir);
40
- const profiles = await getAllHsProfiles(path.join(projectDir, projectConfig.srcDir));
41
- // If a profile is specified, only validate that profile
42
- if (profile) {
43
- const validationErrors = await validateProjectForProfile({
56
+ if (isLegacyProject(projectConfig.platformVersion)) {
57
+ const message = commands.project.validate.badVersion;
58
+ uiLogger.error(message);
59
+ addJsonOutput(generateJson({
60
+ result: {
61
+ valid: false,
62
+ errors: [{ message }],
63
+ warnings: [],
64
+ profiles: [],
65
+ },
66
+ projectConfig,
67
+ profile,
68
+ }));
69
+ return exit(EXIT_CODES.ERROR);
70
+ }
71
+ let result;
72
+ try {
73
+ result = await validateProject({
44
74
  projectConfig,
45
75
  projectDir,
46
- profileName: profile,
47
76
  derivedAccountId,
77
+ profile,
78
+ formatOutputAsJson,
48
79
  });
49
- if (validationErrors.length) {
50
- logValidationErrors(validationErrors);
51
- validationSucceeded = false;
52
- }
53
- }
54
- else if (profiles.length > 0) {
55
- // If no profile was specified and the project has profiles, validate all of them
56
- SpinniesManager.add('validatingAllProfiles', {
57
- text: commands.project.validate.spinners.validatingAllProfiles,
58
- });
59
- const errors = [];
60
- for (const profileName of profiles) {
61
- const validationErrors = await validateProjectForProfile({
62
- projectConfig,
63
- projectDir,
64
- profileName,
65
- derivedAccountId,
66
- indentSpinners: true,
67
- });
68
- if (validationErrors.length) {
69
- errors.push(...validationErrors);
70
- validationSucceeded = false;
71
- }
72
- }
73
- if (validationSucceeded) {
74
- SpinniesManager.succeed('validatingAllProfiles', {
75
- text: commands.project.validate.spinners.allProfilesValidationSucceeded,
76
- });
77
- }
78
- else {
79
- SpinniesManager.fail('validatingAllProfiles', {
80
- text: commands.project.validate.spinners.allProfilesValidationFailed,
81
- });
82
- }
83
- logValidationErrors(errors);
84
80
  }
85
- else if (profiles.length === 0) {
86
- // If the project has no profiles, validate the project without a profile
87
- try {
88
- await handleTranslate({
89
- projectDir: projectDir,
90
- projectConfig,
91
- accountId: derivedAccountId,
92
- skipValidation: false,
93
- });
94
- }
95
- catch (e) {
96
- uiLogger.error(commands.project.validate.failure(projectConfig.name));
97
- logError(e);
98
- validationSucceeded = false;
99
- uiLogger.log('');
100
- }
101
- }
102
- if (!validationSucceeded) {
81
+ catch (error) {
82
+ outputError(error);
103
83
  return exit(EXIT_CODES.ERROR);
104
84
  }
105
- try {
106
- await validateSourceDirectory(srcDir, projectConfig, projectDir);
107
- }
108
- catch (e) {
109
- logError(e);
85
+ addJsonOutput(generateJson({ result, projectConfig, profile }));
86
+ if (!result.valid) {
110
87
  return exit(EXIT_CODES.ERROR);
111
88
  }
112
89
  uiLogger.success(commands.project.validate.success(projectConfig.name));
@@ -127,30 +104,23 @@ function projectValidateBuilder(yargs) {
127
104
  '$0 project validate --profile=profileName',
128
105
  commands.project.validate.examples.withProfile,
129
106
  ],
107
+ ['$0 project validate --json', commands.project.validate.examples.json],
130
108
  ]);
131
109
  return yargs;
132
110
  }
133
- function logValidationErrors(validationErrors) {
134
- uiLogger.log('');
135
- validationErrors.forEach(error => {
136
- if (error instanceof Error) {
137
- logError(error);
138
- }
139
- else {
140
- uiLogger.log(error);
141
- }
142
- });
143
- }
144
111
  const builder = makeYargsBuilder(projectValidateBuilder, command, describe, {
145
112
  useGlobalOptions: true,
146
113
  useConfigOptions: true,
147
114
  useAccountOptions: true,
148
115
  useEnvironmentOptions: true,
116
+ useJSONOutputOptions: true,
149
117
  });
150
118
  const projectValidateCommand = {
151
119
  command,
152
120
  describe,
153
- handler: makeWrappedYargsHandler('project-validate', handler),
121
+ handler: makeWrappedYargsHandler('project-validate', handler, {
122
+ jsonOutputSchema: ValidateSchema,
123
+ }),
154
124
  builder,
155
125
  };
156
126
  export default projectValidateCommand;
@@ -6,7 +6,7 @@ import { createWatcher } from '../../lib/projects/watch.js';
6
6
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
7
7
  import { uiLogger } from '../../lib/ui/logger.js';
8
8
  import { PROJECT_ERROR_TYPES } from '../../lib/constants.js';
9
- import { getProjectConfig, validateProjectConfig, } from '../../lib/projects/config.js';
9
+ import { getProjectConfig } from '../../lib/projects/config.js';
10
10
  import { logFeedbackMessage } from '../../lib/projects/ui.js';
11
11
  import { handleProjectUpload } from '../../lib/projects/upload.js';
12
12
  import { pollBuildStatus, pollDeployStatus, } from '../../lib/projects/pollProjectBuildAndDeploy.js';
@@ -58,22 +58,19 @@ function handleUserInput(accountId, projectName, currentBuildId, exit) {
58
58
  async function handler(args) {
59
59
  const { initialUpload, derivedAccountId, exit } = args;
60
60
  uiCommandRelocatedMessage('hs project dev');
61
- const { projectConfig, projectDir } = await getProjectConfig();
62
- if (!projectConfig || !projectDir) {
63
- uiLogger.error(commands.project.watch.errors.projectConfigNotFound);
64
- return exit(EXIT_CODES.ERROR);
65
- }
66
- if (!isLegacyProject(projectConfig.platformVersion)) {
67
- uiLogger.error(commands.project.watch.errors.v2ApiError(projectConfig.platformVersion));
68
- return exit(EXIT_CODES.ERROR);
69
- }
61
+ let projectConfig;
62
+ let projectDir;
70
63
  try {
71
- validateProjectConfig(projectConfig, projectDir);
64
+ ({ projectConfig, projectDir } = getProjectConfig());
72
65
  }
73
66
  catch (error) {
74
67
  logError(error);
75
68
  return exit(EXIT_CODES.ERROR);
76
69
  }
70
+ if (!isLegacyProject(projectConfig.platformVersion)) {
71
+ uiLogger.error(commands.project.watch.errors.v2ApiError(projectConfig.platformVersion));
72
+ return exit(EXIT_CODES.ERROR);
73
+ }
77
74
  try {
78
75
  const { data: { results: builds }, } = await fetchProjectBuilds(derivedAccountId, projectConfig.name);
79
76
  const hasNoBuilds = !builds || !builds.length;
@@ -33,7 +33,7 @@ const describe = commands.project.describe;
33
33
  // the CLI is not officially compatible with
34
34
  async function validatePlatformVersion() {
35
35
  try {
36
- const { projectConfig } = await getProjectConfig();
36
+ const { projectConfig } = getProjectConfig();
37
37
  // Only warn if a platform version is explicitly set but not supported
38
38
  // Don't warn if the platform version is missing/undefined
39
39
  if (projectConfig?.platformVersion &&
@@ -1,6 +1,6 @@
1
1
  import { AccountLevel } from '@hubspot/local-dev-lib/types/developerTestAccounts.js';
2
2
  import { CommonArgs, ConfigArgs, AccountArgs, TestingArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
3
- import { CreateTestAccountJsonOutput } from '../../lib/jsonOutput.js';
3
+ import { CreateTestAccountJsonOutput } from '../../lib/jsonOutput/createTestAccount.js';
4
4
  type CreateTestAccountArgs = CommonArgs & AccountArgs & ConfigArgs & TestingArgs & EnvironmentArgs & JSONOutputArgs<CreateTestAccountJsonOutput> & {
5
5
  configPath?: string;
6
6
  name?: string;
@@ -4,7 +4,7 @@ import { getValidEnv } from '@hubspot/local-dev-lib/environment';
4
4
  import { getConfigAccountEnvironment } from '@hubspot/local-dev-lib/config';
5
5
  import { getCwd } from '@hubspot/local-dev-lib/path';
6
6
  import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
7
- import { CreateTestAccountSchema, } from '../../lib/jsonOutput.js';
7
+ import { CreateTestAccountSchema, } from '../../lib/jsonOutput/createTestAccount.js';
8
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
9
  import { promptUser, listPrompt } from '../../lib/prompts/promptUtils.js';
10
10
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
package/lang/en.d.ts CHANGED
@@ -1466,7 +1466,6 @@ export declare const commands: {
1466
1466
  duplicateTargetAccount: (targetAccountId: number) => string;
1467
1467
  };
1468
1468
  errors: {
1469
- noProjectConfig: string;
1470
1469
  unsupportedPlatformVersion: string;
1471
1470
  profileExists: (profileName: string) => string;
1472
1471
  invalidTargetAccount: string;
@@ -1499,7 +1498,6 @@ export declare const commands: {
1499
1498
  deleteProjectPrompt: (accountId: number) => string;
1500
1499
  };
1501
1500
  errors: {
1502
- noProjectConfig: string;
1503
1501
  unsupportedPlatformVersion: string;
1504
1502
  noProfileFound: (profileName: string) => string;
1505
1503
  noProfilesFound: string;
@@ -1523,7 +1521,6 @@ export declare const commands: {
1523
1521
  testingAccountFlagExplanation: (accountId: number) => string;
1524
1522
  };
1525
1523
  errors: {
1526
- noProjectConfig: string;
1527
1524
  noAccount: (accountId: number) => string;
1528
1525
  unsupportedPlatformVersion: (platformVersion: string) => string;
1529
1526
  noRunnableComponents: string;
@@ -1649,7 +1646,6 @@ export declare const commands: {
1649
1646
  describe: string;
1650
1647
  errors: {
1651
1648
  noProjectConfig: (command: string) => string;
1652
- noThemeMigrationAccess: (accountId?: number) => string;
1653
1649
  };
1654
1650
  examples: {
1655
1651
  default: string;
@@ -1912,9 +1908,11 @@ export declare const commands: {
1912
1908
  autoDeployDisabled: (deployCommand: string) => string;
1913
1909
  autoDeploySkipped: (deployCommand: string) => string;
1914
1910
  releaseManagementRequired: (releaseCommand: string) => string;
1911
+ uploadingWithProfile: (profileName: string, accountId: number) => string;
1912
+ uploadingToAccount: (accountId: number) => string;
1913
+ uploadedToAccount: (accountId: number) => string;
1915
1914
  };
1916
1915
  errors: {
1917
- noProjectConfig: string;
1918
1916
  projectLockedError: string;
1919
1917
  previewRequiresTarget: string;
1920
1918
  targetRequiresPreview: string;
@@ -1976,7 +1974,6 @@ export declare const commands: {
1976
1974
  fileAlreadyQueued: (filePath: string) => string;
1977
1975
  };
1978
1976
  errors: {
1979
- projectConfigNotFound: string;
1980
1977
  projectLockedError: string;
1981
1978
  uploadFailed: (remotePath: string, filePath: string) => string;
1982
1979
  deleteFileFailed: (remotePath: string) => string;
@@ -1988,6 +1985,7 @@ export declare const commands: {
1988
1985
  describe: string;
1989
1986
  examples: {
1990
1987
  default: string;
1988
+ json: string;
1991
1989
  };
1992
1990
  logs: {
1993
1991
  downloadCancelled: string;
@@ -2043,7 +2041,6 @@ export declare const commands: {
2043
2041
  installationSuccessful: (directory: string) => string;
2044
2042
  addingDependenciesToLocation: (dependencies: string, directory: string) => string;
2045
2043
  installingDependenciesFailed: (directory: string) => string;
2046
- noProjectConfig: string;
2047
2044
  noPackageJsonInProject: (projectName: string) => string;
2048
2045
  packageManagerNotInstalled: (packageManager: string) => string;
2049
2046
  };
@@ -2061,7 +2058,6 @@ export declare const commands: {
2061
2058
  addingLintScripts: string;
2062
2059
  linting: string;
2063
2060
  };
2064
- noProjectConfig: string;
2065
2061
  failedToReadPackageJson: (packageJsonPath: string) => string;
2066
2062
  installLintPackagesPrompt: (directories: string[], missingPackages: string[]) => string;
2067
2063
  skippingDirectoriesWarning: (directories: string[]) => string;
@@ -2091,7 +2087,6 @@ export declare const commands: {
2091
2087
  updateSuccessful: (directory: string) => string;
2092
2088
  updatingDependenciesToLocation: (dependencies: string, directory: string) => string;
2093
2089
  updatingDependenciesFailed: (directory: string) => string;
2094
- noProjectConfig: string;
2095
2090
  noPackageJsonInProject: (projectName: string) => string;
2096
2091
  packageManagerNotInstalled: (packageManager: string) => string;
2097
2092
  };
@@ -2102,6 +2097,7 @@ export declare const commands: {
2102
2097
  examples: {
2103
2098
  default: string;
2104
2099
  withProfile: string;
2100
+ json: string;
2105
2101
  };
2106
2102
  success: (projectName: string) => string;
2107
2103
  failure: (projectName: string, profileName?: string) => string;
@@ -2128,6 +2124,10 @@ export declare const commands: {
2128
2124
  name: string;
2129
2125
  platformVersion: string;
2130
2126
  };
2127
+ examples: {
2128
+ default: string;
2129
+ json: string;
2130
+ };
2131
2131
  errors: {
2132
2132
  noProjectsFound: (accountId: number) => string;
2133
2133
  };
@@ -2161,7 +2161,6 @@ export declare const commands: {
2161
2161
  uid: string;
2162
2162
  };
2163
2163
  errors: {
2164
- noProjectConfig: string;
2165
2164
  projectNotFound: (projectName: string, accountId: number) => string;
2166
2165
  noDeployedBuild: string;
2167
2166
  unsupportedPlatformVersion: (platformVersion: string) => string;
@@ -2223,7 +2222,6 @@ export declare const commands: {
2223
2222
  profile: string;
2224
2223
  };
2225
2224
  errors: {
2226
- noProjectConfig: string;
2227
2225
  unsupportedPlatformVersion: (platformVersion: string) => string;
2228
2226
  failedToParseProject: string;
2229
2227
  noAppInProject: string;
@@ -2257,7 +2255,6 @@ export declare const commands: {
2257
2255
  json: string;
2258
2256
  };
2259
2257
  errors: {
2260
- noProjectConfig: string;
2261
2258
  unsupportedPlatformVersion: (platformVersion: string) => string;
2262
2259
  failedToParseProject: string;
2263
2260
  noAppInProject: string;
@@ -3548,7 +3545,6 @@ export declare const lib: {
3548
3545
  };
3549
3546
  loadProfile: {
3550
3547
  errors: {
3551
- noProjectConfig: string;
3552
3548
  profileNotFound: (profileName: string) => string;
3553
3549
  missingAccountId: (profileName: string) => string;
3554
3550
  listedAccountNotFound: (accountId: number, profileName: string) => string;
@@ -3590,12 +3586,6 @@ export declare const lib: {
3590
3586
  };
3591
3587
  validateProjectConfig: {
3592
3588
  configNotFound: string;
3593
- configMissingFields: (missingFields: string[]) => string;
3594
- srcDirNotFound: (srcDir: string, projectDir: string) => string;
3595
- srcOutsideProjectDir: (projectConfig: string, srcDir: string) => string;
3596
- };
3597
- getProjectConfig: {
3598
- error: string;
3599
3589
  };
3600
3590
  platformVersion: {
3601
3591
  unsupported: (currentCliVersion: string, latestSupported: string, platformVersion?: string) => string;
package/lang/en.js CHANGED
@@ -1482,7 +1482,6 @@ export const commands = {
1482
1482
  duplicateTargetAccount: (targetAccountId) => `The account ${uiAccountDescription(targetAccountId)} is being used in an existing profile. Make sure to edit your project's name between uploads if you do not want to overwrite the existing project in this account.`,
1483
1483
  },
1484
1484
  errors: {
1485
- noProjectConfig: 'No project config found. Please run this command from a project directory.',
1486
1485
  unsupportedPlatformVersion: 'This command is only available for projects 2025.2 and later.',
1487
1486
  profileExists: (profileName) => `Profile ${chalk.bold(profileName)} already exists. Please choose a different name.`,
1488
1487
  invalidTargetAccount: 'Target account is not configured in the CLI',
@@ -1515,7 +1514,6 @@ export const commands = {
1515
1514
  deleteProjectPrompt: (accountId) => `Would you like to delete this project from ${uiAccountDescription(accountId)}?`,
1516
1515
  },
1517
1516
  errors: {
1518
- noProjectConfig: 'No project config found. Please run this command from a project directory.',
1519
1517
  unsupportedPlatformVersion: 'This command is only available for projects 2025.2 and later.',
1520
1518
  noProfileFound: (profileName) => `No profile with filename ${chalk.bold(profileName)} found in your project.`,
1521
1519
  noProfilesFound: 'No profiles found in your project.',
@@ -1539,7 +1537,6 @@ export const commands = {
1539
1537
  testingAccountFlagExplanation: (accountId) => `Using account ${uiAccountDescription(accountId)} provided by the --testing-account flag for testing`,
1540
1538
  },
1541
1539
  errors: {
1542
- noProjectConfig: 'No project detected. Please run this command again from a project directory.',
1543
1540
  noAccount: (accountId) => `An error occurred while reading account ${uiAccountDescription(accountId)} from your config. Run ${uiAuthCommandReference()} to re-auth this account.`,
1544
1541
  unsupportedPlatformVersion: (platformVersion) => `Local development is not supported for platform version ${chalk.bold(platformVersion)}. Please upgrade to 2025.2 or later.`,
1545
1542
  noRunnableComponents: `No supported components were found in this project. Run ${uiCommandReference('hs project add')} to see a list of available components and add one to your project.`,
@@ -1665,7 +1662,6 @@ export const commands = {
1665
1662
  describe: 'Migrate an existing project to the new version of the projects framework.',
1666
1663
  errors: {
1667
1664
  noProjectConfig: (command) => `No project detected. Please run this command again from a project directory. If you are trying to migrate an app, run ${command}`,
1668
- noThemeMigrationAccess: (accountId) => `This project contains a CMS theme. You must opt in to theme migration beta to continue updating it on ${uiAccountDescription(accountId)}. Try again with a different account or ${uiLink('join the beta now', getProductUpdatesUrl('253920', accountId))}`,
1669
1665
  },
1670
1666
  examples: {
1671
1667
  default: 'Migrate an existing project to the new version of the projects framework.',
@@ -1928,9 +1924,11 @@ export const commands = {
1928
1924
  autoDeployDisabled: (deployCommand) => `Automatic deploys are disabled for this project. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
1929
1925
  autoDeploySkipped: (deployCommand) => `Auto-deploy was skipped for this build. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
1930
1926
  releaseManagementRequired: (releaseCommand) => `Run ${uiCommandReference(releaseCommand)} to create a release for this build.`,
1927
+ uploadingWithProfile: (profileName, accountId) => `Initializing project upload with ${chalk.bold(profileName)} profile: ${uiAccountDescription(accountId)}`,
1928
+ uploadingToAccount: (accountId) => `Initializing project upload to account ${uiAccountDescription(accountId)}`,
1929
+ uploadedToAccount: (accountId) => `Project uploaded to ${uiAccountDescription(accountId)}`,
1931
1930
  },
1932
1931
  errors: {
1933
- noProjectConfig: 'No project detected. Run this command from a project directory.',
1934
1932
  projectLockedError: `Your project is locked. This may mean that another user is running the ${uiCommandReference('hs project dev')} command for this project. If this is you, unlock the project in Projects UI.`,
1935
1933
  previewRequiresTarget: `${uiCommandReference('--preview')} requires ${uiCommandReference('--target=<portalId>')} to specify the portal to preview on.`,
1936
1934
  targetRequiresPreview: `${uiCommandReference('--target')} can only be used with ${uiCommandReference('--preview')}.`,
@@ -1992,7 +1990,6 @@ export const commands = {
1992
1990
  fileAlreadyQueued: (filePath) => `File "${filePath}" is already queued for upload`,
1993
1991
  },
1994
1992
  errors: {
1995
- projectConfigNotFound: 'No project config found. Please ensure that you are in a project directory.',
1996
1993
  projectLockedError: `Your project is locked. This may mean that another user is running the ${chalk.bold(`hs project dev`)} command for this project. If this is you, unlock the project in Projects UI.`,
1997
1994
  uploadFailed: (remotePath, filePath) => `Failed to upload file "${filePath}" to "${remotePath}"`,
1998
1995
  deleteFileFailed: (remotePath) => `Failed to delete file "${remotePath}"`,
@@ -2004,6 +2001,7 @@ export const commands = {
2004
2001
  describe: 'Download your project files from HubSpot.',
2005
2002
  examples: {
2006
2003
  default: 'Download the project myProject into myProjectFolder folder',
2004
+ json: 'Output the download result as JSON for scripting',
2007
2005
  },
2008
2006
  logs: {
2009
2007
  downloadCancelled: 'Cancelling project download',
@@ -2059,7 +2057,6 @@ export const commands = {
2059
2057
  installationSuccessful: (directory) => `Installed dependencies in ${directory}`,
2060
2058
  addingDependenciesToLocation: (dependencies, directory) => `Installing ${dependencies} in ${directory}`,
2061
2059
  installingDependenciesFailed: (directory) => `Installing dependencies for ${directory} failed`,
2062
- noProjectConfig: 'No project detected. Run this command from a project directory.',
2063
2060
  noPackageJsonInProject: (projectName) => `No dependencies to install. The project ${projectName} folder might be missing component or subcomponent files. ${uiLink('Learn how to create a project from scratch', 'https://developers.hubspot.com/docs/apps/developer-platform/build-apps/create-an-app#customize-a-new-project-using-the-cli')}`,
2064
2061
  packageManagerNotInstalled: (packageManager) => `This command depends on ${packageManager}, install ${uiLink(packageManager, 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm')}`,
2065
2062
  },
@@ -2077,7 +2074,6 @@ export const commands = {
2077
2074
  addingLintScripts: 'Adding lint scripts to package.json files…',
2078
2075
  linting: 'Linting…',
2079
2076
  },
2080
- noProjectConfig: 'No project detected. Run this command from a project directory.',
2081
2077
  failedToReadPackageJson: (packageJsonPath) => `Failed to read package.json at ${packageJsonPath}`,
2082
2078
  installLintPackagesPrompt: (directories, missingPackages) => {
2083
2079
  const uniquePackages = Array.from(new Set(missingPackages)).sort();
@@ -2119,7 +2115,6 @@ export const commands = {
2119
2115
  updateSuccessful: (directory) => `Updated dependencies in ${directory}`,
2120
2116
  updatingDependenciesToLocation: (dependencies, directory) => `Updating ${dependencies} in ${directory}`,
2121
2117
  updatingDependenciesFailed: (directory) => `Updating dependencies for ${directory} failed`,
2122
- noProjectConfig: 'No project detected. Run this command from a project directory.',
2123
2118
  noPackageJsonInProject: (projectName) => `No dependencies to update. The project ${projectName} folder might be missing component or subcomponent files. ${uiLink('Learn how to create a project from scratch', 'https://developers.hubspot.com/docs/apps/developer-platform/build-apps/create-an-app#customize-a-new-project-using-the-cli')}`,
2124
2119
  packageManagerNotInstalled: (packageManager) => `This command depends on ${packageManager}, install ${uiLink(packageManager, 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm')}`,
2125
2120
  },
@@ -2130,6 +2125,7 @@ export const commands = {
2130
2125
  examples: {
2131
2126
  default: 'Validate the project before uploading',
2132
2127
  withProfile: 'Validate the project with a profile before uploading.',
2128
+ json: 'Output validation results as JSON for scripting',
2133
2129
  },
2134
2130
  success: (projectName) => `Project ${projectName} is valid and ready to upload`,
2135
2131
  failure: (projectName, profileName) => `Project ${projectName} is invalid${profileName ? ` with profile "${profileName}" applied` : ''}`,
@@ -2156,6 +2152,10 @@ export const commands = {
2156
2152
  name: 'Name',
2157
2153
  platformVersion: 'Platform Version',
2158
2154
  },
2155
+ examples: {
2156
+ default: 'List projects in the target account',
2157
+ json: 'Output as JSON for scripting',
2158
+ },
2159
2159
  errors: {
2160
2160
  noProjectsFound: (accountId) => `No projects found for account ${uiAccountDescription(accountId)}`,
2161
2161
  },
@@ -2189,7 +2189,6 @@ export const commands = {
2189
2189
  uid: 'UID',
2190
2190
  },
2191
2191
  errors: {
2192
- noProjectConfig: `No project found in this directory.\n\nRun ${uiCommandReference('hs project create')} to start a new project, or change to a directory containing hsproject.json.`,
2193
2192
  projectNotFound: (projectName, accountId) => `Project "${projectName}" was not found in account ${uiAccountDescription(accountId)}. Make sure the project has been uploaded at least once.`,
2194
2193
  noDeployedBuild: `This project has not been deployed yet.\n\nRun ${uiCommandReference('hs project deploy')} to deploy your project.`,
2195
2194
  unsupportedPlatformVersion: (platformVersion) => `This command is not supported for platform version ${chalk.bold(platformVersion)}. Please upgrade to 2025.2 or later.`,
@@ -2248,7 +2247,6 @@ export const commands = {
2248
2247
  profile: 'The profile to target with this install',
2249
2248
  },
2250
2249
  errors: {
2251
- noProjectConfig: `No project config found. Run this command from within a HubSpot project directory, or use ${uiCommandReference('hs project create')} to create a new one.`,
2252
2250
  unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
2253
2251
  failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
2254
2252
  noAppInProject: 'No app was found in the local project. This command requires a project that contains an app.',
@@ -2282,7 +2280,6 @@ export const commands = {
2282
2280
  json: 'Output install status as JSON',
2283
2281
  },
2284
2282
  errors: {
2285
- noProjectConfig: `No project config found. Run this command from within a HubSpot project directory, or use ${uiCommandReference('hs project create')} to create a new one.`,
2286
2283
  unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
2287
2284
  failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
2288
2285
  noAppInProject: 'No app was found in the local project. Install status is only available for projects that contain an app.',
@@ -3587,7 +3584,6 @@ export const lib = {
3587
3584
  },
3588
3585
  loadProfile: {
3589
3586
  errors: {
3590
- noProjectConfig: 'No project config found. Please run this command from a project directory.',
3591
3587
  profileNotFound: (profileName) => `Profile ${chalk.bold(profileName)} not found.`,
3592
3588
  missingAccountId: (profileName) => `Profile ${chalk.bold(profileName)} is missing an account id.`,
3593
3589
  listedAccountNotFound: (accountId, profileName) => `The account ${uiAccountDescription(accountId)} is defined in your profile ${chalk.bold(profileName)}, but is missing in your config file`,
@@ -3629,12 +3625,6 @@ export const lib = {
3629
3625
  },
3630
3626
  validateProjectConfig: {
3631
3627
  configNotFound: `Unable to locate a project configuration file. Try running again from a project directory, or run ${uiCommandReference('hs project create')} to create a new project.`,
3632
- configMissingFields: (missingFields) => `The project configuration file is missing required field${missingFields.length > 1 ? 's' : ''}: ${missingFields.map(f => chalk.bold(f)).join(', ')}`,
3633
- srcDirNotFound: (srcDir, projectDir) => `Project source directory ${chalk.bold(srcDir)} could not be found in ${chalk.bold(projectDir)}.`,
3634
- srcOutsideProjectDir: (projectConfig, srcDir) => `Invalid value for 'srcDir' in ${projectConfig}: ${chalk.bold(`srcDir: "${srcDir}"`)}\n\t'srcDir' must be a relative path to a folder under the project root, such as "." or "./src"`,
3635
- },
3636
- getProjectConfig: {
3637
- error: 'Could not read from project config',
3638
3628
  },
3639
3629
  platformVersion: {
3640
3630
  unsupported: (currentCliVersion, latestSupported, platformVersion) => `Platform version${platformVersion ? ' ' + chalk.bold(platformVersion) : ''} is not officially supported by this version of the CLI (${chalk.bold(currentCliVersion)}).\n\nUpdate your CLI to the latest version with ${uiCommandReference('hs upgrade')} or use a compatible platform version (${chalk.bold(latestSupported)} or earlier).`,
@@ -39,7 +39,7 @@ export function getUnmigratableReason(reasonCode, projectName, accountId) {
39
39
  export function generateFilterAppsByProjectNameFunction(projectConfig) {
40
40
  return (app) => {
41
41
  if (projectConfig) {
42
- return app.projectName === projectConfig?.projectConfig?.name;
42
+ return app.projectName === projectConfig.projectConfig.name;
43
43
  }
44
44
  return true;
45
45
  };
@@ -70,7 +70,7 @@ export async function validateMigrationApps(appId, derivedAccountId, { migratabl
70
70
  if (allApps.length > 1 && projectConfig) {
71
71
  throw new Error(lib.migrate.errors.project.multipleApps);
72
72
  }
73
- if (!projectConfig?.projectConfig) {
73
+ if (!projectConfig) {
74
74
  allApps.forEach(app => {
75
75
  if (app.projectName) {
76
76
  app.isMigratable = false;
@@ -80,7 +80,7 @@ export async function validateMigrationApps(appId, derivedAccountId, { migratabl
80
80
  });
81
81
  }
82
82
  if (allApps.length === 0 && projectConfig) {
83
- throw new Error(lib.migrate.errors.noAppsForProject(projectConfig?.projectConfig?.name || ''));
83
+ throw new Error(lib.migrate.errors.noAppsForProject(projectConfig.projectConfig.name));
84
84
  }
85
85
  if (allApps.length === 0 || !allApps.some(app => app.isMigratable)) {
86
86
  const reasons = unmigratableApps.map(app => `${chalk.bold(app.appName)}: ${getUnmigratableReason(app.unmigratableReason, app.projectName, derivedAccountId)}`);
@@ -173,9 +173,7 @@ export async function handleMigrationSetup(derivedAccountId, options, projectCon
173
173
  return {};
174
174
  }
175
175
  // If it's a project we don't want to prompt for dest and name, so just return early
176
- if (projectConfig &&
177
- projectConfig?.projectConfig &&
178
- projectConfig?.projectDir) {
176
+ if (projectConfig) {
179
177
  return {
180
178
  appIdToMigrate,
181
179
  projectName: projectConfig.projectConfig.name,
@@ -309,7 +307,7 @@ export async function downloadProjectFiles(derivedAccountId, projectName, buildI
309
307
  });
310
308
  const { data: zippedProject } = await downloadProject(derivedAccountId, projectName, buildId);
311
309
  let absoluteDestPath;
312
- if (projectConfig?.projectConfig && projectConfig?.projectDir) {
310
+ if (projectConfig) {
313
311
  const { projectDir } = projectConfig;
314
312
  absoluteDestPath = projectDir;
315
313
  const { srcDir } = projectConfig.projectConfig;
@@ -80,7 +80,6 @@ export declare const APP_AUTH_TYPES: {
80
80
  export declare const FEATURES: {
81
81
  readonly UNIFIED_APPS: "Developers:UnifiedApps:PrivateBeta";
82
82
  readonly APP_EVENTS: "Developers:UnifiedApps:AppEventsAccess";
83
- readonly THEME_MIGRATION_2025_2: "Developers:ProjectThemeMigrations:2025.2";
84
83
  readonly AGENT_TOOLS: "ThirdPartyAgentTools";
85
84
  readonly APP_ACTIONS: "Developers:AppActions";
86
85
  };
package/lib/constants.js CHANGED
@@ -72,7 +72,6 @@ export const APP_AUTH_TYPES = {
72
72
  export const FEATURES = {
73
73
  UNIFIED_APPS: 'Developers:UnifiedApps:PrivateBeta',
74
74
  APP_EVENTS: 'Developers:UnifiedApps:AppEventsAccess',
75
- THEME_MIGRATION_2025_2: 'Developers:ProjectThemeMigrations:2025.2',
76
75
  AGENT_TOOLS: 'ThirdPartyAgentTools',
77
76
  APP_ACTIONS: 'Developers:AppActions',
78
77
  };