@hubspot/cli 7.4.2-experimental.0 → 7.4.2

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