@hubspot/cli 8.1.1-experimental.0 → 8.1.2-experimental.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 (124) hide show
  1. package/api/releases.d.ts +36 -0
  2. package/api/releases.js +41 -0
  3. package/commands/account/auth.js +2 -2
  4. package/commands/account/clean.js +2 -2
  5. package/commands/account/createOverride.js +2 -2
  6. package/commands/account/info.js +2 -2
  7. package/commands/account/link.js +2 -2
  8. package/commands/account/list.js +2 -2
  9. package/commands/account/remove.js +2 -2
  10. package/commands/account/removeOverride.js +2 -2
  11. package/commands/account/rename.js +2 -2
  12. package/commands/account/unlink.js +2 -2
  13. package/commands/account/use.js +2 -2
  14. package/commands/api.js +2 -2
  15. package/commands/app/migrate.js +2 -2
  16. package/commands/app/secret/add.js +2 -2
  17. package/commands/app/secret/delete.js +2 -2
  18. package/commands/app/secret/list.js +2 -2
  19. package/commands/app/secret/update.js +2 -2
  20. package/commands/auth.js +2 -2
  21. package/commands/cms/app/create.js +2 -2
  22. package/commands/cms/convertFields.js +2 -2
  23. package/commands/cms/delete.js +2 -2
  24. package/commands/cms/fetch.js +2 -2
  25. package/commands/cms/function/create.js +2 -2
  26. package/commands/cms/function/deploy.js +2 -2
  27. package/commands/cms/function/list.js +2 -2
  28. package/commands/cms/function/logs.js +2 -2
  29. package/commands/cms/function/server.js +2 -2
  30. package/commands/cms/getReactModule.js +2 -2
  31. package/commands/cms/lighthouseScore.js +2 -2
  32. package/commands/cms/lint.js +2 -2
  33. package/commands/cms/list.js +2 -2
  34. package/commands/cms/module/create.js +7 -2
  35. package/commands/cms/module/marketplace-validate.js +2 -2
  36. package/commands/cms/mv.js +2 -2
  37. package/commands/cms/template/create.js +2 -2
  38. package/commands/cms/theme/create.js +2 -2
  39. package/commands/cms/theme/generate-selectors.js +2 -2
  40. package/commands/cms/theme/marketplace-validate.js +2 -2
  41. package/commands/cms/theme/preview.js +2 -2
  42. package/commands/cms/upload.js +2 -2
  43. package/commands/cms/watch.js +2 -2
  44. package/commands/cms/webpack/create.js +2 -2
  45. package/commands/completion.js +2 -2
  46. package/commands/config/migrate.js +2 -2
  47. package/commands/config/set.js +2 -2
  48. package/commands/customObject/create.js +2 -2
  49. package/commands/customObject/createSchema.js +2 -2
  50. package/commands/customObject/deleteSchema.js +2 -2
  51. package/commands/customObject/fetchAllSchemas.js +2 -2
  52. package/commands/customObject/fetchSchema.js +2 -2
  53. package/commands/customObject/listSchemas.js +2 -2
  54. package/commands/customObject/updateSchema.js +2 -2
  55. package/commands/doctor.js +2 -2
  56. package/commands/feedback.js +2 -2
  57. package/commands/filemanager/fetch.js +2 -2
  58. package/commands/filemanager/upload.js +2 -2
  59. package/commands/getStarted.js +2 -2
  60. package/commands/hubdb/clear.js +2 -2
  61. package/commands/hubdb/create.js +2 -2
  62. package/commands/hubdb/delete.js +2 -2
  63. package/commands/hubdb/fetch.js +2 -2
  64. package/commands/hubdb/list.js +2 -2
  65. package/commands/init.js +2 -2
  66. package/commands/mcp/setup.js +2 -2
  67. package/commands/mcp/start.js +2 -2
  68. package/commands/open.js +2 -2
  69. package/commands/project/add.js +2 -2
  70. package/commands/project/appInstallStatus.js +2 -2
  71. package/commands/project/create.js +2 -2
  72. package/commands/project/delete.js +2 -2
  73. package/commands/project/deploy.js +2 -2
  74. package/commands/project/dev/index.js +2 -2
  75. package/commands/project/download.js +2 -2
  76. package/commands/project/info.js +2 -2
  77. package/commands/project/installDeps.js +2 -2
  78. package/commands/project/lint.js +4 -2
  79. package/commands/project/list.js +2 -2
  80. package/commands/project/listBuilds.js +2 -2
  81. package/commands/project/logs.js +2 -2
  82. package/commands/project/migrate.js +2 -2
  83. package/commands/project/open.js +2 -2
  84. package/commands/project/profile/add.js +2 -2
  85. package/commands/project/profile/delete.js +2 -2
  86. package/commands/project/updateDeps.js +2 -2
  87. package/commands/project/upload.d.ts +2 -0
  88. package/commands/project/upload.js +62 -9
  89. package/commands/project/validate.js +2 -2
  90. package/commands/project/watch.js +2 -2
  91. package/commands/sandbox/create.js +2 -2
  92. package/commands/sandbox/delete.js +2 -2
  93. package/commands/secret/addSecret.js +2 -2
  94. package/commands/secret/deleteSecret.js +2 -2
  95. package/commands/secret/listSecret.js +2 -2
  96. package/commands/secret/updateSecret.js +2 -2
  97. package/commands/testAccount/create.js +2 -2
  98. package/commands/testAccount/createConfig.js +2 -2
  99. package/commands/testAccount/delete.js +2 -2
  100. package/commands/testAccount/importData.js +2 -2
  101. package/commands/upgrade.js +2 -2
  102. package/lang/en.d.ts +18 -0
  103. package/lang/en.js +18 -0
  104. package/lib/constants.d.ts +1 -0
  105. package/lib/constants.js +1 -0
  106. package/lib/projects/localDev/helpers/project.js +1 -1
  107. package/lib/projects/pollProjectBuildAndDeploy.d.ts +5 -1
  108. package/lib/projects/pollProjectBuildAndDeploy.js +3 -2
  109. package/lib/projects/preview.d.ts +7 -0
  110. package/lib/projects/preview.js +48 -0
  111. package/lib/projects/upload.d.ts +1 -0
  112. package/lib/projects/upload.js +5 -4
  113. package/lib/projects/workspaces.d.ts +11 -1
  114. package/lib/projects/workspaces.js +27 -12
  115. package/lib/yargs/makeWrappedYargsHandler.d.ts +3 -0
  116. package/lib/yargs/{makeYargsHandlerWithUsageTracking.js → makeWrappedYargsHandler.js} +1 -1
  117. package/mcp-server/tools/cms/HsCreateFunctionTool.js +2 -2
  118. package/mcp-server/tools/cms/HsCreateModuleTool.js +7 -5
  119. package/mcp-server/tools/cms/HsCreateTemplateTool.js +2 -2
  120. package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -3
  121. package/mcp-server/tools/cms/HsListFunctionsTool.js +2 -3
  122. package/mcp-server/tools/cms/HsListTool.js +2 -2
  123. package/package.json +1 -1
  124. package/lib/yargs/makeYargsHandlerWithUsageTracking.d.ts +0 -3
@@ -11,7 +11,7 @@ import { selectAccountFromConfig } from '../../lib/prompts/accountsPrompt.js';
11
11
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
12
12
  import { promptUser } from '../../lib/prompts/promptUtils.js';
13
13
  import { uiAuthCommandReference, uiBetaTag } from '../../lib/ui/index.js';
14
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
14
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
15
15
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
16
16
  const command = 'delete';
17
17
  const describe = uiBetaTag(commands.sandbox.subcommands.delete.describe, false);
@@ -182,7 +182,7 @@ const builder = makeYargsBuilder(sandboxDeleteBuilder, command, describe, {
182
182
  const sandboxDeleteCommand = {
183
183
  command,
184
184
  describe,
185
- handler: makeYargsHandlerWithUsageTracking('sandbox-delete', handler),
185
+ handler: makeWrappedYargsHandler('sandbox-delete', handler),
186
186
  builder,
187
187
  };
188
188
  export default sandboxDeleteCommand;
@@ -4,7 +4,7 @@ import { secretValuePrompt, secretNamePrompt, } from '../../lib/prompts/secretPr
4
4
  import { commands } from '../../lang/en.js';
5
5
  import { uiLogger } from '../../lib/ui/logger.js';
6
6
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
7
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
7
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
8
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
9
  const command = 'add [name]';
10
10
  const describe = commands.secret.subcommands.add.describe;
@@ -51,7 +51,7 @@ const builder = makeYargsBuilder(addSecretBuilder, command, describe, {
51
51
  const addSecretCommand = {
52
52
  command,
53
53
  describe,
54
- handler: makeYargsHandlerWithUsageTracking('secrets-add', handler),
54
+ handler: makeWrappedYargsHandler('secrets-add', handler),
55
55
  builder,
56
56
  };
57
57
  export default addSecretCommand;
@@ -5,7 +5,7 @@ import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
5
  import { ApiErrorContext, logError } from '../../lib/errorHandlers/index.js';
6
6
  import { commands } from './../../lang/en.js';
7
7
  import { uiLogger } from '../../lib/ui/logger.js';
8
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
8
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
9
9
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
10
10
  const command = 'delete [name]';
11
11
  const describe = commands.secret.subcommands.delete.describe;
@@ -64,7 +64,7 @@ const builder = makeYargsBuilder(deleteSecretBuilder, command, describe, {
64
64
  const deleteSecretCommand = {
65
65
  command,
66
66
  describe,
67
- handler: makeYargsHandlerWithUsageTracking('secrets-delete', handler),
67
+ handler: makeWrappedYargsHandler('secrets-delete', handler),
68
68
  builder,
69
69
  };
70
70
  export default deleteSecretCommand;
@@ -3,7 +3,7 @@ import { logError, ApiErrorContext } from '../../lib/errorHandlers/index.js';
3
3
  import { uiAccountDescription } from '../../lib/ui/index.js';
4
4
  import { commands } from '../../lang/en.js';
5
5
  import { uiLogger } from '../../lib/ui/logger.js';
6
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
6
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
7
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
8
8
  const command = 'list';
9
9
  const describe = commands.secret.subcommands.list.describe;
@@ -36,7 +36,7 @@ const builder = makeYargsBuilder(listSecretBuilder, command, describe, {
36
36
  const listSecretCommand = {
37
37
  command,
38
38
  describe,
39
- handler: makeYargsHandlerWithUsageTracking('secrets-list', handler),
39
+ handler: makeWrappedYargsHandler('secrets-list', handler),
40
40
  builder,
41
41
  };
42
42
  export default listSecretCommand;
@@ -4,7 +4,7 @@ import { ApiErrorContext, logError } from '../../lib/errorHandlers/index.js';
4
4
  import { secretValuePrompt, secretListPrompt, } from '../../lib/prompts/secretPrompt.js';
5
5
  import { commands } from '../../lang/en.js';
6
6
  import { uiLogger } from '../../lib/ui/logger.js';
7
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
7
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
8
8
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
9
9
  const command = 'update [name]';
10
10
  const describe = commands.secret.subcommands.update.describe;
@@ -50,7 +50,7 @@ const builder = makeYargsBuilder(updateSecretBuilder, command, describe, {
50
50
  const updateSecretCommand = {
51
51
  command,
52
52
  describe,
53
- handler: makeYargsHandlerWithUsageTracking('secrets-update', handler),
53
+ handler: makeWrappedYargsHandler('secrets-update', handler),
54
54
  builder,
55
55
  };
56
56
  export default updateSecretCommand;
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  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
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
6
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
7
7
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
8
8
  import { promptUser, listPrompt } from '../../lib/prompts/promptUtils.js';
9
9
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -230,7 +230,7 @@ const builder = makeYargsBuilder(createTestAccountBuilder, command, describe, {
230
230
  const createTestAccountCommand = {
231
231
  command,
232
232
  describe,
233
- handler: makeYargsHandlerWithUsageTracking('test-account-create', handler),
233
+ handler: makeWrappedYargsHandler('test-account-create', handler),
234
234
  builder,
235
235
  };
236
236
  export default createTestAccountCommand;
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { getCwd } from '@hubspot/local-dev-lib/path';
4
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
4
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
5
5
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
6
6
  import { promptUser } from '../../lib/prompts/promptUtils.js';
7
7
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
@@ -85,7 +85,7 @@ const builder = makeYargsBuilder(createTestAccountConfigBuilder, command, descri
85
85
  const createTestAccountConfigCommand = {
86
86
  command,
87
87
  describe,
88
- handler: makeYargsHandlerWithUsageTracking('test-account-create-config', handler),
88
+ handler: makeWrappedYargsHandler('test-account-create-config', handler),
89
89
  builder,
90
90
  };
91
91
  export default createTestAccountConfigCommand;
@@ -1,5 +1,5 @@
1
1
  import { fetchDeveloperTestAccounts, deleteDeveloperTestAccount, } from '@hubspot/local-dev-lib/api/developerTestAccounts';
2
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
2
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
3
3
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
4
4
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
5
5
  import { uiLogger } from '../../lib/ui/logger.js';
@@ -191,7 +191,7 @@ const builder = makeYargsBuilder(deleteTestAccountBuilder, command, describe, {
191
191
  const deleteTestAccountCommand = {
192
192
  command,
193
193
  describe,
194
- handler: makeYargsHandlerWithUsageTracking('test-account-delete', handler),
194
+ handler: makeWrappedYargsHandler('test-account-delete', handler),
195
195
  builder,
196
196
  };
197
197
  export default deleteTestAccountCommand;
@@ -1,6 +1,6 @@
1
1
  import { getImportDataRequest } from '@hubspot/local-dev-lib/crm';
2
2
  import { logError } from '../../lib/errorHandlers/index.js';
3
- import { makeYargsHandlerWithUsageTracking } from '../../lib/yargs/makeYargsHandlerWithUsageTracking.js';
3
+ import { makeWrappedYargsHandler } from '../../lib/yargs/makeWrappedYargsHandler.js';
4
4
  import { makeYargsBuilder } from '../../lib/yargsUtils.js';
5
5
  import { EXIT_CODES } from '../../lib/enums/exitCodes.js';
6
6
  import { importDataFilePathPrompt } from '../../lib/prompts/importDataFilePathPrompt.js';
@@ -55,6 +55,6 @@ const crmImportDataCommand = {
55
55
  command,
56
56
  describe,
57
57
  builder,
58
- handler: makeYargsHandlerWithUsageTracking('crm-import-data', handler),
58
+ handler: makeWrappedYargsHandler('crm-import-data', handler),
59
59
  };
60
60
  export default crmImportDataCommand;
@@ -1,7 +1,7 @@
1
1
  import { isConfigFlagEnabled } from '@hubspot/local-dev-lib/config';
2
2
  import { CONFIG_FLAGS } from '@hubspot/local-dev-lib/constants/config';
3
3
  import { EXIT_CODES } from '../lib/enums/exitCodes.js';
4
- import { makeYargsHandlerWithUsageTracking } from '../lib/yargs/makeYargsHandlerWithUsageTracking.js';
4
+ import { makeWrappedYargsHandler } from '../lib/yargs/makeWrappedYargsHandler.js';
5
5
  import { makeYargsBuilder } from '../lib/yargsUtils.js';
6
6
  import { uiLogger } from '../lib/ui/logger.js';
7
7
  import { commands } from '../lang/en.js';
@@ -112,7 +112,7 @@ const builder = makeYargsBuilder(upgradeBuilder, command, describe, {
112
112
  const upgradeCommand = {
113
113
  command,
114
114
  describe,
115
- handler: makeYargsHandlerWithUsageTracking('upgrade', handler),
115
+ handler: makeWrappedYargsHandler('upgrade', handler),
116
116
  builder,
117
117
  };
118
118
  export default upgradeCommand;
package/lang/en.d.ts CHANGED
@@ -1805,6 +1805,7 @@ export declare const commands: {
1805
1805
  examples: {
1806
1806
  default: string;
1807
1807
  withProfile: string;
1808
+ withPreview: string;
1808
1809
  };
1809
1810
  logs: {
1810
1811
  buildSucceeded: (buildId: number) => string;
@@ -1815,6 +1816,8 @@ export declare const commands: {
1815
1816
  errors: {
1816
1817
  noProjectConfig: string;
1817
1818
  projectLockedError: string;
1819
+ previewRequiresTarget: string;
1820
+ targetRequiresPreview: string;
1818
1821
  };
1819
1822
  options: {
1820
1823
  forceCreate: {
@@ -1829,6 +1832,12 @@ export declare const commands: {
1829
1832
  skipNpmAudit: {
1830
1833
  describe: string;
1831
1834
  };
1835
+ preview: {
1836
+ describe: string;
1837
+ };
1838
+ target: {
1839
+ describe: string;
1840
+ };
1832
1841
  };
1833
1842
  };
1834
1843
  watch: {
@@ -3403,6 +3412,15 @@ export declare const lib: {
3403
3412
  npmAuditNonZeroExit: (packageRoot: string, exitCode: number) => string;
3404
3413
  };
3405
3414
  };
3415
+ projectPreview: {
3416
+ triggeringPreview: (buildId: number, targetPortalId: number) => string;
3417
+ pollingStatus: (releaseTag: string, targetPortalId: number) => string;
3418
+ succeeded: (releaseTag: string, targetPortalId: number) => string;
3419
+ triggerFailed: string;
3420
+ pollFailed: string;
3421
+ warning: string;
3422
+ missingProjectId: string;
3423
+ };
3406
3424
  importData: {
3407
3425
  errors: {
3408
3426
  incorrectAccountType: (derivedAccountId: number) => string;
package/lang/en.js CHANGED
@@ -1822,6 +1822,7 @@ 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',
1825
1826
  },
1826
1827
  logs: {
1827
1828
  buildSucceeded: (buildId) => `Build #${buildId} succeeded\n`,
@@ -1832,6 +1833,8 @@ export const commands = {
1832
1833
  errors: {
1833
1834
  noProjectConfig: 'No project detected. Run this command from a project directory.',
1834
1835
  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')}.`,
1835
1838
  },
1836
1839
  options: {
1837
1840
  forceCreate: {
@@ -1846,6 +1849,12 @@ export const commands = {
1846
1849
  skipNpmAudit: {
1847
1850
  describe: 'Skip the npm audit security check before uploading',
1848
1851
  },
1852
+ preview: {
1853
+ describe: 'Preview the build on a target portal after a successful upload',
1854
+ },
1855
+ target: {
1856
+ describe: 'Portal ID to preview the build on',
1857
+ },
1849
1858
  },
1850
1859
  },
1851
1860
  watch: {
@@ -3429,6 +3438,15 @@ export const lib = {
3429
3438
  npmAuditNonZeroExit: (packageRoot, exitCode) => `npm audit: ${chalk.bold(packageRoot)} exited with code ${exitCode}`,
3430
3439
  },
3431
3440
  },
3441
+ projectPreview: {
3442
+ triggeringPreview: (buildId, targetPortalId) => `Previewing build #${buildId} on ${uiAccountDescription(targetPortalId)}`,
3443
+ pollingStatus: (releaseTag, targetPortalId) => `Previewing ${chalk.bold(releaseTag)} on ${uiAccountDescription(targetPortalId)}`,
3444
+ succeeded: (releaseTag, targetPortalId) => `Previewed ${chalk.bold(releaseTag)} on ${uiAccountDescription(targetPortalId)}`,
3445
+ triggerFailed: 'Failed to trigger preview',
3446
+ pollFailed: 'Failed to poll preview status',
3447
+ warning: 'The build succeeded but the preview failed. You can manually preview this build from the project UI.',
3448
+ missingProjectId: 'Unable to preview: could not resolve the project ID.',
3449
+ },
3432
3450
  importData: {
3433
3451
  errors: {
3434
3452
  incorrectAccountType: (derivedAccountId) => `The account ${uiAccountDescription(derivedAccountId)} is not a standard account, developer test account, or app developer account.`,
@@ -4,6 +4,7 @@ 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;
7
8
  export declare const PROJECT_CONFIG_FILE: "hsproject.json";
8
9
  export declare const PROJECT_BUILD_STATES: {
9
10
  readonly BUILDING: "BUILDING";
package/lib/constants.js CHANGED
@@ -4,6 +4,7 @@ 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;
7
8
  export const PROJECT_CONFIG_FILE = 'hsproject.json';
8
9
  export const PROJECT_BUILD_STATES = {
9
10
  BUILDING: 'BUILDING',
@@ -70,7 +70,7 @@ function projectUploadCallback(accountId, projectConfig, tempFile, exit, buildId
70
70
  uiLogger.error(lib.localDevHelpers.project.createInitialBuildForNewProject.genericError);
71
71
  return exit(EXIT_CODES.ERROR);
72
72
  }
73
- return pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, true);
73
+ return pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, { silenceLogs: true });
74
74
  }
75
75
  // Create an initial build if the project was newly created in the account
76
76
  // Return the newly deployed build
@@ -6,5 +6,9 @@ type PollTaskStatusFunction<T extends ProjectTask> = (accountId: number, taskNam
6
6
  export declare const pollBuildStatus: PollTaskStatusFunction<Build>;
7
7
  export declare const pollDeployStatus: PollTaskStatusFunction<Deploy>;
8
8
  export declare function displayWarnLogs(accountId: number, projectName: string, taskId: number, isDeploy?: boolean): Promise<void>;
9
- export declare function pollProjectBuildAndDeploy(accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number, silenceLogs?: boolean): Promise<ProjectPollResult>;
9
+ type PollOptions = {
10
+ silenceLogs?: boolean;
11
+ skipDeploy?: boolean;
12
+ };
13
+ export declare function pollProjectBuildAndDeploy(accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number, options?: PollOptions): Promise<ProjectPollResult>;
10
14
  export {};
@@ -291,7 +291,8 @@ export async function displayWarnLogs(accountId, projectName, taskId, isDeploy =
291
291
  });
292
292
  }
293
293
  }
294
- export async function pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, silenceLogs = false) {
294
+ export async function pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, options = {}) {
295
+ const { silenceLogs = false, skipDeploy = false } = options;
295
296
  let buildStatus = await pollBuildStatus(accountId, projectConfig.name, buildId, null, silenceLogs);
296
297
  if (!silenceLogs) {
297
298
  uiLine();
@@ -306,7 +307,7 @@ export async function pollProjectBuildAndDeploy(accountId, projectConfig, tempFi
306
307
  result.succeeded = false;
307
308
  return result;
308
309
  }
309
- else if (buildStatus.isAutoDeployEnabled) {
310
+ else if (buildStatus.isAutoDeployEnabled && !skipDeploy) {
310
311
  if (!silenceLogs) {
311
312
  uiLogger.log(lib.projectBuildAndDeploy.pollProjectBuildAndDeploy.buildSucceededAutomaticallyDeploying(buildId, uiAccountDescription(accountId)));
312
313
  await displayWarnLogs(accountId, projectConfig.name, buildId);
@@ -0,0 +1,7 @@
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 {};
@@ -0,0 +1,48 @@
1
+ import { triggerAutoRelease, getAutoReleaseStatus, } from '../../api/releases.js';
2
+ import { PREVIEW_POLL_TIMEOUT } from '../constants.js';
3
+ import { poll } from '../polling.js';
4
+ import SpinniesManager from '../ui/SpinniesManager.js';
5
+ import { logError, ApiErrorContext } from '../errorHandlers/index.js';
6
+ import { lib } from '../../lang/en.js';
7
+ export async function triggerAndPollPreview(accountId, projectId, buildId, targetPortalId) {
8
+ let triggerResponse;
9
+ SpinniesManager.add('preview', {
10
+ text: lib.projectPreview.triggeringPreview(buildId, targetPortalId),
11
+ succeedColor: 'white',
12
+ });
13
+ try {
14
+ const { data } = await triggerAutoRelease(accountId, projectId, buildId, targetPortalId);
15
+ triggerResponse = data;
16
+ }
17
+ catch (e) {
18
+ SpinniesManager.fail('preview', {
19
+ text: lib.projectPreview.triggerFailed,
20
+ });
21
+ logError(e, new ApiErrorContext({
22
+ accountId,
23
+ request: 'preview trigger',
24
+ }));
25
+ return { succeeded: false };
26
+ }
27
+ const { releaseTag, appId } = triggerResponse;
28
+ SpinniesManager.update('preview', {
29
+ text: lib.projectPreview.pollingStatus(releaseTag, targetPortalId),
30
+ });
31
+ try {
32
+ await poll(() => getAutoReleaseStatus(accountId, projectId, targetPortalId, releaseTag, appId), { successStates: ['COMPLETE'], errorStates: [] }, PREVIEW_POLL_TIMEOUT);
33
+ }
34
+ catch (e) {
35
+ SpinniesManager.fail('preview', {
36
+ text: lib.projectPreview.pollFailed,
37
+ });
38
+ logError(e, new ApiErrorContext({
39
+ accountId,
40
+ request: 'preview status',
41
+ }));
42
+ return { succeeded: false, releaseTag, appId };
43
+ }
44
+ SpinniesManager.succeed('preview', {
45
+ text: lib.projectPreview.succeeded(releaseTag, targetPortalId),
46
+ });
47
+ return { succeeded: true, releaseTag, appId };
48
+ }
@@ -5,6 +5,7 @@ type ProjectUploadResult<T> = {
5
5
  result?: T;
6
6
  uploadError?: unknown;
7
7
  projectNotFound?: boolean;
8
+ projectId?: number;
8
9
  };
9
10
  type HandleProjectUploadArg<T> = {
10
11
  accountId: number;
@@ -89,7 +89,7 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
89
89
  return resolve({ uploadError: e });
90
90
  }
91
91
  }
92
- const { projectExists } = await ensureProjectExists(accountId, projectConfig.name, {
92
+ const { projectExists, project } = await ensureProjectExists(accountId, projectConfig.name, {
93
93
  forceCreate,
94
94
  uploadCommand: isUploadCommand,
95
95
  noLogs: true,
@@ -98,13 +98,14 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
98
98
  uiLogger.log(lib.projectUpload.handleProjectUpload.projectDoesNotExist(accountId));
99
99
  return resolve({ projectNotFound: true });
100
100
  }
101
+ const projectId = project?.id;
101
102
  const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation);
102
103
  if (error) {
103
- resolve({ uploadError: error });
104
+ resolve({ uploadError: error, projectId });
104
105
  }
105
106
  else if (callbackFunc) {
106
107
  const uploadResult = await callbackFunc(accountId, projectConfig, tempFile, buildId);
107
- resolve({ result: uploadResult });
108
+ resolve({ result: uploadResult, projectId });
108
109
  }
109
110
  }
110
111
  catch (e) {
@@ -133,7 +134,7 @@ export async function handleProjectUpload({ accountId, projectConfig, projectDir
133
134
  return ignored ? false : file;
134
135
  });
135
136
  // Archive workspaces and file: dependencies
136
- await archiveWorkspacesAndDependencies(archive, srcDir, projectDir, workspaceMappings, fileDependencyMappings);
137
+ await archiveWorkspacesAndDependencies(archive, srcDir, workspaceMappings, fileDependencyMappings);
137
138
  archive.finalize();
138
139
  return result;
139
140
  }
@@ -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)
@@ -0,0 +1,3 @@
1
+ import { ArgumentsCamelCase } from 'yargs';
2
+ import { CommonArgs } from '../../types/Yargs.js';
3
+ export declare function makeWrappedYargsHandler<T extends CommonArgs>(trackingName: string, handler: (args: ArgumentsCamelCase<T>) => Promise<void>): (args: ArgumentsCamelCase<T>) => Promise<void>;
@@ -32,7 +32,7 @@ function logUsageTrackingMessage(isJsonOutput) {
32
32
  return;
33
33
  }
34
34
  }
35
- export function makeYargsHandlerWithUsageTracking(trackingName, handler) {
35
+ export function makeWrappedYargsHandler(trackingName, handler) {
36
36
  return async (args) => {
37
37
  const startTime = Date.now();
38
38
  const meta = {};
@@ -59,7 +59,7 @@ export class HsCreateFunctionTool extends Tool {
59
59
  };
60
60
  }
61
61
  // Build the command
62
- let command = 'hs create function';
62
+ let command = 'hs cms function create';
63
63
  if (dest) {
64
64
  command += ` "${dest}"`;
65
65
  }
@@ -94,7 +94,7 @@ export class HsCreateFunctionTool extends Tool {
94
94
  register() {
95
95
  return this.mcpServer.registerTool(toolName, {
96
96
  title: 'Create HubSpot CMS Serverless Function',
97
- description: `Creates a new HubSpot CMS serverless function using the hs create function command. Functions can be created non-interactively by specifying functionsFolder, filename, and endpointPath. Supports all HTTP methods (${HTTP_METHODS.join(', ')}).`,
97
+ description: `Creates a new HubSpot CMS serverless function using the hs cms function create command. Functions can be created non-interactively by specifying functionsFolder, filename, and endpointPath. Supports all HTTP methods (${HTTP_METHODS.join(', ')}).`,
98
98
  inputSchema,
99
99
  annotations: {
100
100
  readOnlyHint: false,