@hubspot/cli 8.14.0 → 8.15.0-beta.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 (91) hide show
  1. package/commands/cms/theme/preview.js +8 -1
  2. package/commands/getStarted.js +15 -20
  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 +20 -6
  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.js +3 -3
  12. package/commands/project/info.d.ts +1 -1
  13. package/commands/project/info.js +8 -5
  14. package/commands/project/installApp.d.ts +1 -1
  15. package/commands/project/installApp.js +9 -4
  16. package/commands/project/installDeps.js +6 -5
  17. package/commands/project/lint.js +16 -9
  18. package/commands/project/list.d.ts +3 -2
  19. package/commands/project/list.js +21 -3
  20. package/commands/project/listBuilds.d.ts +1 -1
  21. package/commands/project/listBuilds.js +4 -8
  22. package/commands/project/migrate.js +14 -12
  23. package/commands/project/open.js +15 -7
  24. package/commands/project/profile/add.js +8 -4
  25. package/commands/project/profile/delete.js +8 -4
  26. package/commands/project/release/create.d.ts +1 -1
  27. package/commands/project/release/create.js +5 -7
  28. package/commands/project/release/info.d.ts +1 -1
  29. package/commands/project/release/info.js +4 -4
  30. package/commands/project/release/list.d.ts +1 -1
  31. package/commands/project/release/list.js +4 -4
  32. package/commands/project/updateDeps.js +6 -5
  33. package/commands/project/upload.d.ts +1 -1
  34. package/commands/project/upload.js +26 -15
  35. package/commands/project/validate.js +14 -97
  36. package/commands/project/watch.js +8 -11
  37. package/commands/project.js +1 -1
  38. package/commands/testAccount/create.d.ts +1 -1
  39. package/commands/testAccount/create.js +1 -1
  40. package/lang/en.d.ts +7 -18
  41. package/lang/en.js +7 -18
  42. package/lib/app/migrate.js +5 -7
  43. package/lib/dependencyManagement.js +3 -10
  44. package/lib/doctor/DiagnosticInfoBuilder.d.ts +2 -2
  45. package/lib/doctor/DiagnosticInfoBuilder.js +8 -8
  46. package/lib/doctor/Doctor.js +7 -9
  47. package/lib/errors/ProjectErrors.d.ts +0 -6
  48. package/lib/errors/ProjectErrors.js +0 -12
  49. package/lib/errors/ProjectValidationError.d.ts +2 -1
  50. package/lib/errors/ProjectValidationError.js +3 -1
  51. package/lib/getStartedV2Actions.js +14 -18
  52. package/lib/jsonOutput/appInstallStatus.d.ts +14 -0
  53. package/lib/jsonOutput/appInstallStatus.js +14 -0
  54. package/lib/jsonOutput/createTestAccount.d.ts +7 -0
  55. package/lib/jsonOutput/createTestAccount.js +6 -0
  56. package/lib/jsonOutput/deploy.d.ts +5 -0
  57. package/lib/jsonOutput/deploy.js +4 -0
  58. package/lib/jsonOutput/info.d.ts +21 -0
  59. package/lib/jsonOutput/info.js +19 -0
  60. package/lib/jsonOutput/installApp.d.ts +11 -0
  61. package/lib/jsonOutput/installApp.js +10 -0
  62. package/lib/jsonOutput/listBuilds.d.ts +75 -0
  63. package/lib/jsonOutput/listBuilds.js +65 -0
  64. package/lib/jsonOutput/projectList.d.ts +29 -0
  65. package/lib/jsonOutput/projectList.js +28 -0
  66. package/lib/jsonOutput/release.d.ts +42 -0
  67. package/lib/jsonOutput/release.js +37 -0
  68. package/lib/jsonOutput/upload.d.ts +29 -0
  69. package/lib/jsonOutput/upload.js +23 -0
  70. package/lib/npm/packageJson.js +1 -1
  71. package/lib/projects/ProjectLogsManager.js +1 -4
  72. package/lib/projects/config.d.ts +6 -5
  73. package/lib/projects/config.js +7 -38
  74. package/lib/projects/create/tracking.d.ts +1 -0
  75. package/lib/projects/create/tracking.js +27 -0
  76. package/lib/projects/delete.js +14 -1
  77. package/lib/projects/localDev/LocalDevProcess.js +7 -7
  78. package/lib/projects/projectProfiles.d.ts +2 -2
  79. package/lib/projects/projectProfiles.js +0 -3
  80. package/lib/projects/release.js +1 -1
  81. package/lib/projects/uieLinting.js +0 -3
  82. package/lib/projects/validate.d.ts +9 -0
  83. package/lib/projects/validate.js +96 -0
  84. package/lib/theme/migrate.js +1 -4
  85. package/mcp-server/tools/project/GetBuildLogsTool.js +2 -3
  86. package/mcp-server/tools/project/GetBuildStatusTool.js +2 -3
  87. package/mcp-server/tools/project/UploadProjectTools.js +3 -5
  88. package/package.json +3 -3
  89. package/types/Projects.d.ts +1 -5
  90. package/lib/jsonOutput.d.ts +0 -182
  91. package/lib/jsonOutput.js +0 -158
@@ -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;
@@ -1912,9 +1909,11 @@ export declare const commands: {
1912
1909
  autoDeployDisabled: (deployCommand: string) => string;
1913
1910
  autoDeploySkipped: (deployCommand: string) => string;
1914
1911
  releaseManagementRequired: (releaseCommand: string) => string;
1912
+ uploadingWithProfile: (profileName: string, accountId: number) => string;
1913
+ uploadingToAccount: (accountId: number) => string;
1914
+ uploadedToAccount: (accountId: number) => string;
1915
1915
  };
1916
1916
  errors: {
1917
- noProjectConfig: string;
1918
1917
  projectLockedError: string;
1919
1918
  previewRequiresTarget: string;
1920
1919
  targetRequiresPreview: string;
@@ -1976,7 +1975,6 @@ export declare const commands: {
1976
1975
  fileAlreadyQueued: (filePath: string) => string;
1977
1976
  };
1978
1977
  errors: {
1979
- projectConfigNotFound: string;
1980
1978
  projectLockedError: string;
1981
1979
  uploadFailed: (remotePath: string, filePath: string) => string;
1982
1980
  deleteFileFailed: (remotePath: string) => 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
  };
@@ -2128,6 +2123,10 @@ export declare const commands: {
2128
2123
  name: string;
2129
2124
  platformVersion: string;
2130
2125
  };
2126
+ examples: {
2127
+ default: string;
2128
+ json: string;
2129
+ };
2131
2130
  errors: {
2132
2131
  noProjectsFound: (accountId: number) => string;
2133
2132
  };
@@ -2161,7 +2160,6 @@ export declare const commands: {
2161
2160
  uid: string;
2162
2161
  };
2163
2162
  errors: {
2164
- noProjectConfig: string;
2165
2163
  projectNotFound: (projectName: string, accountId: number) => string;
2166
2164
  noDeployedBuild: string;
2167
2165
  unsupportedPlatformVersion: (platformVersion: string) => string;
@@ -2223,7 +2221,6 @@ export declare const commands: {
2223
2221
  profile: string;
2224
2222
  };
2225
2223
  errors: {
2226
- noProjectConfig: string;
2227
2224
  unsupportedPlatformVersion: (platformVersion: string) => string;
2228
2225
  failedToParseProject: string;
2229
2226
  noAppInProject: string;
@@ -2257,7 +2254,6 @@ export declare const commands: {
2257
2254
  json: string;
2258
2255
  };
2259
2256
  errors: {
2260
- noProjectConfig: string;
2261
2257
  unsupportedPlatformVersion: (platformVersion: string) => string;
2262
2258
  failedToParseProject: string;
2263
2259
  noAppInProject: string;
@@ -3548,7 +3544,6 @@ export declare const lib: {
3548
3544
  };
3549
3545
  loadProfile: {
3550
3546
  errors: {
3551
- noProjectConfig: string;
3552
3547
  profileNotFound: (profileName: string) => string;
3553
3548
  missingAccountId: (profileName: string) => string;
3554
3549
  listedAccountNotFound: (accountId: number, profileName: string) => string;
@@ -3590,12 +3585,6 @@ export declare const lib: {
3590
3585
  };
3591
3586
  validateProjectConfig: {
3592
3587
  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
3588
  };
3600
3589
  platformVersion: {
3601
3590
  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.`,
@@ -1928,9 +1925,11 @@ export const commands = {
1928
1925
  autoDeployDisabled: (deployCommand) => `Automatic deploys are disabled for this project. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
1929
1926
  autoDeploySkipped: (deployCommand) => `Auto-deploy was skipped for this build. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
1930
1927
  releaseManagementRequired: (releaseCommand) => `Run ${uiCommandReference(releaseCommand)} to create a release for this build.`,
1928
+ uploadingWithProfile: (profileName, accountId) => `Initializing project upload with ${chalk.bold(profileName)} profile: ${uiAccountDescription(accountId)}`,
1929
+ uploadingToAccount: (accountId) => `Initializing project upload to account ${uiAccountDescription(accountId)}`,
1930
+ uploadedToAccount: (accountId) => `Project uploaded to ${uiAccountDescription(accountId)}`,
1931
1931
  },
1932
1932
  errors: {
1933
- noProjectConfig: 'No project detected. Run this command from a project directory.',
1934
1933
  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
1934
  previewRequiresTarget: `${uiCommandReference('--preview')} requires ${uiCommandReference('--target=<portalId>')} to specify the portal to preview on.`,
1936
1935
  targetRequiresPreview: `${uiCommandReference('--target')} can only be used with ${uiCommandReference('--preview')}.`,
@@ -1992,7 +1991,6 @@ export const commands = {
1992
1991
  fileAlreadyQueued: (filePath) => `File "${filePath}" is already queued for upload`,
1993
1992
  },
1994
1993
  errors: {
1995
- projectConfigNotFound: 'No project config found. Please ensure that you are in a project directory.',
1996
1994
  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
1995
  uploadFailed: (remotePath, filePath) => `Failed to upload file "${filePath}" to "${remotePath}"`,
1998
1996
  deleteFileFailed: (remotePath) => `Failed to delete file "${remotePath}"`,
@@ -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
  },
@@ -2156,6 +2151,10 @@ export const commands = {
2156
2151
  name: 'Name',
2157
2152
  platformVersion: 'Platform Version',
2158
2153
  },
2154
+ examples: {
2155
+ default: 'List projects in the target account',
2156
+ json: 'Output as JSON for scripting',
2157
+ },
2159
2158
  errors: {
2160
2159
  noProjectsFound: (accountId) => `No projects found for account ${uiAccountDescription(accountId)}`,
2161
2160
  },
@@ -2189,7 +2188,6 @@ export const commands = {
2189
2188
  uid: 'UID',
2190
2189
  },
2191
2190
  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
2191
  projectNotFound: (projectName, accountId) => `Project "${projectName}" was not found in account ${uiAccountDescription(accountId)}. Make sure the project has been uploaded at least once.`,
2194
2192
  noDeployedBuild: `This project has not been deployed yet.\n\nRun ${uiCommandReference('hs project deploy')} to deploy your project.`,
2195
2193
  unsupportedPlatformVersion: (platformVersion) => `This command is not supported for platform version ${chalk.bold(platformVersion)}. Please upgrade to 2025.2 or later.`,
@@ -2248,7 +2246,6 @@ export const commands = {
2248
2246
  profile: 'The profile to target with this install',
2249
2247
  },
2250
2248
  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
2249
  unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
2253
2250
  failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
2254
2251
  noAppInProject: 'No app was found in the local project. This command requires a project that contains an app.',
@@ -2282,7 +2279,6 @@ export const commands = {
2282
2279
  json: 'Output install status as JSON',
2283
2280
  },
2284
2281
  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
2282
  unsupportedPlatformVersion: (platformVersion) => `This command is only supported for projects on platform version 2025.2 or later (detected: ${platformVersion}).`,
2287
2283
  failedToParseProject: 'Failed to parse the project. Check your project configuration is valid and try again.',
2288
2284
  noAppInProject: 'No app was found in the local project. Install status is only available for projects that contain an app.',
@@ -3587,7 +3583,6 @@ export const lib = {
3587
3583
  },
3588
3584
  loadProfile: {
3589
3585
  errors: {
3590
- noProjectConfig: 'No project config found. Please run this command from a project directory.',
3591
3586
  profileNotFound: (profileName) => `Profile ${chalk.bold(profileName)} not found.`,
3592
3587
  missingAccountId: (profileName) => `Profile ${chalk.bold(profileName)} is missing an account id.`,
3593
3588
  listedAccountNotFound: (accountId, profileName) => `The account ${uiAccountDescription(accountId)} is defined in your profile ${chalk.bold(profileName)}, but is missing in your config file`,
@@ -3629,12 +3624,6 @@ export const lib = {
3629
3624
  },
3630
3625
  validateProjectConfig: {
3631
3626
  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
3627
  },
3639
3628
  platformVersion: {
3640
3629
  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;
@@ -182,21 +182,14 @@ async function updatePackagesInDirectory({ directory, packages, npmWorkspaceDire
182
182
  }
183
183
  }
184
184
  export async function getProjectPackageJsonLocations(dir, isUpdate = false) {
185
- const projectConfig = await getProjectConfig(dir);
186
- if (!projectConfig ||
187
- !projectConfig.projectDir ||
188
- !projectConfig.projectConfig) {
189
- throw new Error(isUpdate
190
- ? commands.project.updateDeps.noProjectConfig
191
- : commands.project.installDeps.noProjectConfig);
192
- }
193
- const { projectDir, projectConfig: { srcDir, name }, } = projectConfig;
185
+ const { projectConfig, projectDir } = getProjectConfig(dir);
186
+ const { srcDir, name } = projectConfig;
194
187
  if (!(await isGloballyInstalled(DEFAULT_PACKAGE_MANAGER))) {
195
188
  throw new Error(isUpdate
196
189
  ? commands.project.updateDeps.packageManagerNotInstalled(DEFAULT_PACKAGE_MANAGER)
197
190
  : commands.project.installDeps.packageManagerNotInstalled(DEFAULT_PACKAGE_MANAGER));
198
191
  }
199
- if (!fs.existsSync(projectConfig.projectDir) ||
192
+ if (!fs.existsSync(projectDir) ||
200
193
  !fs.existsSync(path.join(projectDir, srcDir))) {
201
194
  throw new NoPackageJsonFilesError(name, isUpdate);
202
195
  }
@@ -1,9 +1,9 @@
1
- import { getProjectConfig } from '../projects/config.js';
2
1
  import { Environment } from '@hubspot/local-dev-lib/types/Accounts';
3
2
  import { AccessToken, AccountType, AuthType } from '@hubspot/local-dev-lib/types/Accounts';
4
3
  import { Project } from '@hubspot/local-dev-lib/types/Project';
5
4
  import process from 'process';
6
- export type ProjectConfig = Awaited<ReturnType<typeof getProjectConfig>>;
5
+ import type { LoadedProjectConfig } from '../projects/config.js';
6
+ export type ProjectConfig = LoadedProjectConfig | undefined;
7
7
  declare const hubspotCli = "@hubspot/cli";
8
8
  interface FilesInfo {
9
9
  files: string[];
@@ -50,12 +50,15 @@ export class DiagnosticInfoBuilder {
50
50
  this.processInfo = processInfo;
51
51
  }
52
52
  async generateDiagnosticInfo() {
53
- this._projectConfig = await getProjectConfig();
54
- if (this._projectConfig?.projectConfig) {
53
+ try {
54
+ this._projectConfig = getProjectConfig();
55
+ }
56
+ catch {
57
+ this._projectConfig = undefined;
58
+ }
59
+ if (this._projectConfig) {
55
60
  await this.fetchProjectDetails();
56
61
  await this.fetchAccessToken();
57
- }
58
- if (this._projectConfig?.projectDir) {
59
62
  await this.fetchProjectFilenames();
60
63
  }
61
64
  const { platform, arch, versions: { node }, mainModule, } = this.processInfo;
@@ -89,9 +92,7 @@ export class DiagnosticInfoBuilder {
89
92
  }
90
93
  async fetchProjectDetails() {
91
94
  try {
92
- const { data } = await fetchProject(this.accountId,
93
- // We check that config exists before running this function
94
- this._projectConfig.projectConfig.name);
95
+ const { data } = await fetchProject(this.accountId, this._projectConfig.projectConfig.name);
95
96
  this.projectDetails = data;
96
97
  }
97
98
  catch (e) {
@@ -109,7 +110,6 @@ export class DiagnosticInfoBuilder {
109
110
  }
110
111
  async fetchProjectFilenames() {
111
112
  try {
112
- // We check that projectDir exists before running this function
113
113
  this.files = (await walk(this._projectConfig.projectDir, ['node_modules'])).map(filename => path.relative(this._projectConfig.projectDir, filename));
114
114
  }
115
115
  catch (e) {
@@ -26,7 +26,7 @@ import { isServerRunningAtUrl } from '../http.js';
26
26
  import { detectConfiguredMcpClients } from '../mcp/promotion.js';
27
27
  import { MCP_CLIENTS } from '../mcp/clients.js';
28
28
  import { WEBHOOKS_KEY, APP_KEY } from '@hubspot/project-parsing-lib/constants';
29
- import { validateProjectConfig } from '../projects/config.js';
29
+ import { validateProjectConfig } from '@hubspot/project-parsing-lib/projects';
30
30
  import { validateSourceDirectory, handleTranslate, } from '../projects/upload.js';
31
31
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
32
32
  import { validateProjectForProfile } from '../projects/projectProfiles.js';
@@ -57,7 +57,7 @@ export class Doctor {
57
57
  ...this.performCliChecks(),
58
58
  ...this.performCliConfigChecks(),
59
59
  ...this.performNetworkingChecks(),
60
- ...(this.projectConfig?.projectConfig ? this.performProjectChecks() : []),
60
+ ...(this.projectConfig ? this.performProjectChecks() : []),
61
61
  ]);
62
62
  this.performDefaultAccountOverrideFileChecks();
63
63
  this.performCliConfigSettingsChecks();
@@ -283,7 +283,7 @@ export class Doctor {
283
283
  for (const packageFile of this.diagnosticInfo?.packageFiles || []) {
284
284
  const packageDirName = path.dirname(packageFile);
285
285
  try {
286
- const needsInstall = await hasMissingPackages(path.join(this.projectConfig?.projectDir || '', packageDirName));
286
+ const needsInstall = await hasMissingPackages(path.join(this.projectConfig?.projectDir ?? '', packageDirName));
287
287
  if (needsInstall) {
288
288
  foundError = true;
289
289
  this.diagnosis?.addProjectSection({
@@ -331,7 +331,7 @@ export class Doctor {
331
331
  async checkProjectConfigJsonFiles() {
332
332
  let foundError = false;
333
333
  for (const jsonFile of this.diagnosticInfo?.jsonFiles || []) {
334
- const fileToCheck = path.join(this.projectConfig?.projectDir || '', jsonFile);
334
+ const fileToCheck = path.join(this.projectConfig?.projectDir ?? '', jsonFile);
335
335
  if (!(await this.isValidJsonFile(fileToCheck))) {
336
336
  foundError = true;
337
337
  this.diagnosis?.addProjectSection({
@@ -432,7 +432,7 @@ export class Doctor {
432
432
  const hsMetaFiles = this.diagnosticInfo?.hsMetaFiles || [];
433
433
  for (const metaFiles of hsMetaFiles) {
434
434
  try {
435
- const content = await fs.promises.readFile(path.join(this.projectConfig?.projectDir || '', metaFiles), 'utf8');
435
+ const content = await fs.promises.readFile(path.join(this.projectConfig?.projectDir ?? '', metaFiles), 'utf8');
436
436
  const contents = JSON.parse(content);
437
437
  if (contents.type === WEBHOOKS_KEY &&
438
438
  contents.config?.settings?.targetUrl) {
@@ -461,7 +461,7 @@ export class Doctor {
461
461
  const hsMetaFiles = this.diagnosticInfo?.hsMetaFiles || [];
462
462
  for (const metaFile of hsMetaFiles) {
463
463
  try {
464
- const content = await fs.promises.readFile(path.join(this.projectConfig?.projectDir || '', metaFile), 'utf8');
464
+ const content = await fs.promises.readFile(path.join(this.projectConfig?.projectDir ?? '', metaFile), 'utf8');
465
465
  const contents = JSON.parse(content);
466
466
  if (contents.type === APP_KEY &&
467
467
  Array.isArray(contents.config?.auth?.redirectUrls)) {
@@ -550,9 +550,7 @@ export class Doctor {
550
550
  }
551
551
  }
552
552
  async checkProjectValidation() {
553
- if (!this.projectConfig?.projectConfig ||
554
- !this.projectConfig?.projectDir ||
555
- !this.accountId) {
553
+ if (!this.projectConfig || !this.accountId) {
556
554
  return;
557
555
  }
558
556
  const { projectConfig, projectDir } = this.projectConfig;
@@ -1,12 +1,6 @@
1
1
  export declare class ProjectNestingError extends Error {
2
2
  constructor(message: string);
3
3
  }
4
- export declare class ProjectConfigNotFoundError extends Error {
5
- constructor(message: string);
6
- }
7
- export declare class ProjectValidationError extends Error {
8
- constructor(message: string);
9
- }
10
4
  export declare class ProjectUploadError extends Error {
11
5
  constructor(message: string, cause?: unknown);
12
6
  }
@@ -4,18 +4,6 @@ export class ProjectNestingError extends Error {
4
4
  this.name = 'ProjectNestingError';
5
5
  }
6
6
  }
7
- export class ProjectConfigNotFoundError extends Error {
8
- constructor(message) {
9
- super(message);
10
- this.name = 'ProjectConfigNotFoundError';
11
- }
12
- }
13
- export class ProjectValidationError extends Error {
14
- constructor(message) {
15
- super(message);
16
- this.name = 'ProjectValidationError';
17
- }
18
- }
19
7
  export class ProjectUploadError extends Error {
20
8
  constructor(message, cause) {
21
9
  super(message, { cause });
@@ -1,4 +1,5 @@
1
+ import { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
1
2
  export default class ProjectValidationError extends Error {
2
3
  constructor(message: string, options?: ErrorOptions);
3
4
  }
4
- export declare function isProjectValidationError(err: unknown): err is ProjectValidationError;
5
+ export declare function isProjectValidationError(err: unknown): err is ProjectValidationError | ProjectConfigValidationError;
@@ -1,3 +1,4 @@
1
+ import { ProjectConfigValidationError } from '@hubspot/project-parsing-lib/projects';
1
2
  export default class ProjectValidationError extends Error {
2
3
  constructor(message, options) {
3
4
  super(message, options);
@@ -5,5 +6,6 @@ export default class ProjectValidationError extends Error {
5
6
  }
6
7
  }
7
8
  export function isProjectValidationError(err) {
8
- return err instanceof ProjectValidationError;
9
+ return (err instanceof ProjectValidationError ||
10
+ err instanceof ProjectConfigValidationError);
9
11
  }
@@ -11,8 +11,8 @@ import { translate, } from '@hubspot/project-parsing-lib/translate';
11
11
  import { commands, lib } from '../lang/en.js';
12
12
  import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
13
13
  import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_CONFIG_FILE, } from '../lib/constants.js';
14
- import { ProjectNestingError, ProjectConfigNotFoundError, ProjectValidationError, ProjectUploadError, ProjectBuildDeployError, } from './errors/ProjectErrors.js';
15
- import { getProjectConfig, validateProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
14
+ import { ProjectNestingError, ProjectUploadError, ProjectBuildDeployError, } from './errors/ProjectErrors.js';
15
+ import { getProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
16
16
  import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
17
17
  import { pollProjectBuildAndDeploy } from '../lib/projects/pollProjectBuildAndDeploy.js';
18
18
  import { handleProjectUpload } from '../lib/projects/upload.js';
@@ -29,11 +29,17 @@ export async function createProjectAction({ projectName, projectDest, }) {
29
29
  : 'Invalid project directory');
30
30
  }
31
31
  const projectDestAbsolute = path.resolve(getCwd(), projectDest);
32
- const { projectConfig: existingProjectConfig, projectDir: existingProjectDir, } = await getProjectConfig(projectDestAbsolute);
33
- if (existingProjectConfig &&
34
- existingProjectDir &&
35
- projectDestAbsolute.startsWith(existingProjectDir)) {
36
- throw new ProjectNestingError(commands.project.create.errors.cannotNestProjects(existingProjectDir));
32
+ try {
33
+ const { projectDir: existingProjectDir } = getProjectConfig(projectDestAbsolute);
34
+ if (projectDestAbsolute.startsWith(existingProjectDir)) {
35
+ throw new ProjectNestingError(commands.project.create.errors.cannotNestProjects(existingProjectDir));
36
+ }
37
+ }
38
+ catch (error) {
39
+ if (error instanceof ProjectNestingError) {
40
+ throw error;
41
+ }
42
+ // Not in a project directory, which is the expected case
37
43
  }
38
44
  try {
39
45
  await cloneGithubRepo(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDestAbsolute, {
@@ -88,17 +94,7 @@ async function buildProjectMetadata(projectDir, projectConfig, accountId) {
88
94
  };
89
95
  }
90
96
  export async function uploadAndDeployAction({ accountId, projectDest, }) {
91
- const { projectConfig, projectDir } = await getProjectConfig(projectDest);
92
- if (!projectConfig || !projectDir) {
93
- throw new ProjectConfigNotFoundError(commands.getStarted.errors.configFileNotFound);
94
- }
95
- try {
96
- validateProjectConfig(projectConfig, projectDir);
97
- }
98
- catch (error) {
99
- const message = error instanceof Error ? error.message : String(error);
100
- throw new ProjectValidationError(message);
101
- }
97
+ const { projectConfig, projectDir } = getProjectConfig(projectDest);
102
98
  const env = getConfigAccountEnvironment(accountId);
103
99
  try {
104
100
  const { result, uploadError } = await handleProjectUpload({
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ export declare const InstallStatusSchema: z.ZodObject<{
3
+ appId: z.ZodOptional<z.ZodNumber>;
4
+ appUid: z.ZodString;
5
+ accountId: z.ZodNumber;
6
+ projectId: z.ZodNumber;
7
+ isInstalled: z.ZodBoolean;
8
+ isInstalledWithCurrentScopes: z.ZodBoolean;
9
+ previouslyAuthorizedScopeGroups: z.ZodArray<z.ZodObject<{
10
+ id: z.ZodNumber;
11
+ name: z.ZodString;
12
+ }, z.core.$strip>>;
13
+ }, z.core.$strip>;
14
+ export type InstallStatusJsonOutput = z.infer<typeof InstallStatusSchema>;
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ const ScopeGroupSchema = z.object({
3
+ id: z.number(),
4
+ name: z.string(),
5
+ });
6
+ export const InstallStatusSchema = z.object({
7
+ appId: z.number().optional(),
8
+ appUid: z.string(),
9
+ accountId: z.number(),
10
+ projectId: z.number(),
11
+ isInstalled: z.boolean(),
12
+ isInstalledWithCurrentScopes: z.boolean(),
13
+ previouslyAuthorizedScopeGroups: z.array(ScopeGroupSchema),
14
+ });
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ export declare const CreateTestAccountSchema: z.ZodObject<{
3
+ accountName: z.ZodOptional<z.ZodString>;
4
+ accountId: z.ZodOptional<z.ZodNumber>;
5
+ personalAccessKey: z.ZodOptional<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ export type CreateTestAccountJsonOutput = z.infer<typeof CreateTestAccountSchema>;
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export const CreateTestAccountSchema = z.object({
3
+ accountName: z.string().optional(),
4
+ accountId: z.number().optional(),
5
+ personalAccessKey: z.string().optional(),
6
+ });
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare const DeploySchema: z.ZodObject<{
3
+ deployId: z.ZodOptional<z.ZodNumber>;
4
+ }, z.core.$strip>;
5
+ export type DeployJsonOutput = z.infer<typeof DeploySchema>;
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export const DeploySchema = z.object({
3
+ deployId: z.number().optional(),
4
+ });
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ export declare const ProjectInfoSchema: z.ZodObject<{
3
+ projectName: z.ZodString;
4
+ platformVersion: z.ZodString;
5
+ projectId: z.ZodNumber;
6
+ deployedBuildId: z.ZodNumber;
7
+ autoDeployEnabled: z.ZodBoolean;
8
+ projectUrl: z.ZodOptional<z.ZodString>;
9
+ app: z.ZodOptional<z.ZodObject<{
10
+ name: z.ZodString;
11
+ id: z.ZodNumber;
12
+ uid: z.ZodString;
13
+ authType: z.ZodOptional<z.ZodString>;
14
+ distributionType: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>>;
16
+ components: z.ZodArray<z.ZodObject<{
17
+ uid: z.ZodString;
18
+ type: z.ZodString;
19
+ }, z.core.$strip>>;
20
+ }, z.core.$strip>;
21
+ export type ProjectInfoJsonOutput = z.infer<typeof ProjectInfoSchema>;