@hubspot/cli 8.0.12-experimental.1 → 8.1.0-experimental.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from 'yargs';
3
- import { logError } from '../lib/errorHandlers/index.js';
3
+ import { logError, debugError } from '../lib/errorHandlers/index.js';
4
4
  import { setCLILogLevel, getCommandName } from '../lib/commonOpts.js';
5
5
  import { trackHelpUsage, trackConvertFieldsUsage, } from '../lib/usageTracking.js';
6
6
  import { EXIT_CODES } from '../lib/enums/exitCodes.js';
@@ -132,11 +132,11 @@ const argvWithSuggestions = await parseYargsOrExit(parser, handleFailure);
132
132
  if ('help' in argvWithSuggestions && argvWithSuggestions.help !== undefined) {
133
133
  (async () => {
134
134
  await trackHelpUsage(getCommandName(argvWithSuggestions));
135
- })();
135
+ })().catch(debugError);
136
136
  }
137
137
  if ('convertFields' in argvWithSuggestions &&
138
138
  argvWithSuggestions.convertFields !== undefined) {
139
139
  (async () => {
140
140
  await trackConvertFieldsUsage(getCommandName(argvWithSuggestions));
141
- })();
141
+ })().catch(debugError);
142
142
  }
@@ -3,13 +3,13 @@ import util from 'util';
3
3
  import { HUBSPOT_ACCOUNT_TYPES } from '@hubspot/local-dev-lib/constants/config';
4
4
  import { startPortManagerServer, stopPortManagerServer, } from '@hubspot/local-dev-lib/portManager';
5
5
  import { isTranslationError, translateForLocalDev, } from '@hubspot/project-parsing-lib/translate';
6
- import { getConfigAccountEnvironment, getLinkedOrAllConfigAccounts, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
6
+ import { getConfigAccountEnvironment, getLinkedOrAllConfigAccounts, getConfigAccountById, getConfigAccountIfExists, } from '@hubspot/local-dev-lib/config';
7
7
  import { logError } from '../../../lib/errorHandlers/index.js';
8
8
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
9
9
  import { ensureProjectExists } from '../../../lib/projects/ensureProjectExists.js';
10
10
  import { createInitialBuildForNewProject, createNewProjectForLocalDev, compareLocalProjectToDeployed, checkAndInstallDependencies, } from '../../../lib/projects/localDev/helpers/project.js';
11
11
  import { useExistingDevTestAccount, createDeveloperTestAccountForLocalDev, selectAccountTypePrompt, createSandboxForLocalDev, } from '../../../lib/projects/localDev/helpers/account.js';
12
- import { selectDeveloperTestTargetAccountPrompt, selectSandboxTargetAccountPrompt, } from '../../../lib/prompts/projectDevTargetAccountPrompt.js';
12
+ import { selectDeveloperTestTargetAccountPrompt, selectSandboxTargetAccountPrompt, confirmLinkExistingDeveloperTestAccountPrompt, } from '../../../lib/prompts/projectDevTargetAccountPrompt.js';
13
13
  import LocalDevProcess from '../../../lib/projects/localDev/LocalDevProcess.js';
14
14
  import LocalDevWatcher from '../../../lib/projects/localDev/LocalDevWatcher.js';
15
15
  import { handleExit, handleKeypress } from '../../../lib/process.js';
@@ -89,17 +89,26 @@ export async function unifiedProjectDevFlow({ args, targetProjectAccountId, prov
89
89
  const accountType = await selectAccountTypePrompt(targetProjectAccountConfig);
90
90
  if (accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST) {
91
91
  const devAccountPromptResponse = await selectDeveloperTestTargetAccountPrompt(accounts, targetProjectAccountConfig);
92
+ const { notInConfigAccount } = devAccountPromptResponse;
92
93
  targetTestingAccountId =
93
94
  devAccountPromptResponse.targetAccountId || undefined;
94
- if (!!devAccountPromptResponse.notInConfigAccount) {
95
- // When the developer test account isn't configured in the CLI config yet
96
- // Walk the user through adding the account's PAK to the config
97
- const accountAdded = await useExistingDevTestAccount(env, devAccountPromptResponse.notInConfigAccount);
98
- if (!accountAdded) {
99
- return exit(EXIT_CODES.SUCCESS);
95
+ if (notInConfigAccount) {
96
+ const existingGlobalConfig = getConfigAccountIfExists(notInConfigAccount.id);
97
+ if (directoryIsLinked && existingGlobalConfig) {
98
+ const shouldLink = await confirmLinkExistingDeveloperTestAccountPrompt(notInConfigAccount.accountName);
99
+ if (!shouldLink) {
100
+ return exit(EXIT_CODES.SUCCESS);
101
+ }
102
+ addAccountToLinkedSettings(notInConfigAccount.id);
100
103
  }
101
- if (directoryIsLinked) {
102
- addAccountToLinkedSettings(devAccountPromptResponse.notInConfigAccount.id);
104
+ else {
105
+ const accountAdded = await useExistingDevTestAccount(env, notInConfigAccount);
106
+ if (!accountAdded) {
107
+ return exit(EXIT_CODES.SUCCESS);
108
+ }
109
+ if (directoryIsLinked) {
110
+ addAccountToLinkedSettings(notInConfigAccount.id);
111
+ }
103
112
  }
104
113
  }
105
114
  else if (devAccountPromptResponse.createNestedAccount) {
@@ -5,8 +5,6 @@ export type ProjectUploadArgs = CommonArgs & JSONOutputArgs & {
5
5
  m: string;
6
6
  skipValidation: boolean;
7
7
  profile?: string;
8
- preview: boolean;
9
- target?: number;
10
8
  };
11
9
  declare const projectUploadCommand: YargsCommandModule<unknown, ProjectUploadArgs>;
12
10
  export default projectUploadCommand;
@@ -8,8 +8,7 @@ import { logFeedbackMessage } from '../../lib/projects/ui.js';
8
8
  import { handleProjectUpload } from '../../lib/projects/upload.js';
9
9
  import { loadAndValidateProfile } from '../../lib/projects/projectProfiles.js';
10
10
  import { displayWarnLogs, pollProjectBuildAndDeploy, } from '../../lib/projects/pollProjectBuildAndDeploy.js';
11
- import { triggerAndPollPreview } from '../../lib/projects/preview.js';
12
- import { commands, lib } from '../../lang/en.js';
11
+ import { commands } from '../../lang/en.js';
13
12
  import { PROJECT_ERROR_TYPES } from '../../lib/constants.js';
14
13
  import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
15
14
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -18,22 +17,8 @@ import { makeYargsBuilder } from '../../lib/yargsUtils.js';
18
17
  import { projectProfilePrompt } from '../../lib/prompts/projectProfilePrompt.js';
19
18
  const command = 'upload';
20
19
  const describe = commands.project.upload.describe;
21
- async function handlePreview(accountId, projectId, buildId, targetPortalId) {
22
- if (!projectId) {
23
- uiLogger.warn(lib.projectPreview.missingProjectId);
24
- return;
25
- }
26
- const previewResult = await triggerAndPollPreview(accountId, projectId, buildId, targetPortalId);
27
- if (!previewResult.succeeded) {
28
- uiLogger.warn(lib.projectPreview.warning);
29
- }
30
- return {
31
- releaseTag: previewResult.releaseTag,
32
- succeeded: previewResult.succeeded,
33
- };
34
- }
35
20
  async function handler(args) {
36
- const { forceCreate, message, derivedAccountId, skipValidation, formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, preview, target: targetPortalId, exit, addUsageMetadata, } = args;
21
+ const { forceCreate, message, derivedAccountId, skipValidation, formatOutputAsJson, profile: profileOption, useEnv: useEnvOption, exit, addUsageMetadata, } = args;
37
22
  const jsonOutput = {};
38
23
  const { projectConfig, projectDir } = await getProjectConfig();
39
24
  try {
@@ -71,7 +56,7 @@ async function handler(args) {
71
56
  assetType: projectConfig.platformVersion,
72
57
  });
73
58
  try {
74
- const { result, uploadError, projectId } = await handleProjectUpload({
59
+ const { result, uploadError } = await handleProjectUpload({
75
60
  accountId: targetAccountId,
76
61
  projectConfig,
77
62
  projectDir,
@@ -105,12 +90,6 @@ async function handler(args) {
105
90
  logFeedbackMessage(result.buildId);
106
91
  await displayWarnLogs(targetAccountId, projectConfig.name, result.buildId);
107
92
  }
108
- if (result && result.succeeded && preview && targetPortalId) {
109
- const previewJson = await handlePreview(targetAccountId, projectId, result.buildId, targetPortalId);
110
- if (previewJson && formatOutputAsJson) {
111
- jsonOutput.preview = previewJson;
112
- }
113
- }
114
93
  if (result && result.succeeded && formatOutputAsJson) {
115
94
  jsonOutput.buildId = result.buildId;
116
95
  if (result.deployResult) {
@@ -153,25 +132,6 @@ function projectUploadBuilder(yargs) {
153
132
  alias: 'p',
154
133
  describe: commands.project.upload.options.profile.describe,
155
134
  },
156
- preview: {
157
- describe: commands.project.upload.options.preview.describe,
158
- type: 'boolean',
159
- default: false,
160
- },
161
- target: {
162
- describe: commands.project.upload.options.target.describe,
163
- type: 'number',
164
- requiresArg: true,
165
- },
166
- });
167
- yargs.check(argv => {
168
- if (argv.preview && argv.target == null) {
169
- throw new Error(commands.project.upload.errors.previewRequiresTarget);
170
- }
171
- if (argv.target != null && !argv.preview) {
172
- throw new Error(commands.project.upload.errors.targetRequiresPreview);
173
- }
174
- return true;
175
135
  });
176
136
  yargs.conflicts('profile', 'account');
177
137
  yargs.example([
@@ -180,10 +140,6 @@ function projectUploadBuilder(yargs) {
180
140
  '$0 project upload --profile=profileName',
181
141
  commands.project.upload.examples.withProfile,
182
142
  ],
183
- [
184
- '$0 project upload --preview --target=12345',
185
- commands.project.upload.examples.withPreview,
186
- ],
187
143
  ]);
188
144
  return yargs;
189
145
  }
package/lang/en.d.ts CHANGED
@@ -1805,7 +1805,6 @@ export declare const commands: {
1805
1805
  examples: {
1806
1806
  default: string;
1807
1807
  withProfile: string;
1808
- withPreview: string;
1809
1808
  };
1810
1809
  logs: {
1811
1810
  buildSucceeded: (buildId: number) => string;
@@ -1816,8 +1815,6 @@ export declare const commands: {
1816
1815
  errors: {
1817
1816
  noProjectConfig: string;
1818
1817
  projectLockedError: string;
1819
- previewRequiresTarget: string;
1820
- targetRequiresPreview: string;
1821
1818
  };
1822
1819
  options: {
1823
1820
  forceCreate: {
@@ -1829,12 +1826,6 @@ export declare const commands: {
1829
1826
  profile: {
1830
1827
  describe: string;
1831
1828
  };
1832
- preview: {
1833
- describe: string;
1834
- };
1835
- target: {
1836
- describe: string;
1837
- };
1838
1829
  };
1839
1830
  };
1840
1831
  watch: {
@@ -3402,16 +3393,6 @@ export declare const lib: {
3402
3393
  updatedFileDependency: (packageName: string, relativePath: string) => string;
3403
3394
  };
3404
3395
  };
3405
- projectPreview: {
3406
- triggeringPreview: (buildId: number, targetPortalId: number) => string;
3407
- pollingStatus: (releaseTag: string, targetPortalId: number) => string;
3408
- succeeded: (releaseTag: string, targetPortalId: number) => string;
3409
- triggerFailed: string;
3410
- pollFailed: string;
3411
- timeout: string;
3412
- warning: string;
3413
- missingProjectId: string;
3414
- };
3415
3396
  importData: {
3416
3397
  errors: {
3417
3398
  incorrectAccountType: (derivedAccountId: number) => string;
@@ -3642,6 +3623,7 @@ export declare const lib: {
3642
3623
  developerTestAccountLimit: (limit: number) => string;
3643
3624
  confirmDefaultAccount: (accountName: string, accountType: string) => string;
3644
3625
  confirmUseExistingDeveloperTestAccount: (accountName: string) => string;
3626
+ confirmLinkExistingDeveloperTestAccount: (accountName: string) => string;
3645
3627
  noAccountId: string;
3646
3628
  };
3647
3629
  projectLogsPrompt: {
package/lang/en.js CHANGED
@@ -1822,7 +1822,6 @@ export const commands = {
1822
1822
  examples: {
1823
1823
  default: 'Upload a project into your HubSpot account',
1824
1824
  withProfile: 'Upload a project into your HubSpot account when using profiles',
1825
- withPreview: 'Upload and preview the build on a target portal',
1826
1825
  },
1827
1826
  logs: {
1828
1827
  buildSucceeded: (buildId) => `Build #${buildId} succeeded\n`,
@@ -1833,8 +1832,6 @@ export const commands = {
1833
1832
  errors: {
1834
1833
  noProjectConfig: 'No project detected. Run this command from a project directory.',
1835
1834
  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.`,
1836
- previewRequiresTarget: `${uiCommandReference('--preview')} requires ${uiCommandReference('--target=<portalId>')} to specify the portal to preview on.`,
1837
- targetRequiresPreview: `${uiCommandReference('--target')} can only be used with ${uiCommandReference('--preview')}.`,
1838
1835
  },
1839
1836
  options: {
1840
1837
  forceCreate: {
@@ -1846,12 +1843,6 @@ export const commands = {
1846
1843
  profile: {
1847
1844
  describe: 'Profile to target for this upload',
1848
1845
  },
1849
- preview: {
1850
- describe: 'Preview the build on a target portal after a successful upload',
1851
- },
1852
- target: {
1853
- describe: 'Portal ID to preview the build on',
1854
- },
1855
1846
  },
1856
1847
  },
1857
1848
  watch: {
@@ -3428,16 +3419,6 @@ export const lib = {
3428
3419
  updatedFileDependency: (packageName, relativePath) => ` Updated dependencies.${packageName}: file:${relativePath}`,
3429
3420
  },
3430
3421
  },
3431
- projectPreview: {
3432
- triggeringPreview: (buildId, targetPortalId) => `Previewing build #${buildId} on portal ${targetPortalId}`,
3433
- pollingStatus: (releaseTag, targetPortalId) => `Previewing ${releaseTag} on portal ${targetPortalId}`,
3434
- succeeded: (releaseTag, targetPortalId) => `Previewed ${releaseTag} on portal ${targetPortalId}`,
3435
- triggerFailed: 'Failed to trigger preview',
3436
- pollFailed: 'Failed to poll preview status',
3437
- timeout: 'Preview timed out after 5 minutes',
3438
- warning: 'The build succeeded but the preview failed. You can manually preview this build from the project UI.',
3439
- missingProjectId: 'Unable to preview: could not resolve the project ID.',
3440
- },
3441
3422
  importData: {
3442
3423
  errors: {
3443
3424
  incorrectAccountType: (derivedAccountId) => `The account ${uiAccountDescription(derivedAccountId)} is not a standard account, developer test account, or app developer account.`,
@@ -3668,6 +3649,7 @@ export const lib = {
3668
3649
  developerTestAccountLimit: (limit) => `Your account reached the limit of ${limit} developer test accounts.`,
3669
3650
  confirmDefaultAccount: (accountName, accountType) => `Continue testing on ${chalk.bold(`${accountName} (${accountType})`)}? (Y/n)`,
3670
3651
  confirmUseExistingDeveloperTestAccount: (accountName) => `Continue with ${accountName}? This account isn't currently connected to the HubSpot CLI. By continuing, you'll be prompted to generate a personal access key and connect it.`,
3652
+ confirmLinkExistingDeveloperTestAccount: (accountName) => `${accountName} is not linked to this directory. Would you like to link it?`,
3671
3653
  noAccountId: 'No account ID found for the selected account. Please try again.',
3672
3654
  },
3673
3655
  projectLogsPrompt: {
@@ -4,7 +4,6 @@ export declare const FEEDBACK_INTERVAL: 10;
4
4
  export declare const HUBSPOT_FOLDER: "@hubspot";
5
5
  export declare const MARKETPLACE_FOLDER: "@marketplace";
6
6
  export declare const DEFAULT_POLLING_DELAY = 2000;
7
- export declare const PREVIEW_POLL_TIMEOUT: number;
8
7
  export declare const PROJECT_CONFIG_FILE: "hsproject.json";
9
8
  export declare const PROJECT_BUILD_STATES: {
10
9
  readonly BUILDING: "BUILDING";
package/lib/constants.js CHANGED
@@ -4,7 +4,6 @@ export const FEEDBACK_INTERVAL = 10;
4
4
  export const HUBSPOT_FOLDER = '@hubspot';
5
5
  export const MARKETPLACE_FOLDER = '@marketplace';
6
6
  export const DEFAULT_POLLING_DELAY = 2000;
7
- export const PREVIEW_POLL_TIMEOUT = 5 * 60 * 1000;
8
7
  export const PROJECT_CONFIG_FILE = 'hsproject.json';
9
8
  export const PROJECT_BUILD_STATES = {
10
9
  BUILDING: 'BUILDING',
@@ -5,7 +5,6 @@ type ProjectUploadResult<T> = {
5
5
  result?: T;
6
6
  uploadError?: unknown;
7
7
  projectNotFound?: boolean;
8
- projectId?: number;
9
8
  };
10
9
  type HandleProjectUploadArg<T> = {
11
10
  accountId: number;
@@ -79,7 +79,7 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
79
79
  return resolve({ uploadError: e });
80
80
  }
81
81
  }
82
- const { projectExists, project } = await ensureProjectExists(accountId, projectConfig.name, {
82
+ const { projectExists } = await ensureProjectExists(accountId, projectConfig.name, {
83
83
  forceCreate,
84
84
  uploadCommand: isUploadCommand,
85
85
  noLogs: true,
@@ -88,14 +88,13 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
88
88
  uiLogger.log(lib.projectUpload.handleProjectUpload.projectDoesNotExist(accountId));
89
89
  return resolve({ projectNotFound: true });
90
90
  }
91
- const projectId = project?.id;
92
91
  const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation);
93
92
  if (error) {
94
- resolve({ uploadError: error, projectId });
93
+ resolve({ uploadError: error });
95
94
  }
96
95
  else if (callbackFunc) {
97
96
  const uploadResult = await callbackFunc(accountId, projectConfig, tempFile, buildId);
98
- resolve({ result: uploadResult, projectId });
97
+ resolve({ result: uploadResult });
99
98
  }
100
99
  }
101
100
  catch (e) {
@@ -124,7 +123,7 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
124
123
  return ignored ? false : file;
125
124
  });
126
125
  // Archive workspaces and file: dependencies
127
- await archiveWorkspacesAndDependencies(archive, srcDir, projectDir, workspaceMappings, fileDependencyMappings);
126
+ await archiveWorkspacesAndDependencies(archive, srcDir, workspaceMappings, fileDependencyMappings);
128
127
  archive.finalize();
129
128
  return result;
130
129
  }
@@ -12,6 +12,16 @@ export type WorkspaceArchiveResult = {
12
12
  * Uses SHA256 truncated to 8 hex characters (4 billion possibilities).
13
13
  */
14
14
  export declare function shortHash(input: string): string;
15
+ /**
16
+ * Converts native path separators to POSIX forward slashes.
17
+ *
18
+ * Zip entry names and npm workspace globs are POSIX-only. On Windows,
19
+ * `path.relative` returns backslash-separated paths; archiver normalizes
20
+ * its appended entry names to forward slashes but its filter callback
21
+ * receives forward-slashed names too. Without this normalization, lookups
22
+ * in our exclusion Sets miss on Windows and a file gets archived twice.
23
+ */
24
+ export declare function toPosixPath(p: string): string;
15
25
  /**
16
26
  * Determines the archive path for an external workspace or file: dependency.
17
27
  * Produces `_workspaces/<basename>-<hash>` with no subdirectory.
@@ -39,4 +49,4 @@ export declare function getLockfilePathsToUpdate(srcDir: string, workspaceMappin
39
49
  * Main orchestration function that handles archiving of workspaces and file dependencies.
40
50
  * This is the clean integration point for upload.ts.
41
51
  */
42
- export declare function archiveWorkspacesAndDependencies(archive: archiver.Archiver, srcDir: string, projectDir: string, workspaceMappings: WorkspaceMapping[], fileDependencyMappings: FileDependencyMapping[]): Promise<WorkspaceArchiveResult>;
52
+ export declare function archiveWorkspacesAndDependencies(archive: archiver.Archiver, srcDir: string, workspaceMappings: WorkspaceMapping[], fileDependencyMappings: FileDependencyMapping[]): Promise<WorkspaceArchiveResult>;
@@ -12,6 +12,21 @@ import { lib } from '../../lang/en.js';
12
12
  export function shortHash(input) {
13
13
  return crypto.createHash('sha256').update(input).digest('hex').slice(0, 8);
14
14
  }
15
+ /**
16
+ * Converts native path separators to POSIX forward slashes.
17
+ *
18
+ * Zip entry names and npm workspace globs are POSIX-only. On Windows,
19
+ * `path.relative` returns backslash-separated paths; archiver normalizes
20
+ * its appended entry names to forward slashes but its filter callback
21
+ * receives forward-slashed names too. Without this normalization, lookups
22
+ * in our exclusion Sets miss on Windows and a file gets archived twice.
23
+ */
24
+ export function toPosixPath(p) {
25
+ if (path.sep === path.posix.sep) {
26
+ return p;
27
+ }
28
+ return p.replaceAll(path.sep, path.posix.sep);
29
+ }
15
30
  /**
16
31
  * Determines the archive path for an external workspace or file: dependency.
17
32
  * Produces `_workspaces/<basename>-<hash>` with no subdirectory.
@@ -20,7 +35,7 @@ export function shortHash(input) {
20
35
  export function computeExternalArchivePath(absolutePath) {
21
36
  const resolved = path.resolve(absolutePath);
22
37
  const name = path.basename(resolved);
23
- return path.join('_workspaces', `${name}-${shortHash(resolved)}`);
38
+ return path.posix.join('_workspaces', `${name}-${shortHash(resolved)}`);
24
39
  }
25
40
  /**
26
41
  * Returns true if dir is inside srcDir (i.e. it will already be included
@@ -71,7 +86,7 @@ async function archiveWorkspaceDirectories(archive, srcDir, workspaceMappings) {
71
86
  if (isInsideSrcDir(workspaceDir, srcDir)) {
72
87
  // Internal: already in archive from srcDir walk.
73
88
  // Store the relative path from the package.json directory so npm can resolve it.
74
- const relPath = path.relative(path.dirname(sourcePackageJsonPath), path.resolve(workspaceDir));
89
+ const relPath = toPosixPath(path.relative(path.dirname(sourcePackageJsonPath), path.resolve(workspaceDir)));
75
90
  packageWorkspaceEntries.get(sourcePackageJsonPath).push(relPath);
76
91
  }
77
92
  else {
@@ -89,7 +104,7 @@ async function archiveWorkspaceDirectories(archive, srcDir, workspaceMappings) {
89
104
  externalsToArchive.push({ dir: workspaceDir, archivePath });
90
105
  }
91
106
  const relPkgJsonDir = path.relative(srcDir, path.dirname(sourcePackageJsonPath));
92
- const relativeEntry = path.relative(relPkgJsonDir, archivePath);
107
+ const relativeEntry = toPosixPath(path.relative(relPkgJsonDir, archivePath));
93
108
  packageWorkspaceEntries.get(sourcePackageJsonPath).push(relativeEntry);
94
109
  }
95
110
  }
@@ -130,7 +145,7 @@ async function archiveFileDependencies(archive, srcDir, fileDependencyMappings,
130
145
  packageFileDeps.set(sourcePackageJsonPath, new Map());
131
146
  }
132
147
  const relPkgJsonDir = path.relative(srcDir, path.dirname(sourcePackageJsonPath));
133
- const relativeArchivePath = path.relative(relPkgJsonDir, archivePath);
148
+ const relativeArchivePath = toPosixPath(path.relative(relPkgJsonDir, archivePath));
134
149
  packageFileDeps
135
150
  .get(sourcePackageJsonPath)
136
151
  .set(packageName, relativeArchivePath);
@@ -172,7 +187,7 @@ export async function updatePackageJsonInArchive(archive, srcDir, packageWorkspa
172
187
  if (!fs.existsSync(packageJsonPath)) {
173
188
  continue;
174
189
  }
175
- const relativePackageJsonPath = path.relative(srcDir, packageJsonPath);
190
+ const relativePackageJsonPath = toPosixPath(path.relative(srcDir, packageJsonPath));
176
191
  let rawContent;
177
192
  try {
178
193
  rawContent = fs.readFileSync(packageJsonPath, 'utf8');
@@ -261,11 +276,11 @@ export function rewriteLockfileForExternalDeps(lockfileContent, pathMappings) {
261
276
  export function getPackageJsonPathsToUpdate(srcDir, workspaceMappings, fileDependencyMappings) {
262
277
  const paths = new Set();
263
278
  for (const { sourcePackageJsonPath } of workspaceMappings) {
264
- paths.add(path.relative(srcDir, sourcePackageJsonPath));
279
+ paths.add(toPosixPath(path.relative(srcDir, sourcePackageJsonPath)));
265
280
  }
266
281
  for (const { localPath, sourcePackageJsonPath } of fileDependencyMappings) {
267
282
  if (!isInsideSrcDir(localPath, srcDir)) {
268
- paths.add(path.relative(srcDir, sourcePackageJsonPath));
283
+ paths.add(toPosixPath(path.relative(srcDir, sourcePackageJsonPath)));
269
284
  }
270
285
  }
271
286
  return paths;
@@ -290,7 +305,7 @@ export function getLockfilePathsToUpdate(srcDir, workspaceMappings, fileDependen
290
305
  for (const dir of dirsWithExternalDeps) {
291
306
  const lockfilePath = path.join(dir, 'package-lock.json');
292
307
  if (fs.existsSync(lockfilePath)) {
293
- paths.add(path.relative(srcDir, lockfilePath));
308
+ paths.add(toPosixPath(path.relative(srcDir, lockfilePath)));
294
309
  }
295
310
  }
296
311
  return paths;
@@ -319,12 +334,12 @@ async function rewriteLockfilesInArchive(archive, srcDir, externalArchivePaths,
319
334
  const pathMappings = [];
320
335
  for (const [absoluteExternalPath, archivePath] of externalArchivePaths) {
321
336
  pathMappings.push({
322
- oldPath: path.relative(dir, absoluteExternalPath),
323
- newPath: path.relative(dir, path.join(srcDir, archivePath)),
337
+ oldPath: toPosixPath(path.relative(dir, absoluteExternalPath)),
338
+ newPath: toPosixPath(path.relative(dir, path.join(srcDir, archivePath))),
324
339
  });
325
340
  }
326
341
  const rewritten = rewriteLockfileForExternalDeps(lockfileContent, pathMappings);
327
- const relativeLockfilePath = path.relative(srcDir, lockfilePath);
342
+ const relativeLockfilePath = toPosixPath(path.relative(srcDir, lockfilePath));
328
343
  uiLogger.debug(lib.projectUpload.handleProjectUpload.updatingLockfile(relativeLockfilePath));
329
344
  archive.append(JSON.stringify(rewritten, null, 2), {
330
345
  name: relativeLockfilePath,
@@ -336,7 +351,7 @@ async function rewriteLockfilesInArchive(archive, srcDir, externalArchivePaths,
336
351
  * Main orchestration function that handles archiving of workspaces and file dependencies.
337
352
  * This is the clean integration point for upload.ts.
338
353
  */
339
- export async function archiveWorkspacesAndDependencies(archive, srcDir, projectDir, workspaceMappings, fileDependencyMappings) {
354
+ export async function archiveWorkspacesAndDependencies(archive, srcDir, workspaceMappings, fileDependencyMappings) {
340
355
  // Archive workspace directories (internal ones are skipped, externals are copied)
341
356
  const { externalArchivePaths, packageWorkspaceEntries } = await archiveWorkspaceDirectories(archive, srcDir, workspaceMappings);
342
357
  // Archive external file: dependencies (internals are skipped)
@@ -10,3 +10,4 @@ export declare function selectSandboxTargetAccountPrompt(accounts: HubSpotConfig
10
10
  export declare function selectDeveloperTestTargetAccountPrompt(accounts: HubSpotConfigAccount[], defaultAccountConfig: HubSpotConfigAccount): Promise<ProjectDevTargetAccountPromptResponse>;
11
11
  export declare function confirmDefaultAccountPrompt(accountName: string, accountType: string): Promise<boolean>;
12
12
  export declare function confirmUseExistingDeveloperTestAccountPrompt(account: DeveloperTestAccount): Promise<boolean>;
13
+ export declare function confirmLinkExistingDeveloperTestAccountPrompt(accountName: string): Promise<boolean>;
@@ -164,3 +164,13 @@ export async function confirmUseExistingDeveloperTestAccountPrompt(account) {
164
164
  ]);
165
165
  return confirmUseExistingDeveloperTestAccount;
166
166
  }
167
+ export async function confirmLinkExistingDeveloperTestAccountPrompt(accountName) {
168
+ const { confirmLinkExistingDeveloperTestAccount } = await promptUser([
169
+ {
170
+ name: 'confirmLinkExistingDeveloperTestAccount',
171
+ type: 'confirm',
172
+ message: lib.prompts.projectDevTargetAccountPrompt.confirmLinkExistingDeveloperTestAccount(accountName),
173
+ },
174
+ ]);
175
+ return confirmLinkExistingDeveloperTestAccount;
176
+ }
@@ -162,7 +162,7 @@ async function trackCliInteraction({ action, accountId, command, authType, meta
162
162
  }
163
163
  try {
164
164
  uiLogger.debug('Sent usage tracking command event:', usageTrackingEvent);
165
- return trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
165
+ await trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
166
166
  }
167
167
  catch (error) {
168
168
  debugError(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "8.0.12-experimental.1",
3
+ "version": "8.1.0-experimental.0",
4
4
  "description": "The official CLI for developing on HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": "https://github.com/HubSpot/hubspot-cli",
@@ -10,7 +10,7 @@
10
10
  "!**/__tests__/**"
11
11
  ],
12
12
  "dependencies": {
13
- "@hubspot/local-dev-lib": "0.7.9-experimental.0",
13
+ "@hubspot/local-dev-lib": "5.6.0",
14
14
  "@hubspot/project-parsing-lib": "0.16.0",
15
15
  "@hubspot/serverless-dev-runtime": "7.0.7",
16
16
  "@hubspot/ui-extensions-dev-server": "2.0.5",
@@ -1,7 +0,0 @@
1
- type PreviewResult = {
2
- succeeded: boolean;
3
- releaseTag?: string;
4
- appId?: number;
5
- };
6
- export declare function triggerAndPollPreview(accountId: number, projectId: number, buildId: number, targetPortalId: number): Promise<PreviewResult>;
7
- export {};
@@ -1,58 +0,0 @@
1
- import { triggerAutoRelease, getAutoReleaseStatus, } from '@hubspot/local-dev-lib/api/projects';
2
- import { DEFAULT_POLLING_DELAY, PREVIEW_POLL_TIMEOUT } from '../constants.js';
3
- import SpinniesManager from '../ui/SpinniesManager.js';
4
- import { logError, ApiErrorContext } from '../errorHandlers/index.js';
5
- import { lib } from '../../lang/en.js';
6
- export async function triggerAndPollPreview(accountId, projectId, buildId, targetPortalId) {
7
- let triggerResponse;
8
- SpinniesManager.add('preview', {
9
- text: lib.projectPreview.triggeringPreview(buildId, targetPortalId),
10
- succeedColor: 'white',
11
- });
12
- try {
13
- const { data } = await triggerAutoRelease(accountId, projectId, buildId, targetPortalId);
14
- triggerResponse = data;
15
- }
16
- catch (e) {
17
- SpinniesManager.fail('preview', {
18
- text: lib.projectPreview.triggerFailed,
19
- });
20
- logError(e, new ApiErrorContext({
21
- accountId,
22
- request: 'preview trigger',
23
- }));
24
- return { succeeded: false };
25
- }
26
- const { releaseTag, appId } = triggerResponse;
27
- SpinniesManager.update('preview', {
28
- text: lib.projectPreview.pollingStatus(releaseTag, targetPortalId),
29
- });
30
- try {
31
- await pollPreviewStatus(accountId, projectId, targetPortalId, releaseTag, appId);
32
- }
33
- catch (e) {
34
- SpinniesManager.fail('preview', {
35
- text: lib.projectPreview.pollFailed,
36
- });
37
- logError(e, new ApiErrorContext({
38
- accountId,
39
- request: 'preview status',
40
- }));
41
- return { succeeded: false, releaseTag, appId };
42
- }
43
- SpinniesManager.succeed('preview', {
44
- text: lib.projectPreview.succeeded(releaseTag, targetPortalId),
45
- });
46
- return { succeeded: true, releaseTag, appId };
47
- }
48
- async function pollPreviewStatus(accountId, projectId, targetPortalId, expectedReleaseTag, appId) {
49
- const startTime = Date.now();
50
- while (Date.now() - startTime < PREVIEW_POLL_TIMEOUT) {
51
- await new Promise(resolve => setTimeout(resolve, DEFAULT_POLLING_DELAY));
52
- const { data } = await getAutoReleaseStatus(accountId, projectId, targetPortalId, expectedReleaseTag, appId);
53
- if (data.status === 'COMPLETE') {
54
- return;
55
- }
56
- }
57
- throw new Error(lib.projectPreview.timeout);
58
- }