@hubspot/cli 7.4.3-experimental.0 → 7.4.4-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/api/migrate.d.ts +71 -0
  2. package/api/migrate.js +58 -0
  3. package/bin/cli.js +8 -183
  4. package/commands/account/auth.d.ts +10 -0
  5. package/commands/account/auth.js +168 -0
  6. package/commands/account/clean.js +38 -5
  7. package/commands/account/createOverride.d.ts +10 -0
  8. package/commands/account/createOverride.js +104 -0
  9. package/commands/account/info.js +38 -4
  10. package/commands/account/list.js +23 -5
  11. package/commands/account/remove.js +36 -2
  12. package/commands/account/removeOverride.d.ts +10 -0
  13. package/commands/account/removeOverride.js +76 -0
  14. package/commands/account/use.js +25 -3
  15. package/commands/account.js +7 -2
  16. package/commands/app/migrate.d.ts +4 -5
  17. package/commands/app/migrate.js +24 -12
  18. package/commands/auth.js +14 -11
  19. package/commands/cms/lighthouseScore.js +6 -2
  20. package/commands/cms.js +1 -2
  21. package/commands/completion.js +2 -3
  22. package/commands/config/migrate.d.ts +10 -0
  23. package/commands/config/migrate.js +84 -0
  24. package/commands/config/set.d.ts +10 -0
  25. package/commands/config/set.js +34 -29
  26. package/commands/config.d.ts +4 -1
  27. package/commands/config.js +45 -11
  28. package/commands/create/api-sample.js +3 -1
  29. package/commands/create.js +7 -8
  30. package/commands/customObject/schema/delete.js +4 -1
  31. package/commands/customObject/schema/fetch-all.js +2 -1
  32. package/commands/customObject/schema/fetch.js +2 -1
  33. package/commands/customObject.js +3 -4
  34. package/commands/doctor.js +5 -6
  35. package/commands/feedback.js +7 -8
  36. package/commands/fetch.js +6 -7
  37. package/commands/filemanager.js +1 -2
  38. package/commands/function.js +1 -2
  39. package/commands/hubdb/clear.js +5 -6
  40. package/commands/hubdb/create.js +7 -8
  41. package/commands/hubdb/delete.js +8 -7
  42. package/commands/hubdb/fetch.js +4 -5
  43. package/commands/hubdb.js +1 -2
  44. package/commands/init.js +18 -20
  45. package/commands/lint.js +3 -4
  46. package/commands/list.js +5 -6
  47. package/commands/logs.js +12 -13
  48. package/commands/module/marketplace-validate.js +5 -6
  49. package/commands/module.js +1 -3
  50. package/commands/mv.js +4 -5
  51. package/commands/open.js +4 -5
  52. package/commands/project/add.js +17 -13
  53. package/commands/project/cloneApp.d.ts +5 -1
  54. package/commands/project/cloneApp.js +17 -12
  55. package/commands/project/create.js +18 -14
  56. package/commands/project/deploy.js +17 -15
  57. package/commands/project/dev/deprecatedFlow.js +19 -12
  58. package/commands/project/dev/index.js +12 -8
  59. package/commands/project/dev/unifiedFlow.js +2 -3
  60. package/commands/project/download.js +8 -9
  61. package/commands/project/installDeps.d.ts +9 -1
  62. package/commands/project/installDeps.js +46 -31
  63. package/commands/project/listBuilds.js +15 -11
  64. package/commands/project/logs.d.ts +13 -1
  65. package/commands/project/logs.js +72 -63
  66. package/commands/project/migrate.d.ts +11 -0
  67. package/commands/project/migrate.js +67 -0
  68. package/commands/project/migrateApp.d.ts +4 -4
  69. package/commands/project/migrateApp.js +7 -5
  70. package/commands/project/open.js +11 -5
  71. package/commands/project/upload.d.ts +12 -0
  72. package/commands/project/upload.js +67 -50
  73. package/commands/project/watch.js +22 -6
  74. package/commands/project.js +3 -2
  75. package/commands/remove.js +7 -5
  76. package/commands/sandbox/create.js +10 -11
  77. package/commands/sandbox/delete.js +18 -19
  78. package/commands/sandbox.js +1 -2
  79. package/commands/secret/addSecret.js +5 -6
  80. package/commands/secret/deleteSecret.js +12 -9
  81. package/commands/secret/listSecret.js +3 -4
  82. package/commands/secret/updateSecret.js +9 -8
  83. package/commands/secret.js +1 -2
  84. package/commands/theme/generate-selectors.js +5 -6
  85. package/commands/theme/marketplace-validate.js +5 -6
  86. package/commands/theme/preview.js +14 -14
  87. package/commands/theme.js +1 -2
  88. package/commands/upload.js +23 -24
  89. package/commands/watch.js +18 -19
  90. package/lang/en.d.ts +2792 -0
  91. package/lang/en.js +2648 -3300
  92. package/lang/en.lyaml +97 -43
  93. package/lib/accountTypes.d.ts +1 -0
  94. package/lib/accountTypes.js +12 -0
  95. package/lib/app/migrate.d.ts +10 -6
  96. package/lib/app/migrate.js +206 -220
  97. package/lib/app/migrate_legacy.d.ts +4 -0
  98. package/lib/app/migrate_legacy.js +132 -0
  99. package/lib/configMigrate.d.ts +2 -0
  100. package/lib/configMigrate.js +104 -0
  101. package/lib/constants.d.ts +4 -0
  102. package/lib/constants.js +5 -1
  103. package/lib/doctor/Diagnosis.d.ts +1 -2
  104. package/lib/doctor/Diagnosis.js +10 -6
  105. package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -0
  106. package/lib/doctor/DiagnosticInfoBuilder.js +1 -0
  107. package/lib/doctor/Doctor.d.ts +1 -0
  108. package/lib/doctor/Doctor.js +18 -0
  109. package/lib/errorHandlers/index.js +1 -1
  110. package/lib/hasFeature.d.ts +3 -1
  111. package/lib/localDev.d.ts +2 -1
  112. package/lib/localDev.js +21 -3
  113. package/lib/middleware/__test__/configMiddleware.test.d.ts +1 -0
  114. package/lib/middleware/__test__/configMiddleware.test.js +194 -0
  115. package/lib/middleware/__test__/gitMiddleware.test.d.ts +1 -0
  116. package/lib/middleware/__test__/gitMiddleware.test.js +76 -0
  117. package/lib/middleware/__test__/notificationsMiddleware.test.d.ts +1 -0
  118. package/lib/middleware/__test__/notificationsMiddleware.test.js +10 -0
  119. package/lib/middleware/__test__/requestMiddleware.test.d.ts +1 -0
  120. package/lib/middleware/__test__/requestMiddleware.test.js +20 -0
  121. package/lib/middleware/__test__/utils.test.d.ts +1 -0
  122. package/lib/middleware/__test__/utils.test.js +53 -0
  123. package/lib/middleware/__test__/yargsChecksMiddleware.test.d.ts +1 -0
  124. package/lib/middleware/__test__/yargsChecksMiddleware.test.js +81 -0
  125. package/lib/middleware/configMiddleware.d.ts +13 -0
  126. package/lib/middleware/configMiddleware.js +116 -0
  127. package/lib/middleware/fireAlarmMiddleware.d.ts +4 -0
  128. package/lib/middleware/fireAlarmMiddleware.js +137 -0
  129. package/lib/middleware/gitMiddleware.d.ts +2 -0
  130. package/lib/middleware/gitMiddleware.js +14 -0
  131. package/lib/middleware/notificationsMiddleware.d.ts +1 -0
  132. package/lib/middleware/notificationsMiddleware.js +38 -0
  133. package/lib/middleware/requestMiddleware.d.ts +1 -0
  134. package/lib/middleware/requestMiddleware.js +11 -0
  135. package/lib/middleware/utils.d.ts +8 -0
  136. package/lib/middleware/utils.js +17 -0
  137. package/lib/middleware/yargsChecksMiddleware.d.ts +4 -0
  138. package/lib/middleware/yargsChecksMiddleware.js +24 -0
  139. package/lib/projects/ProjectLogsManager.d.ts +1 -1
  140. package/lib/projects/ProjectLogsManager.js +1 -1
  141. package/lib/projects/index.d.ts +4 -3
  142. package/lib/projects/upload.d.ts +1 -1
  143. package/lib/prompts/promptUtils.d.ts +1 -1
  144. package/lib/ui/SpinniesManager.d.ts +1 -1
  145. package/lib/ui/index.d.ts +1 -0
  146. package/lib/ui/index.js +5 -0
  147. package/lib/ui/spinniesUtils.d.ts +5 -5
  148. package/package.json +7 -6
  149. package/types/Yargs.d.ts +0 -10
@@ -3,72 +3,85 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.downloadProjectFiles = downloadProjectFiles;
7
6
  exports.migrateApp2025_2 = migrateApp2025_2;
8
7
  exports.logInvalidAccountError = logInvalidAccountError;
9
- exports.migrateApp2023_2 = migrateApp2023_2;
10
- const promptUtils_1 = require("../prompts/promptUtils");
11
- const errorHandlers_1 = require("../errorHandlers");
12
- const exitCodes_1 = require("../enums/exitCodes");
13
8
  const logger_1 = require("@hubspot/local-dev-lib/logger");
14
- const ui_1 = require("../ui");
15
- const lang_1 = require("../lang");
16
- const accountTypes_1 = require("../accountTypes");
17
- const selectPublicAppPrompt_1 = require("../prompts/selectPublicAppPrompt");
18
- const appsDev_1 = require("@hubspot/local-dev-lib/api/appsDev");
19
- const createProjectPrompt_1 = require("../prompts/createProjectPrompt");
20
- const projects_1 = require("../projects");
21
- const usageTracking_1 = require("../usageTracking");
22
- const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
23
- const process_1 = require("../process");
24
- const projects_2 = require("@hubspot/local-dev-lib/api/projects");
25
- const polling_1 = require("../polling");
26
9
  const path_1 = __importDefault(require("path"));
27
10
  const path_2 = require("@hubspot/local-dev-lib/path");
28
- const urls_1 = require("@hubspot/local-dev-lib/urls");
29
11
  const archive_1 = require("@hubspot/local-dev-lib/archive");
30
12
  const chalk_1 = __importDefault(require("chalk"));
31
13
  const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
32
- const projects_3 = require("@hubspot/local-dev-lib/constants/projects");
14
+ const projects_1 = require("@hubspot/local-dev-lib/constants/projects");
33
15
  const transform_1 = require("@hubspot/project-parsing-lib/src/lib/transform");
16
+ const Migration_1 = require("@hubspot/local-dev-lib/types/Migration");
17
+ const projects_2 = require("@hubspot/local-dev-lib/api/projects");
18
+ const inquirer = require('inquirer');
19
+ const promptUtils_1 = require("../prompts/promptUtils");
20
+ const ui_1 = require("../ui");
21
+ const projects_3 = require("../projects");
22
+ const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
23
+ const polling_1 = require("../polling");
24
+ const migrate_1 = require("../../api/migrate");
25
+ const fs_1 = __importDefault(require("fs"));
26
+ const en_1 = require("../../lang/en");
27
+ const hasFeature_1 = require("../hasFeature");
28
+ const constants_1 = require("../constants");
29
+ const urls_1 = require("../projects/urls");
34
30
  function getUnmigratableReason(reasonCode) {
35
31
  switch (reasonCode) {
36
- case projects_3.UNMIGRATABLE_REASONS.UP_TO_DATE:
37
- return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.upToDate');
38
- case projects_3.UNMIGRATABLE_REASONS.IS_A_PRIVATE_APP:
39
- return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.isPrivateApp');
40
- case projects_3.UNMIGRATABLE_REASONS.LISTED_IN_MARKETPLACE:
41
- return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.listedInMarketplace');
32
+ case projects_1.UNMIGRATABLE_REASONS.UP_TO_DATE:
33
+ return en_1.lib.migrate.errors.unmigratableReasons.upToDate;
34
+ case projects_1.UNMIGRATABLE_REASONS.IS_A_PRIVATE_APP:
35
+ return en_1.lib.migrate.errors.unmigratableReasons.isPrivateApp;
36
+ case projects_1.UNMIGRATABLE_REASONS.LISTED_IN_MARKETPLACE:
37
+ return en_1.lib.migrate.errors.unmigratableReasons.listedInMarketplace;
38
+ case migrate_1.CLI_UNMIGRATABLE_REASONS.PART_OF_PROJECT_ALREADY:
39
+ return en_1.lib.migrate.errors.unmigratableReasons.partOfProjectAlready;
42
40
  default:
43
- return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.generic', {
44
- reasonCode,
45
- });
41
+ return en_1.lib.migrate.errors.unmigratableReasons.generic(reasonCode);
46
42
  }
47
43
  }
48
- async function handleMigrationSetup(derivedAccountId, options) {
49
- const { name, dest, appId } = options;
50
- const { data } = await (0, projects_2.listAppsForMigration)(derivedAccountId);
51
- const { migratableApps, unmigratableApps } = data;
52
- const allApps = [...migratableApps, ...unmigratableApps].filter(app => !app.projectName);
53
- if (allApps.length === 0) {
54
- throw new Error((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.noApps`, {
55
- accountId: derivedAccountId,
56
- }));
44
+ function filterAppsByProjectName(projectConfig) {
45
+ return (app) => {
46
+ if (projectConfig) {
47
+ return app.projectName === projectConfig?.projectConfig?.name;
48
+ }
49
+ return true;
50
+ };
51
+ }
52
+ async function fetchMigrationApps(appId, derivedAccountId, platformVersion, projectConfig) {
53
+ const { data: { migratableApps, unmigratableApps }, } = await (0, migrate_1.listAppsForMigration)(derivedAccountId, platformVersion);
54
+ const filteredMigratableApps = migratableApps.filter(filterAppsByProjectName(projectConfig));
55
+ const filteredUnmigratableApps = unmigratableApps.filter(filterAppsByProjectName(projectConfig));
56
+ const allApps = [...filteredMigratableApps, ...filteredUnmigratableApps];
57
+ if (allApps.length > 1 && projectConfig) {
58
+ throw new Error(en_1.lib.migrate.errors.project.multipleApps);
59
+ }
60
+ if (!projectConfig?.projectConfig) {
61
+ allApps.forEach(app => {
62
+ if (app.projectName) {
63
+ app.isMigratable = false;
64
+ app.unmigratableReason =
65
+ migrate_1.CLI_UNMIGRATABLE_REASONS.PART_OF_PROJECT_ALREADY;
66
+ }
67
+ });
68
+ }
69
+ if (allApps.length === 0 && projectConfig) {
70
+ throw new Error(en_1.lib.migrate.errors.noAppsForProject(projectConfig?.projectConfig?.name || ''));
57
71
  }
58
- if (migratableApps.length === 0) {
59
- const reasons = unmigratableApps.map(app => `${chalk_1.default.bold(app.appName)}: ${getUnmigratableReason(app.unmigratableReason)}`);
60
- throw new Error(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.noAppsEligible`, {
61
- accountId: derivedAccountId,
62
- })} \n - ${reasons.join('\n - ')}`);
72
+ if (allApps.length === 0 || !allApps.some(app => app.isMigratable)) {
73
+ const reasons = filteredUnmigratableApps.map(app => `${chalk_1.default.bold(app.appName)}: ${getUnmigratableReason(app.unmigratableReason)}`);
74
+ throw new Error(en_1.lib.migrate.errors.noAppsEligible((0, ui_1.uiAccountDescription)(derivedAccountId), reasons));
63
75
  }
64
76
  if (appId &&
65
77
  !allApps.some(app => {
66
78
  return app.appId === appId;
67
79
  })) {
68
- throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.chooseApp', {
69
- appId,
70
- }));
80
+ throw new Error(en_1.lib.migrate.errors.appWithAppIdNotFound(appId));
71
81
  }
82
+ return allApps;
83
+ }
84
+ async function promptForAppToMigrate(allApps) {
72
85
  const appChoices = allApps.map(app => ({
73
86
  name: app.isMigratable
74
87
  ? app.appName
@@ -78,147 +91,225 @@ async function handleMigrationSetup(derivedAccountId, options) {
78
91
  ? false
79
92
  : getUnmigratableReason(app.unmigratableReason),
80
93
  }));
94
+ const enabledChoices = appChoices.filter(app => !app.disabled);
95
+ const disabledChoices = appChoices.filter(app => app.disabled);
96
+ const { appId: selectedAppId } = await (0, promptUtils_1.listPrompt)(en_1.lib.migrate.prompt.chooseApp, {
97
+ choices: [
98
+ ...enabledChoices,
99
+ new inquirer.Separator(),
100
+ ...disabledChoices,
101
+ ],
102
+ });
103
+ return selectedAppId;
104
+ }
105
+ async function selectAppToMigrate(allApps, appId, projectConfig) {
106
+ if (appId &&
107
+ !allApps.some(app => {
108
+ return app.appId === appId;
109
+ })) {
110
+ throw new Error(en_1.lib.migrate.errors.appWithAppIdNotFound(appId));
111
+ }
81
112
  let appIdToMigrate = appId;
82
113
  if (!appIdToMigrate) {
83
- const { appId: selectedAppId } = await (0, promptUtils_1.listPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.chooseApp'), {
84
- choices: appChoices,
85
- });
86
- appIdToMigrate = selectedAppId;
114
+ appIdToMigrate = await promptForAppToMigrate(allApps);
87
115
  }
88
116
  const selectedApp = allApps.find(app => app.appId === appIdToMigrate);
89
- const migratableComponents = [];
90
- const unmigratableComponents = [];
117
+ const migratableComponents = new Set();
118
+ const unmigratableComponents = new Set();
91
119
  selectedApp?.migrationComponents.forEach(component => {
92
120
  if (component.isSupported) {
93
- migratableComponents.push((0, transform_1.mapToUserFacingType)(component.componentType));
121
+ migratableComponents.add((0, transform_1.mapToUserFacingType)(component.componentType));
94
122
  }
95
123
  else {
96
- unmigratableComponents.push((0, transform_1.mapToUserFacingType)(component.componentType));
124
+ unmigratableComponents.add((0, transform_1.mapToUserFacingType)(component.componentType));
97
125
  }
98
126
  });
99
- if (migratableComponents.length !== 0) {
100
- logger_1.logger.log((0, lang_1.i18n)('commands.project.subcommands.migrateApp.componentsToBeMigrated', {
101
- components: `\n - ${migratableComponents.join('\n - ')}`,
102
- }));
127
+ if (migratableComponents.size !== 0) {
128
+ logger_1.logger.log(en_1.lib.migrate.componentsToBeMigrated(`\n - ${[...migratableComponents].join('\n - ')}`));
103
129
  }
104
- if (unmigratableComponents.length !== 0) {
105
- logger_1.logger.log((0, lang_1.i18n)('commands.project.subcommands.migrateApp.componentsThatWillNotBeMigrated', {
106
- components: `\n - ${unmigratableComponents.join('\n - ')}`,
107
- }));
130
+ if (unmigratableComponents.size !== 0) {
131
+ logger_1.logger.log(en_1.lib.migrate.componentsThatWillNotBeMigrated(`\n - ${[...unmigratableComponents].join('\n - ')}`));
108
132
  }
109
133
  logger_1.logger.log();
110
- const proceed = await (0, promptUtils_1.confirmPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.proceed'));
134
+ const promptMessage = projectConfig?.projectConfig
135
+ ? `${en_1.lib.migrate.projectMigrationWarning} ${en_1.lib.migrate.prompt.proceed}`
136
+ : en_1.lib.migrate.prompt.proceed;
137
+ const proceed = await (0, promptUtils_1.confirmPrompt)(promptMessage, { defaultAnswer: false });
138
+ return {
139
+ proceed,
140
+ appIdToMigrate,
141
+ };
142
+ }
143
+ async function handleMigrationSetup(derivedAccountId, options, projectConfig) {
144
+ const { name, dest, appId } = options;
145
+ const allApps = await fetchMigrationApps(appId, derivedAccountId, options.platformVersion, projectConfig);
146
+ const { proceed, appIdToMigrate } = await selectAppToMigrate(allApps, appId, projectConfig);
111
147
  if (!proceed) {
112
148
  return {};
113
149
  }
150
+ // If it's a project we don't want to prompt for dest and name, so just return early
151
+ if (projectConfig &&
152
+ projectConfig?.projectConfig &&
153
+ projectConfig?.projectDir) {
154
+ return {
155
+ appIdToMigrate,
156
+ projectName: projectConfig.projectConfig.name,
157
+ projectDest: projectConfig.projectDir,
158
+ };
159
+ }
114
160
  const projectName = name ||
115
- (await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.inputName')));
116
- const { projectExists } = await (0, projects_1.ensureProjectExists)(derivedAccountId, projectName, { allowCreate: false, noLogs: true });
117
- if (projectExists) {
118
- throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.errors.projectAlreadyExists', {
119
- projectName,
161
+ (await (0, promptUtils_1.inputPrompt)(en_1.lib.migrate.prompt.inputName, {
162
+ validate: async (input) => {
163
+ const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, input, { allowCreate: false, noLogs: true });
164
+ if (projectExists) {
165
+ return en_1.lib.migrate.errors.project.alreadyExists(input);
166
+ }
167
+ return true;
168
+ },
120
169
  }));
170
+ const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, projectName, { allowCreate: false, noLogs: true });
171
+ if (projectExists) {
172
+ throw new Error(en_1.lib.migrate.errors.project.alreadyExists(projectName));
121
173
  }
122
174
  const projectDest = dest ||
123
- (await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.inputDest'), {
175
+ (await (0, promptUtils_1.inputPrompt)(en_1.lib.migrate.prompt.inputDest, {
124
176
  defaultAnswer: path_1.default.resolve((0, path_2.getCwd)(), (0, path_2.sanitizeFileName)(projectName)),
125
177
  }));
126
178
  return { appIdToMigrate, projectName, projectDest };
127
179
  }
128
180
  async function beginMigration(derivedAccountId, appId, platformVersion) {
129
181
  SpinniesManager_1.default.add('beginningMigration', {
130
- text: (0, lang_1.i18n)('commands.project.subcommands.migrateApp.spinners.beginningMigration'),
182
+ text: en_1.lib.migrate.spinners.beginningMigration,
131
183
  });
132
184
  const uidMap = {};
133
- const { data } = await (0, projects_2.initializeMigration)(derivedAccountId, appId, platformVersion);
185
+ const { data } = await (0, migrate_1.initializeMigration)(derivedAccountId, appId, platformVersion);
134
186
  const { migrationId } = data;
135
- const pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, ['INPUT_REQUIRED']);
136
- if (pollResponse.status !== 'INPUT_REQUIRED') {
187
+ const pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, [Migration_1.MIGRATION_STATUS.INPUT_REQUIRED]);
188
+ if (pollResponse.status !== Migration_1.MIGRATION_STATUS.INPUT_REQUIRED) {
137
189
  SpinniesManager_1.default.fail('beginningMigration', {
138
- text: (0, lang_1.i18n)('commands.project.subcommands.migrateApp.spinners.unableToStartMigration'),
190
+ text: en_1.lib.migrate.spinners.unableToStartMigration,
139
191
  });
140
192
  return;
141
193
  }
142
194
  const { componentsRequiringUids } = pollResponse;
143
- SpinniesManager_1.default.succeed('beginningMigration', {
144
- text: (0, lang_1.i18n)('commands.project.subcommands.migrateApp.spinners.migrationStarted'),
145
- });
195
+ SpinniesManager_1.default.remove('beginningMigration');
146
196
  if (Object.values(componentsRequiringUids).length !== 0) {
147
197
  for (const [componentId, component] of Object.entries(componentsRequiringUids)) {
148
- uidMap[componentId] = await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.uidForComponent', {
149
- componentName: component.componentHint || component.componentType,
150
- }), {
198
+ const { componentHint, componentType } = component;
199
+ uidMap[componentId] = await (0, promptUtils_1.inputPrompt)(en_1.lib.migrate.prompt.uidForComponent(componentHint
200
+ ? `${(0, transform_1.mapToUserFacingType)(componentType)} '${componentHint}'`
201
+ : (0, transform_1.mapToUserFacingType)(componentType)), {
151
202
  validate: (uid) => {
152
203
  const result = (0, project_parsing_lib_1.validateUid)(uid);
153
204
  return result === undefined ? true : result;
154
205
  },
206
+ defaultAnswer: componentHint
207
+ ? componentHint.replace(/[^A-Za-z0-9_\-.]/g, '')
208
+ : undefined,
155
209
  });
156
210
  }
157
211
  }
158
212
  return { migrationId, uidMap };
159
213
  }
160
214
  async function pollMigrationStatus(derivedAccountId, migrationId, successStates = []) {
161
- return (0, polling_1.poll)(() => (0, projects_2.checkMigrationStatusV2)(derivedAccountId, migrationId), {
215
+ return (0, polling_1.poll)(() => (0, migrate_1.checkMigrationStatusV2)(derivedAccountId, migrationId), {
162
216
  successStates: [...successStates],
163
217
  errorStates: [...polling_1.DEFAULT_POLLING_STATUS_LOOKUP.errorStates],
164
218
  });
165
219
  }
166
220
  async function finalizeMigration(derivedAccountId, migrationId, uidMap, projectName) {
167
- let buildId;
221
+ let pollResponse;
168
222
  try {
169
223
  SpinniesManager_1.default.add('finishingMigration', {
170
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.finishingMigration`),
224
+ text: en_1.lib.migrate.spinners.finishingMigration,
171
225
  });
172
- await (0, projects_2.continueMigration)(derivedAccountId, migrationId, uidMap, projectName);
173
- const pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, ['SUCCESS']);
174
- if (pollResponse.status === 'SUCCESS') {
175
- buildId = pollResponse.buildId;
176
- SpinniesManager_1.default.succeed('finishingMigration', {
177
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationComplete`),
178
- });
179
- }
180
- else {
181
- SpinniesManager_1.default.fail('finishingMigration', {
182
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationFailed`),
183
- });
184
- }
185
- return buildId;
226
+ await (0, migrate_1.continueMigration)(derivedAccountId, migrationId, uidMap, projectName);
227
+ pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, [
228
+ Migration_1.MIGRATION_STATUS.SUCCESS,
229
+ ]);
186
230
  }
187
231
  catch (error) {
188
232
  SpinniesManager_1.default.fail('finishingMigration', {
189
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationFailed`),
233
+ text: en_1.lib.migrate.spinners.migrationFailed,
234
+ });
235
+ if ((0, migrate_1.isMigrationStatus)(error) && error.status === Migration_1.MIGRATION_STATUS.FAILURE) {
236
+ const errorMessage = error.componentErrors
237
+ ? `${error.projectErrorDetail}: \n\t- ${error.componentErrors
238
+ .map(componentError => {
239
+ const { componentType, errorMessage, developerSymbol: uid, } = componentError;
240
+ return `${componentType}${uid ? ` (${uid})` : ''}: ${errorMessage}`;
241
+ })
242
+ .join('\n\t- ')}`
243
+ : error.projectErrorDetail;
244
+ throw new Error(errorMessage);
245
+ }
246
+ throw new Error(en_1.lib.migrate.errors.migrationFailed, {
247
+ cause: error,
248
+ });
249
+ }
250
+ if (pollResponse.status !== Migration_1.MIGRATION_STATUS.SUCCESS) {
251
+ throw new Error(en_1.lib.migrate.errors.migrationFailed);
252
+ }
253
+ if (pollResponse.status === Migration_1.MIGRATION_STATUS.SUCCESS) {
254
+ SpinniesManager_1.default.succeed('finishingMigration', {
255
+ text: en_1.lib.migrate.spinners.migrationComplete,
190
256
  });
191
- throw error;
192
257
  }
258
+ return pollResponse.buildId;
193
259
  }
194
- async function downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest) {
260
+ async function downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest, projectConfig) {
195
261
  try {
196
262
  SpinniesManager_1.default.add('fetchingMigratedProject', {
197
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContents`),
263
+ text: en_1.lib.migrate.spinners.downloadingProjectContents,
198
264
  });
199
265
  const { data: zippedProject } = await (0, projects_2.downloadProject)(derivedAccountId, projectName, buildId);
200
- const absoluteDestPath = projectDest
201
- ? path_1.default.resolve((0, path_2.getCwd)(), projectDest)
202
- : (0, path_2.getCwd)();
266
+ let absoluteDestPath;
267
+ if (projectConfig?.projectConfig && projectConfig?.projectDir) {
268
+ const { projectDir } = projectConfig;
269
+ absoluteDestPath = projectDir;
270
+ const { srcDir } = projectConfig.projectConfig;
271
+ const archiveDest = path_1.default.join(projectDir, 'archive');
272
+ // Move the existing source directory to archive
273
+ fs_1.default.renameSync(path_1.default.join(projectDir, srcDir), archiveDest);
274
+ logger_1.logger.info(en_1.lib.migrate.sourceContentsMoved(archiveDest));
275
+ }
276
+ else {
277
+ absoluteDestPath = projectDest
278
+ ? path_1.default.resolve((0, path_2.getCwd)(), projectDest)
279
+ : (0, path_2.getCwd)();
280
+ }
203
281
  await (0, archive_1.extractZipArchive)(zippedProject, (0, path_2.sanitizeFileName)(projectName), absoluteDestPath, {
204
282
  includesRootDir: true,
205
- hideLogs: false,
283
+ hideLogs: true,
206
284
  });
207
285
  SpinniesManager_1.default.succeed('fetchingMigratedProject', {
208
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContentsComplete`),
286
+ text: en_1.lib.migrate.spinners.downloadingProjectContentsComplete,
209
287
  });
210
288
  logger_1.logger.success(`Saved ${projectName} to ${projectDest}`);
211
289
  }
212
290
  catch (error) {
213
291
  SpinniesManager_1.default.fail('fetchingMigratedProject', {
214
- text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContentsFailed`),
292
+ text: en_1.lib.migrate.spinners.downloadingProjectContentsFailed,
215
293
  });
216
294
  throw error;
217
295
  }
218
296
  }
219
- async function migrateApp2025_2(derivedAccountId, options) {
297
+ async function migrateApp2025_2(derivedAccountId, options, projectConfig) {
220
298
  SpinniesManager_1.default.init();
221
- const { appIdToMigrate, projectName, projectDest } = await handleMigrationSetup(derivedAccountId, options);
299
+ const ungatedForUnifiedApps = await (0, hasFeature_1.hasFeature)(derivedAccountId, constants_1.FEATURES.UNIFIED_APPS);
300
+ if (!ungatedForUnifiedApps) {
301
+ throw new Error(en_1.lib.migrate.errors.notUngatedForUnifiedApps((0, ui_1.uiAccountDescription)(derivedAccountId)));
302
+ }
303
+ if (projectConfig) {
304
+ if (!projectConfig?.projectConfig || !projectConfig?.projectDir) {
305
+ throw new Error(en_1.lib.migrate.errors.project.invalidConfig);
306
+ }
307
+ const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, projectConfig.projectConfig.name, { allowCreate: false, noLogs: true });
308
+ if (!projectExists) {
309
+ throw new Error(en_1.lib.migrate.errors.project.doesNotExist(derivedAccountId));
310
+ }
311
+ }
312
+ const { appIdToMigrate, projectName, projectDest } = await handleMigrationSetup(derivedAccountId, options, projectConfig);
222
313
  if (!appIdToMigrate || !projectName || !projectDest) {
223
314
  return;
224
315
  }
@@ -227,119 +318,14 @@ async function migrateApp2025_2(derivedAccountId, options) {
227
318
  return;
228
319
  }
229
320
  const { migrationId, uidMap } = migrationInProgress;
230
- const buildId = await finalizeMigration(derivedAccountId, migrationId, uidMap, projectName);
231
- if (!buildId) {
232
- throw new Error('Migration Failed');
233
- }
234
- await downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest);
235
- }
236
- function logInvalidAccountError(i18nKey) {
237
- (0, ui_1.uiLine)();
238
- logger_1.logger.error((0, lang_1.i18n)(`${i18nKey}.errors.invalidAccountTypeTitle`));
239
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.errors.invalidAccountTypeDescription`, {
240
- useCommand: (0, ui_1.uiCommandReference)('hs accounts use'),
241
- authCommand: (0, ui_1.uiCommandReference)('hs auth'),
242
- }));
243
- (0, ui_1.uiLine)();
321
+ const buildId = await finalizeMigration(derivedAccountId, migrationId, uidMap, projectConfig?.projectConfig?.name || projectName);
322
+ await downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest, projectConfig);
323
+ logger_1.logger.log((0, ui_1.uiLink)('Project Details', (0, urls_1.getProjectDetailUrl)(projectName, derivedAccountId)));
324
+ logger_1.logger.log((0, ui_1.uiLink)('Build Details', (0, urls_1.getProjectBuildDetailUrl)(projectName, buildId, derivedAccountId)));
244
325
  }
245
- async function migrateApp2023_2(derivedAccountId, options, accountConfig) {
246
- const i18nKey = 'commands.project.subcommands.migrateApp';
247
- const accountName = (0, ui_1.uiAccountDescription)(derivedAccountId);
248
- if (!(0, accountTypes_1.isAppDeveloperAccount)(accountConfig)) {
249
- logInvalidAccountError(i18nKey);
250
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
251
- }
252
- const { appId } = 'appId' in options
253
- ? options
254
- : await (0, selectPublicAppPrompt_1.selectPublicAppPrompt)({
255
- accountId: derivedAccountId,
256
- accountName,
257
- isMigratingApp: true,
258
- });
259
- try {
260
- const { data: selectedApp } = await (0, appsDev_1.fetchPublicAppMetadata)(appId, derivedAccountId);
261
- // preventProjectMigrations returns true if we have not added app to allowlist config.
262
- // listingInfo will only exist for marketplace apps
263
- const preventProjectMigrations = selectedApp.preventProjectMigrations;
264
- const listingInfo = selectedApp.listingInfo;
265
- if (preventProjectMigrations && listingInfo) {
266
- logger_1.logger.error((0, lang_1.i18n)(`${i18nKey}.errors.invalidApp`, { appId }));
267
- process.exit(exitCodes_1.EXIT_CODES.ERROR);
268
- }
269
- }
270
- catch (error) {
271
- (0, errorHandlers_1.logError)(error, new errorHandlers_1.ApiErrorContext({ accountId: derivedAccountId }));
272
- process.exit(exitCodes_1.EXIT_CODES.ERROR);
273
- }
274
- const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(options);
275
- const { name: projectName, dest: projectDest } = createProjectPromptResponse;
276
- const { projectExists } = await (0, projects_1.ensureProjectExists)(derivedAccountId, projectName, {
277
- allowCreate: false,
278
- noLogs: true,
279
- });
280
- if (projectExists) {
281
- throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.projectAlreadyExists`, {
282
- projectName,
283
- }));
284
- }
285
- await (0, usageTracking_1.trackCommandMetadataUsage)('migrate-app', { step: 'STARTED' }, derivedAccountId);
286
- logger_1.logger.log('');
326
+ function logInvalidAccountError() {
287
327
  (0, ui_1.uiLine)();
288
- logger_1.logger.warn(`${(0, lang_1.i18n)(`${i18nKey}.warning.title`)}\n`);
289
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.warning.projectConversion`));
290
- logger_1.logger.log(`${(0, lang_1.i18n)(`${i18nKey}.warning.appConfig`)}\n`);
291
- logger_1.logger.log(`${(0, lang_1.i18n)(`${i18nKey}.warning.buildAndDeploy`)}\n`);
292
- logger_1.logger.log(`${(0, lang_1.i18n)(`${i18nKey}.warning.existingApps`)}\n`);
293
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.warning.copyApp`));
328
+ logger_1.logger.error(en_1.lib.migrate.errors.invalidAccountTypeTitle);
329
+ logger_1.logger.log(en_1.lib.migrate.errors.invalidAccountTypeDescription((0, ui_1.uiCommandReference)('hs account use'), (0, ui_1.uiCommandReference)('hs auth')));
294
330
  (0, ui_1.uiLine)();
295
- const { shouldCreateApp } = await (0, promptUtils_1.promptUser)({
296
- name: 'shouldCreateApp',
297
- type: 'confirm',
298
- message: (0, lang_1.i18n)(`${i18nKey}.createAppPrompt`),
299
- });
300
- process.stdin.resume();
301
- if (!shouldCreateApp) {
302
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
303
- }
304
- try {
305
- SpinniesManager_1.default.init();
306
- SpinniesManager_1.default.add('migrateApp', {
307
- text: (0, lang_1.i18n)(`${i18nKey}.migrationStatus.inProgress`),
308
- });
309
- (0, process_1.handleKeypress)(async (key) => {
310
- if ((key.ctrl && key.name === 'c') || key.name === 'q') {
311
- SpinniesManager_1.default.remove('migrateApp');
312
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.migrationInterrupted`));
313
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
314
- }
315
- });
316
- const { data: migrateResponse } = await (0, projects_2.migrateApp)(derivedAccountId, appId, projectName);
317
- const { id } = migrateResponse;
318
- const pollResponse = await (0, polling_1.poll)(() => (0, projects_2.checkMigrationStatus)(derivedAccountId, id));
319
- const { status, project } = pollResponse;
320
- if (status === 'SUCCESS') {
321
- const absoluteDestPath = path_1.default.resolve((0, path_2.getCwd)(), projectDest);
322
- const { env } = accountConfig;
323
- const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)(env);
324
- const { data: zippedProject } = await (0, projects_2.downloadProject)(derivedAccountId, projectName, 1);
325
- await (0, archive_1.extractZipArchive)(zippedProject, (0, path_2.sanitizeFileName)(projectName), path_1.default.resolve(absoluteDestPath), { includesRootDir: true, hideLogs: true });
326
- SpinniesManager_1.default.succeed('migrateApp', {
327
- text: (0, lang_1.i18n)(`${i18nKey}.migrationStatus.done`),
328
- succeedColor: 'white',
329
- });
330
- logger_1.logger.log('');
331
- (0, ui_1.uiLine)();
332
- logger_1.logger.success((0, lang_1.i18n)(`${i18nKey}.migrationStatus.success`));
333
- logger_1.logger.log('');
334
- logger_1.logger.log((0, ui_1.uiLink)((0, lang_1.i18n)(`${i18nKey}.projectDetailsLink`), `${baseUrl}/developer-projects/${derivedAccountId}/project/${encodeURIComponent(project.name)}`));
335
- process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
336
- }
337
- }
338
- catch (error) {
339
- SpinniesManager_1.default.fail('migrateApp', {
340
- text: (0, lang_1.i18n)(`${i18nKey}.migrationStatus.failure`),
341
- failColor: 'white',
342
- });
343
- throw error;
344
- }
345
331
  }
@@ -0,0 +1,4 @@
1
+ import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
2
+ import { ArgumentsCamelCase } from 'yargs';
3
+ import { MigrateAppArgs } from './migrate';
4
+ export declare function migrateApp2023_2(derivedAccountId: number, options: ArgumentsCamelCase<MigrateAppArgs>, accountConfig: CLIAccount): Promise<void>;