@hubspot/cli 8.4.0 → 8.5.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 (93) hide show
  1. package/api/migrate.js +3 -3
  2. package/bin/cli.js +3 -0
  3. package/commands/app/migrate.js +4 -4
  4. package/commands/getStarted.js +2 -2
  5. package/commands/project/add.js +3 -3
  6. package/commands/project/create.js +10 -7
  7. package/commands/project/delete.js +2 -2
  8. package/commands/project/deploy.js +4 -3
  9. package/commands/project/dev/index.js +5 -4
  10. package/commands/project/info.js +2 -2
  11. package/commands/project/migrate.js +5 -5
  12. package/commands/project/profile/add.js +2 -2
  13. package/commands/project/profile/delete.js +2 -2
  14. package/commands/project/upload.js +3 -3
  15. package/commands/project/validate.js +2 -2
  16. package/commands/project/watch.js +2 -2
  17. package/commands/project.js +6 -3
  18. package/commands/testAccount/create.js +4 -4
  19. package/lang/en.d.ts +11 -0
  20. package/lang/en.js +16 -5
  21. package/lib/app/migrate.js +7 -0
  22. package/lib/constants.d.ts +0 -1
  23. package/lib/constants.js +0 -1
  24. package/lib/doctor/Doctor.js +2 -2
  25. package/lib/getStartedV2Actions.js +2 -2
  26. package/lib/hasFeature.js +1 -2
  27. package/lib/middleware/autoUpdateMiddleware.js +6 -3
  28. package/lib/projects/ProjectLogsManager.js +6 -3
  29. package/lib/projects/create/index.js +2 -2
  30. package/lib/projects/create/legacy.js +2 -2
  31. package/lib/projects/create/v2.js +3 -4
  32. package/lib/projects/delete.js +2 -2
  33. package/lib/projects/deploy.d.ts +1 -1
  34. package/lib/projects/deploy.js +2 -2
  35. package/lib/projects/upload.js +22 -3
  36. package/lib/projects/workspaces.d.ts +42 -0
  37. package/lib/projects/workspaces.js +350 -0
  38. package/lib/prompts/projectsLogsPrompt.js +3 -0
  39. package/lib/theme/cmsDevServerProcess.js +1 -1
  40. package/mcp-server/Tool.d.ts +15 -0
  41. package/mcp-server/Tool.js +53 -0
  42. package/mcp-server/server.js +5 -3
  43. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +4 -2
  44. package/mcp-server/tools/cms/HsCreateFunctionTool.js +8 -6
  45. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +4 -2
  46. package/mcp-server/tools/cms/HsCreateModuleTool.js +8 -6
  47. package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +4 -2
  48. package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -6
  49. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +4 -2
  50. package/mcp-server/tools/cms/HsFunctionLogsTool.js +8 -6
  51. package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +4 -2
  52. package/mcp-server/tools/cms/HsListFunctionsTool.js +8 -6
  53. package/mcp-server/tools/cms/HsListTool.d.ts +4 -2
  54. package/mcp-server/tools/cms/HsListTool.js +8 -6
  55. package/mcp-server/tools/index.d.ts +3 -2
  56. package/mcp-server/tools/index.js +22 -22
  57. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +6 -4
  58. package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -6
  59. package/mcp-server/tools/project/CreateProjectTool.d.ts +6 -4
  60. package/mcp-server/tools/project/CreateProjectTool.js +9 -7
  61. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +4 -2
  62. package/mcp-server/tools/project/CreateTestAccountTool.js +20 -8
  63. package/mcp-server/tools/project/DeployProjectTool.d.ts +4 -2
  64. package/mcp-server/tools/project/DeployProjectTool.js +4 -6
  65. package/mcp-server/tools/project/DocFetchTool.d.ts +4 -2
  66. package/mcp-server/tools/project/DocFetchTool.js +8 -6
  67. package/mcp-server/tools/project/DocsSearchTool.d.ts +9 -3
  68. package/mcp-server/tools/project/DocsSearchTool.js +32 -9
  69. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +4 -2
  70. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +8 -6
  71. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +4 -2
  72. package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
  73. package/mcp-server/tools/project/GetBuildLogsTool.d.ts +4 -2
  74. package/mcp-server/tools/project/GetBuildLogsTool.js +8 -6
  75. package/mcp-server/tools/project/GetBuildStatusTool.d.ts +4 -2
  76. package/mcp-server/tools/project/GetBuildStatusTool.js +8 -6
  77. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -2
  78. package/mcp-server/tools/project/GetConfigValuesTool.js +12 -7
  79. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +4 -2
  80. package/mcp-server/tools/project/GuidedWalkthroughTool.js +4 -6
  81. package/mcp-server/tools/project/UploadProjectTools.d.ts +4 -2
  82. package/mcp-server/tools/project/UploadProjectTools.js +9 -7
  83. package/mcp-server/tools/project/ValidateProjectTool.d.ts +4 -2
  84. package/mcp-server/tools/project/ValidateProjectTool.js +8 -6
  85. package/mcp-server/tools/project/constants.d.ts +2 -2
  86. package/mcp-server/types.d.ts +0 -7
  87. package/mcp-server/types.js +1 -13
  88. package/mcp-server/utils/logger.d.ts +10 -0
  89. package/mcp-server/utils/logger.js +29 -0
  90. package/mcp-server/utils/toolUsageTracking.js +0 -2
  91. package/package.json +10 -10
  92. package/lib/projects/platformVersion.d.ts +0 -9
  93. package/lib/projects/platformVersion.js +0 -39
@@ -26,7 +26,7 @@ import { isServerRunningAtUrl } from '../http.js';
26
26
  import { WEBHOOKS_KEY, APP_KEY } from '@hubspot/project-parsing-lib/constants';
27
27
  import { validateProjectConfig } from '../projects/config.js';
28
28
  import { validateSourceDirectory, handleTranslate, } from '../projects/upload.js';
29
- import { isV2Project } from '../projects/platformVersion.js';
29
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
30
30
  import { validateProjectForProfile } from '../projects/projectProfiles.js';
31
31
  import { getAllHsProfiles } from '@hubspot/project-parsing-lib/profiles';
32
32
  const minMajorNodeVersion = 20;
@@ -534,7 +534,7 @@ export class Doctor {
534
534
  if (!this.validateProjectConfigWrapper(projectConfig, projectDir)) {
535
535
  return;
536
536
  }
537
- if (!isV2Project(projectConfig.platformVersion)) {
537
+ if (isLegacyProject(projectConfig.platformVersion)) {
538
538
  this.diagnosis?.addProjectSection({
539
539
  type: 'success',
540
540
  message: lib.doctor.projectValidation.valid,
@@ -13,7 +13,7 @@ import { getStaticAuthAppInstallUrl } from '../lib/app/urls.js';
13
13
  import { HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_CONFIG_FILE, } from '../lib/constants.js';
14
14
  import { ProjectNestingError, ProjectConfigNotFoundError, ProjectValidationError, ProjectUploadError, ProjectBuildDeployError, } from './errors/ProjectErrors.js';
15
15
  import { getProjectConfig, validateProjectConfig, writeProjectConfig, } from '../lib/projects/config.js';
16
- import { isV2Project } from '../lib/projects/platformVersion.js';
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';
19
19
  import { validateProjectDirectory } from '../lib/prompts/projectNameAndDestPrompt.js';
@@ -109,7 +109,7 @@ export async function uploadAndDeployAction({ accountId, projectDest, }) {
109
109
  uploadMessage: commands.getStarted.logs.initialUploadMessage,
110
110
  forceCreate: true,
111
111
  isUploadCommand: false,
112
- sendIR: isV2Project(projectConfig.platformVersion),
112
+ sendIR: !isLegacyProject(projectConfig.platformVersion),
113
113
  skipValidation: false,
114
114
  });
115
115
  if (uploadError) {
package/lib/hasFeature.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { http } from '@hubspot/local-dev-lib/http';
2
2
  import { fetchEnabledFeatures } from '@hubspot/local-dev-lib/api/localDevAuth';
3
- import { FEATURES } from './constants.js';
4
- const FEATURES_THAT_DEFAULT_ON = [FEATURES.APPS_HOME];
3
+ const FEATURES_THAT_DEFAULT_ON = [];
5
4
  export async function hasFeature(accountId, feature) {
6
5
  const { data: { enabledFeatures }, } = await fetchEnabledFeatures(accountId);
7
6
  if (enabledFeatures[feature] === undefined &&
@@ -42,6 +42,10 @@ export async function autoUpdateCLI(argv) {
42
42
  debugError(e);
43
43
  }
44
44
  const cliUpgradeInfo = getCliUpgradeInfo();
45
+ // Ignore all update notifications if the current version is a pre-release (contains a hyphen)
46
+ if (cliUpgradeInfo.current && cliUpgradeInfo.current.includes('-')) {
47
+ showManualInstallHelp = false;
48
+ }
45
49
  if (isAllowAutoUpdatesEnabled &&
46
50
  cliUpgradeInfo.current &&
47
51
  cliUpgradeInfo.latest &&
@@ -49,9 +53,8 @@ export async function autoUpdateCLI(argv) {
49
53
  !argv.useEnv &&
50
54
  !process.env.SKIP_HUBSPOT_CLI_AUTO_UPDATES &&
51
55
  !preventAutoUpdateForCommand(argv._)) {
52
- // Ignore all update notifications if the current version is a pre-release (contains a hyphen)
53
- if (cliUpgradeInfo.current.includes('-')) {
54
- showManualInstallHelp = false;
56
+ if (!showManualInstallHelp) {
57
+ // Pre-release version detected, skip auto-update
55
58
  }
56
59
  else if (!['major', 'latest'].includes(cliUpgradeInfo.type)) {
57
60
  // type "latest" => current installed version is latest
@@ -4,7 +4,7 @@ import { fetchProjectComponentsMetadata } from '@hubspot/local-dev-lib/api/proje
4
4
  import { fetchAppMetadataBySourceId } from '@hubspot/local-dev-lib/api/appsDev';
5
5
  import { uiLogger } from '../ui/logger.js';
6
6
  import { commands } from '../../lang/en.js';
7
- import { isV2Project } from './platformVersion.js';
7
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
8
8
  import { getDeployedProjectNodes } from './localDev/helpers/project.js';
9
9
  import { debugError } from '../errorHandlers/index.js';
10
10
  class _ProjectLogsManager {
@@ -51,7 +51,7 @@ class _ProjectLogsManager {
51
51
  throw new Error(commands.project.logs.errors.failedToFetchProjectDetails);
52
52
  }
53
53
  this.projectId = project.id;
54
- if (isV2Project(projectConfig.platformVersion)) {
54
+ if (!isLegacyProject(projectConfig.platformVersion)) {
55
55
  const deployedBuildId = project.deployedBuild.buildId;
56
56
  if (!deployedBuildId) {
57
57
  throw new Error(commands.project.logs.errors.noDeployedBuild);
@@ -134,9 +134,12 @@ class _ProjectLogsManager {
134
134
  return this.functions.map(serverlessFunction => serverlessFunction.componentName);
135
135
  }
136
136
  setFunction(functionName) {
137
- if (!functionName || this.functions.length === 0) {
137
+ if (this.functions.length === 0) {
138
138
  throw new Error(commands.project.logs.errors.noFunctionsInProject);
139
139
  }
140
+ if (!functionName) {
141
+ throw new Error(commands.project.logs.errors.functionNameRequired);
142
+ }
140
143
  this.selectedFunction = this.functions.find(serverlessFunction => serverlessFunction.componentName === functionName);
141
144
  if (!this.selectedFunction) {
142
145
  throw new Error(commands.project.logs.errors.noFunctionWithName(functionName));
@@ -1,7 +1,7 @@
1
1
  import { selectProjectTemplatePrompt, } from '../../prompts/selectProjectTemplatePrompt.js';
2
2
  import { projectNameAndDestPrompt } from '../../prompts/projectNameAndDestPrompt.js';
3
3
  import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, EMPTY_PROJECT, } from '../../constants.js';
4
- import { isV2Project } from '../platformVersion.js';
4
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
5
5
  import { v2ComponentFlow } from './v2.js';
6
6
  import { getProjectTemplateListFromRepo } from './legacy.js';
7
7
  import { commands } from '../../../lang/en.js';
@@ -9,7 +9,7 @@ export async function handleProjectCreationFlow(args) {
9
9
  const { platformVersion, templateSource, projectBase, auth: providedAuth, distribution: providedDistribution, } = args;
10
10
  const repo = templateSource || HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
11
11
  const projectNameAndDestPromptResponse = await projectNameAndDestPrompt(args);
12
- if (isV2Project(platformVersion)) {
12
+ if (!isLegacyProject(platformVersion)) {
13
13
  const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await v2ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution, args.derivedAccountId);
14
14
  const selectProjectTemplatePromptResponse = await selectProjectTemplatePrompt(args, undefined, projectContents !== EMPTY_PROJECT ? componentTemplateChoices : undefined);
15
15
  return {
@@ -1,13 +1,13 @@
1
1
  import { fetchRepoFile } from '@hubspot/local-dev-lib/api/github';
2
2
  import { DEFAULT_PROJECT_TEMPLATE_BRANCH, HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, PROJECT_COMPONENT_TYPES, } from '../../constants.js';
3
3
  import { debugError } from '../../errorHandlers/index.js';
4
- import { isV2Project } from '../platformVersion.js';
4
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
5
5
  import { lib } from '../../../lang/en.js';
6
6
  const PROJECT_TEMPLATE_PROPERTIES = ['name', 'label', 'path'];
7
7
  export const EMPTY_PROJECT_TEMPLATE_NAME = 'no-template';
8
8
  export async function getConfigForPlatformVersion(platformVersion) {
9
9
  let path = '';
10
- if (isV2Project(platformVersion)) {
10
+ if (!isLegacyProject(platformVersion)) {
11
11
  path = `${platformVersion}/`;
12
12
  }
13
13
  const { data } = await fetchRepoFile(HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, `${path}config.json`, DEFAULT_PROJECT_TEMPLATE_BRANCH);
@@ -1,8 +1,8 @@
1
1
  import { marketplaceDistribution, oAuth, privateDistribution, staticAuth, EMPTY_PROJECT, PROJECT_WITH_APP, FEATURES, } from '../../constants.js';
2
2
  import { commands, lib } from '../../../lang/en.js';
3
3
  import { listPrompt } from '../../prompts/promptUtils.js';
4
- import { APP_EVENTS_KEY as AppEventsKey, PAGES_KEY as PagesKey, } from '@hubspot/project-parsing-lib/constants';
5
- import { isV2Project } from '../platformVersion.js';
4
+ import { APP_EVENTS_KEY as AppEventsKey } from '@hubspot/project-parsing-lib/constants';
5
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
6
6
  import path from 'path';
7
7
  import { getConfigForPlatformVersion } from './legacy.js';
8
8
  import { hasFeature } from '../../hasFeature.js';
@@ -47,7 +47,6 @@ export async function createV2App(providedAuth, providedDistribution) {
47
47
  }
48
48
  const componentTypeToGateMap = {
49
49
  [AppEventsKey]: FEATURES.APP_EVENTS,
50
- [PagesKey]: FEATURES.APPS_HOME,
51
50
  'workflow-action-tool': FEATURES.AGENT_TOOLS,
52
51
  };
53
52
  export async function calculateComponentTemplateChoices(components, authType, distribution, accountId, projectMetadata) {
@@ -135,7 +134,7 @@ export async function v2ComponentFlow(platformVersion, projectBase, providedAuth
135
134
  };
136
135
  }
137
136
  export function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }) {
138
- if (!isV2Project(platformVersion)) {
137
+ if (isLegacyProject(platformVersion)) {
139
138
  return [];
140
139
  }
141
140
  const components = selectProjectTemplatePromptResponse.componentTemplates?.map((componentTemplate) => {
@@ -10,7 +10,7 @@ import { PromptExitError } from '../errors/PromptExitError.js';
10
10
  import { EXIT_CODES } from '../enums/exitCodes.js';
11
11
  import { AUTO_GENERATED_COMPONENT_TYPES } from '@hubspot/project-parsing-lib/constants';
12
12
  import { mapToUserFacingType } from '@hubspot/project-parsing-lib/transform';
13
- import { isV2Project } from './platformVersion.js';
13
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
14
14
  import { COMPONENT_TYPES, SUBCOMPONENT_TYPES, } from '@hubspot/local-dev-lib/enums/build';
15
15
  export const DELETION_POLL_TIMEOUT_MS = 5 * 60 * 1000;
16
16
  export const DELETION_DEPLOY_SUCCESS_STATES = [
@@ -81,7 +81,7 @@ export async function checkDeployedComponents(accountId, projectName) {
81
81
  if (!platformVersion) {
82
82
  throw new Error(commands.project.delete.errors.noPlatformVersion);
83
83
  }
84
- if (!isV2Project(platformVersion)) {
84
+ if (isLegacyProject(platformVersion)) {
85
85
  const userVisibleComponents = [];
86
86
  projectData.deployedBuild?.subbuildStatuses?.forEach(item => {
87
87
  if (LEGACY_COMPONENTS_TO_FILTER.includes(item.buildType)) {
@@ -10,4 +10,4 @@ export declare function logDeployErrors(errorData: {
10
10
  };
11
11
  }>;
12
12
  }): void;
13
- export declare function handleProjectDeploy(targetAccountId: number, projectName: string, buildId: number, isV2Project: boolean, force: boolean): Promise<Deploy | undefined>;
13
+ export declare function handleProjectDeploy(targetAccountId: number, projectName: string, buildId: number, isLegacyProject: boolean, force: boolean): Promise<Deploy | undefined>;
@@ -47,9 +47,9 @@ function handleBlockedDeploy(deployResp) {
47
47
  uiLogger.log('');
48
48
  });
49
49
  }
50
- export async function handleProjectDeploy(targetAccountId, projectName, buildId, isV2Project, force) {
50
+ export async function handleProjectDeploy(targetAccountId, projectName, buildId, isLegacyProject, force) {
51
51
  let deployId;
52
- if (isV2Project) {
52
+ if (!isLegacyProject) {
53
53
  const { data: deployResp } = await deployProjectV2(targetAccountId, projectName, buildId, force);
54
54
  if (!deployResp || deployResp.buildResultType !== 'DEPLOY_QUEUED') {
55
55
  if (deployResp?.buildResultType === 'DEPLOY_BLOCKED') {
@@ -6,16 +6,18 @@ import { uploadProject } from '@hubspot/local-dev-lib/api/projects';
6
6
  import { shouldIgnoreFile } from '@hubspot/local-dev-lib/ignoreRules';
7
7
  import { isTranslationError, translate, } from '@hubspot/project-parsing-lib/translate';
8
8
  import { projectContainsHsMetaFiles } from '@hubspot/project-parsing-lib/projects';
9
+ import { findAndParsePackageJsonFiles, collectWorkspaceDirectories, collectFileDependencies, } from '@hubspot/project-parsing-lib/workspaces';
9
10
  import SpinniesManager from '../ui/SpinniesManager.js';
10
11
  import { uiAccountDescription } from '../ui/index.js';
11
12
  import util from 'node:util';
12
13
  import { lib } from '../../lang/en.js';
13
14
  import { ensureProjectExists } from './ensureProjectExists.js';
14
15
  import { uiLogger } from '../ui/logger.js';
15
- import { isV2Project } from './platformVersion.js';
16
16
  import ProjectValidationError from '../errors/ProjectValidationError.js';
17
17
  import { walk } from '@hubspot/local-dev-lib/fs';
18
18
  import { LEGACY_CONFIG_FILES } from '../constants.js';
19
+ import { archiveWorkspacesAndDependencies, getPackageJsonPathsToUpdate, getLockfilePathsToUpdate, } from './workspaces.js';
20
+ import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
19
21
  async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
20
22
  const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
21
23
  SpinniesManager.add('upload', {
@@ -48,6 +50,15 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
48
50
  await validateNoHSMetaMismatch(srcDir, projectConfig);
49
51
  const tempFile = tmp.fileSync({ postfix: '.zip' });
50
52
  uiLogger.debug(lib.projectUpload.handleProjectUpload.compressing(tempFile.name));
53
+ // Collect workspace directories and file: dependencies for v2+ projects only.
54
+ // Versions <= 2025.1 do not support the new npm workspaces bundling behavior.
55
+ let workspaceMappings = [];
56
+ let fileDependencyMappings = [];
57
+ if (!isLegacyProject(projectConfig.platformVersion)) {
58
+ const parsedPackageJsons = await findAndParsePackageJsonFiles(srcDir);
59
+ workspaceMappings = await collectWorkspaceDirectories(parsedPackageJsons);
60
+ fileDependencyMappings = await collectFileDependencies(parsedPackageJsons);
61
+ }
51
62
  const output = fs.createWriteStream(tempFile.name);
52
63
  const archive = archiver('zip');
53
64
  const result = new Promise((resolve, reject) => output.on('close', async function () {
@@ -91,8 +102,14 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
91
102
  }
92
103
  }));
93
104
  archive.pipe(output);
105
+ const modifiedPackageJsonPaths = getPackageJsonPathsToUpdate(srcDir, workspaceMappings, fileDependencyMappings);
106
+ const lockfilePathsToUpdate = getLockfilePathsToUpdate(srcDir, workspaceMappings, fileDependencyMappings);
94
107
  let loggedIgnoredNodeModule = false;
95
108
  archive.directory(srcDir, false, file => {
109
+ if (modifiedPackageJsonPaths.has(file.name) ||
110
+ lockfilePathsToUpdate.has(file.name)) {
111
+ return false;
112
+ }
96
113
  const ignored = shouldIgnoreFile(file.name, true);
97
114
  if (ignored) {
98
115
  const isNodeModule = file.name.includes('node_modules');
@@ -105,6 +122,8 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
105
122
  }
106
123
  return ignored ? false : file;
107
124
  });
125
+ // Archive workspaces and file: dependencies
126
+ await archiveWorkspacesAndDependencies(archive, srcDir, projectDir, workspaceMappings, fileDependencyMappings);
108
127
  archive.finalize();
109
128
  return result;
110
129
  }
@@ -113,7 +132,7 @@ export async function validateSourceDirectory(srcDir, projectConfig, projectDir)
113
132
  if (!projectFilePaths || projectFilePaths.length === 0) {
114
133
  throw new ProjectValidationError(lib.projectUpload.handleProjectUpload.emptySource(projectConfig.srcDir));
115
134
  }
116
- if (isV2Project(projectConfig.platformVersion)) {
135
+ if (!isLegacyProject(projectConfig.platformVersion)) {
117
136
  projectFilePaths.forEach(filePath => {
118
137
  const filename = path.basename(filePath);
119
138
  if (LEGACY_CONFIG_FILES.includes(filename)) {
@@ -124,7 +143,7 @@ export async function validateSourceDirectory(srcDir, projectConfig, projectDir)
124
143
  }
125
144
  export async function validateNoHSMetaMismatch(srcDir, projectConfig) {
126
145
  const hasHsMetaFiles = await projectContainsHsMetaFiles(srcDir);
127
- if (!isV2Project(projectConfig.platformVersion) && hasHsMetaFiles) {
146
+ if (isLegacyProject(projectConfig.platformVersion) && hasHsMetaFiles) {
128
147
  throw new ProjectValidationError(lib.projectUpload.wrongPlatformVersionMetaFiles);
129
148
  }
130
149
  }
@@ -0,0 +1,42 @@
1
+ import archiver from 'archiver';
2
+ import { WorkspaceMapping, FileDependencyMapping } from '@hubspot/project-parsing-lib/workspaces';
3
+ /**
4
+ * Result of archiving workspaces and file dependencies
5
+ */
6
+ export type WorkspaceArchiveResult = {
7
+ packageWorkspaces: Map<string, string[]>;
8
+ packageFileDeps: Map<string, Map<string, string>>;
9
+ };
10
+ /**
11
+ * Generates a short hash of the input string for use in workspace paths.
12
+ * Uses SHA256 truncated to 8 hex characters (4 billion possibilities).
13
+ */
14
+ export declare function shortHash(input: string): string;
15
+ /**
16
+ * Determines the archive path for an external workspace or file: dependency.
17
+ * Produces `_workspaces/<basename>-<hash>` with no subdirectory.
18
+ * The hash prevents collisions between different directories with the same basename.
19
+ */
20
+ export declare function computeExternalArchivePath(absolutePath: string): string;
21
+ /**
22
+ * Updates package.json files in the archive to reflect new workspace and file: dependency paths.
23
+ *
24
+ * Workspace entries in packageWorkspaces are already in final form:
25
+ * - Internal workspaces: relative paths (e.g. "../packages/utils")
26
+ * - External workspaces: relative paths (e.g. "../_workspaces/logger-abc")
27
+ *
28
+ * Only external file: dependencies appear in packageFileDeps; internal ones
29
+ * keep their original file: references and are left untouched.
30
+ */
31
+ export declare function updatePackageJsonInArchive(archive: archiver.Archiver, srcDir: string, packageWorkspaces: Map<string, string[]>, packageFileDeps: Map<string, Map<string, string>>): Promise<void>;
32
+ export declare function rewriteLockfileForExternalDeps(lockfileContent: Record<string, unknown>, pathMappings: Array<{
33
+ oldPath: string;
34
+ newPath: string;
35
+ }>): Record<string, unknown>;
36
+ export declare function getPackageJsonPathsToUpdate(srcDir: string, workspaceMappings: WorkspaceMapping[], fileDependencyMappings: FileDependencyMapping[]): Set<string>;
37
+ export declare function getLockfilePathsToUpdate(srcDir: string, workspaceMappings: WorkspaceMapping[], fileDependencyMappings: FileDependencyMapping[]): Set<string>;
38
+ /**
39
+ * Main orchestration function that handles archiving of workspaces and file dependencies.
40
+ * This is the clean integration point for upload.ts.
41
+ */
42
+ export declare function archiveWorkspacesAndDependencies(archive: archiver.Archiver, srcDir: string, projectDir: string, workspaceMappings: WorkspaceMapping[], fileDependencyMappings: FileDependencyMapping[]): Promise<WorkspaceArchiveResult>;