@hubspot/cli 7.3.0-experimental.2 → 7.4.0-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.
- package/api/migrate.d.ts +61 -0
- package/api/migrate.js +44 -0
- package/bin/cli.js +10 -241
- package/commands/account/auth.d.ts +10 -0
- package/commands/account/auth.js +168 -0
- package/commands/account/clean.js +45 -13
- package/commands/account/createOverride.d.ts +10 -0
- package/commands/account/createOverride.js +104 -0
- package/commands/account/info.js +43 -11
- package/commands/account/list.js +27 -10
- package/commands/account/remove.js +42 -9
- package/commands/account/removeOverride.d.ts +10 -0
- package/commands/account/removeOverride.js +76 -0
- package/commands/account/rename.js +4 -5
- package/commands/account/use.js +29 -8
- package/commands/account.js +7 -2
- package/commands/app/migrate.d.ts +7 -0
- package/commands/app/migrate.js +95 -0
- package/commands/app.d.ts +6 -0
- package/commands/app.js +23 -0
- package/commands/auth.js +6 -2
- package/commands/cms/convertFields.js +5 -6
- package/commands/cms/getReactModule.js +7 -8
- package/commands/cms/lighthouseScore.js +19 -16
- package/commands/config/migrate.d.ts +10 -0
- package/commands/config/migrate.js +84 -0
- package/commands/config/set.d.ts +10 -0
- package/commands/config/set.js +34 -30
- package/commands/config.d.ts +4 -1
- package/commands/config.js +45 -11
- package/commands/create/api-sample.js +8 -7
- package/commands/create/module.js +1 -2
- package/commands/create/template.js +1 -2
- package/commands/customObject/create.js +8 -9
- package/commands/customObject/schema/create.js +5 -6
- package/commands/customObject/schema/delete.js +12 -10
- package/commands/customObject/schema/fetch-all.js +8 -8
- package/commands/customObject/schema/fetch.js +10 -10
- package/commands/customObject/schema/list.js +2 -3
- package/commands/customObject/schema/update.js +7 -8
- package/commands/customObject/schema.js +1 -2
- package/commands/filemanager/fetch.js +5 -6
- package/commands/filemanager/upload.js +12 -13
- package/commands/function/deploy.js +9 -10
- package/commands/function/list.js +4 -5
- package/commands/function/server.js +7 -8
- package/commands/init.js +9 -10
- package/commands/project/cloneApp.d.ts +9 -1
- package/commands/project/cloneApp.js +91 -76
- package/commands/project/create.js +1 -0
- package/commands/project/migrateApp.d.ts +9 -1
- package/commands/project/migrateApp.js +43 -170
- package/commands/project/watch.js +12 -0
- package/lang/en.js +11 -3
- package/lang/en.lyaml +125 -10
- package/lib/DevServerManagerV2.d.ts +1 -2
- package/lib/DevServerManagerV2.js +1 -2
- package/lib/LocalDevManagerV2.js +10 -15
- package/lib/app/migrate.d.ts +5 -0
- package/lib/app/migrate.js +242 -0
- package/lib/app/migrate_legacy.d.ts +4 -0
- package/lib/app/migrate_legacy.js +129 -0
- package/lib/configMigrate.d.ts +2 -0
- package/lib/configMigrate.js +104 -0
- package/lib/dependencyManagement.d.ts +5 -0
- package/lib/dependencyManagement.js +47 -22
- package/lib/doctor/Diagnosis.d.ts +1 -2
- package/lib/doctor/Diagnosis.js +10 -6
- package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -0
- package/lib/doctor/DiagnosticInfoBuilder.js +1 -0
- package/lib/doctor/Doctor.d.ts +1 -0
- package/lib/doctor/Doctor.js +19 -2
- package/lib/middleware/__test__/configMiddleware.test.d.ts +1 -0
- package/lib/middleware/__test__/configMiddleware.test.js +194 -0
- package/lib/middleware/__test__/gitMiddleware.test.d.ts +1 -0
- package/lib/middleware/__test__/gitMiddleware.test.js +76 -0
- package/lib/middleware/__test__/notificationsMiddleware.test.d.ts +1 -0
- package/lib/middleware/__test__/notificationsMiddleware.test.js +10 -0
- package/lib/middleware/__test__/requestMiddleware.test.d.ts +1 -0
- package/lib/middleware/__test__/requestMiddleware.test.js +20 -0
- package/lib/middleware/__test__/utils.test.d.ts +1 -0
- package/lib/middleware/__test__/utils.test.js +53 -0
- package/lib/middleware/__test__/yargsChecksMiddleware.test.d.ts +1 -0
- package/lib/middleware/__test__/yargsChecksMiddleware.test.js +81 -0
- package/lib/middleware/configMiddleware.d.ts +13 -0
- package/lib/middleware/configMiddleware.js +109 -0
- package/lib/middleware/fireAlarmMiddleware.d.ts +4 -0
- package/lib/middleware/fireAlarmMiddleware.js +137 -0
- package/lib/middleware/gitMiddleware.d.ts +2 -0
- package/lib/middleware/gitMiddleware.js +14 -0
- package/lib/middleware/notificationsMiddleware.d.ts +1 -0
- package/lib/middleware/notificationsMiddleware.js +38 -0
- package/lib/middleware/requestMiddleware.d.ts +1 -0
- package/lib/middleware/requestMiddleware.js +11 -0
- package/lib/middleware/utils.d.ts +8 -0
- package/lib/middleware/utils.js +17 -0
- package/lib/middleware/yargsChecksMiddleware.d.ts +4 -0
- package/lib/middleware/yargsChecksMiddleware.js +24 -0
- package/lib/polling.d.ts +4 -0
- package/lib/polling.js +3 -3
- package/lib/projects/structure.d.ts +1 -2
- package/lib/projects/structure.js +0 -4
- package/lib/prompts/promptUtils.d.ts +6 -4
- package/lib/prompts/promptUtils.js +3 -1
- package/lib/ui/SpinniesManager.d.ts +1 -1
- package/lib/ui/index.d.ts +3 -2
- package/lib/ui/index.js +11 -5
- package/lib/ui/spinniesUtils.d.ts +5 -5
- package/package.json +8 -7
- package/types/ProjectComponents.d.ts +0 -15
- package/types/Prompts.d.ts +2 -2
- package/types/Yargs.d.ts +10 -0
- package/lib/npm.d.ts +0 -9
- package/lib/npm.js +0 -36
package/lib/LocalDevManagerV2.js
CHANGED
|
@@ -10,6 +10,7 @@ const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
|
10
10
|
const localDevAuth_1 = require("@hubspot/local-dev-lib/api/localDevAuth");
|
|
11
11
|
const appsDev_1 = require("@hubspot/local-dev-lib/api/appsDev");
|
|
12
12
|
const config_1 = require("@hubspot/local-dev-lib/config");
|
|
13
|
+
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
13
14
|
const constants_1 = require("./constants");
|
|
14
15
|
const SpinniesManager_1 = __importDefault(require("./ui/SpinniesManager"));
|
|
15
16
|
const DevServerManagerV2_1 = __importDefault(require("./DevServerManagerV2"));
|
|
@@ -212,16 +213,13 @@ class LocalDevManagerV2 {
|
|
|
212
213
|
: (0, ui_1.uiCommandReference)('hs project upload');
|
|
213
214
|
}
|
|
214
215
|
logUploadWarning(reason) {
|
|
215
|
-
let warning;
|
|
216
|
-
if (
|
|
217
|
-
warning = reason;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
216
|
+
let warning = reason;
|
|
217
|
+
if (!warning) {
|
|
220
218
|
warning =
|
|
221
219
|
this.publicAppActiveInstalls && this.publicAppActiveInstalls > 0
|
|
222
|
-
? (0, lang_1.i18n)(`${i18nKey}.uploadWarning.
|
|
220
|
+
? (0, lang_1.i18n)(`${i18nKey}.uploadWarning.defaultMarketplaceAppWarning`, {
|
|
223
221
|
installCount: this.publicAppActiveInstalls,
|
|
224
|
-
|
|
222
|
+
accountText: this.publicAppActiveInstalls === 1 ? 'account' : 'accounts',
|
|
225
223
|
})
|
|
226
224
|
: (0, lang_1.i18n)(`${i18nKey}.uploadWarning.defaultWarning`);
|
|
227
225
|
}
|
|
@@ -268,10 +266,10 @@ class LocalDevManagerV2 {
|
|
|
268
266
|
const deployedComponentNames = this.deployedBuild.subbuildStatuses.map(subbuildStatus => subbuildStatus.buildName);
|
|
269
267
|
const missingProjectNodes = [];
|
|
270
268
|
Object.values(this.projectNodes).forEach(node => {
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
269
|
+
if (!deployedComponentNames.includes(node.uid)) {
|
|
270
|
+
const userFriendlyName = (0, project_parsing_lib_1.mapToUserFriendlyName)(node.componentType);
|
|
271
|
+
const label = userFriendlyName ? `[${userFriendlyName}] ` : '';
|
|
272
|
+
missingProjectNodes.push(`${label}${node.uid}`);
|
|
275
273
|
}
|
|
276
274
|
});
|
|
277
275
|
if (missingProjectNodes.length) {
|
|
@@ -284,9 +282,7 @@ class LocalDevManagerV2 {
|
|
|
284
282
|
this.watcher = chokidar_1.default.watch(this.projectDir, {
|
|
285
283
|
ignoreInitial: true,
|
|
286
284
|
});
|
|
287
|
-
const configPaths = Object.values(this.projectNodes)
|
|
288
|
-
.filter(structure_1.isAppIRNode)
|
|
289
|
-
.map(component => component.localDev.componentConfigPath);
|
|
285
|
+
const configPaths = Object.values(this.projectNodes).map(component => component.localDev.componentConfigPath);
|
|
290
286
|
const projectConfigPath = path_1.default.join(this.projectDir, constants_1.PROJECT_CONFIG_FILE);
|
|
291
287
|
configPaths.push(projectConfigPath);
|
|
292
288
|
this.watcher.on('add', filePath => {
|
|
@@ -317,7 +313,6 @@ class LocalDevManagerV2 {
|
|
|
317
313
|
try {
|
|
318
314
|
await DevServerManagerV2_1.default.setup({
|
|
319
315
|
projectNodes: this.projectNodes,
|
|
320
|
-
onUploadRequired: this.logUploadWarning.bind(this),
|
|
321
316
|
accountId: this.targetTestingAccountId,
|
|
322
317
|
setActiveApp: this.setActiveApp.bind(this),
|
|
323
318
|
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ArgumentsCamelCase } from 'yargs';
|
|
2
|
+
import { MigrateAppOptions } from '../../types/Yargs';
|
|
3
|
+
export declare function downloadProjectFiles(derivedAccountId: number, projectName: string, buildId: number, projectDest: string): Promise<void>;
|
|
4
|
+
export declare function migrateApp2025_2(derivedAccountId: number, options: ArgumentsCamelCase<MigrateAppOptions>): Promise<void>;
|
|
5
|
+
export declare function logInvalidAccountError(i18nKey: string): void;
|
|
@@ -0,0 +1,242 @@
|
|
|
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.downloadProjectFiles = downloadProjectFiles;
|
|
7
|
+
exports.migrateApp2025_2 = migrateApp2025_2;
|
|
8
|
+
exports.logInvalidAccountError = logInvalidAccountError;
|
|
9
|
+
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const path_2 = require("@hubspot/local-dev-lib/path");
|
|
12
|
+
const archive_1 = require("@hubspot/local-dev-lib/archive");
|
|
13
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
+
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
15
|
+
const projects_1 = require("@hubspot/local-dev-lib/constants/projects");
|
|
16
|
+
const transform_1 = require("@hubspot/project-parsing-lib/src/lib/transform");
|
|
17
|
+
const Migration_1 = require("@hubspot/local-dev-lib/types/Migration");
|
|
18
|
+
const projects_2 = require("@hubspot/local-dev-lib/api/projects");
|
|
19
|
+
const promptUtils_1 = require("../prompts/promptUtils");
|
|
20
|
+
const ui_1 = require("../ui");
|
|
21
|
+
const lang_1 = require("../lang");
|
|
22
|
+
const projects_3 = require("../projects");
|
|
23
|
+
const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
|
|
24
|
+
const polling_1 = require("../polling");
|
|
25
|
+
const migrate_1 = require("../../api/migrate");
|
|
26
|
+
function getUnmigratableReason(reasonCode) {
|
|
27
|
+
switch (reasonCode) {
|
|
28
|
+
case projects_1.UNMIGRATABLE_REASONS.UP_TO_DATE:
|
|
29
|
+
return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.upToDate');
|
|
30
|
+
case projects_1.UNMIGRATABLE_REASONS.IS_A_PRIVATE_APP:
|
|
31
|
+
return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.isPrivateApp');
|
|
32
|
+
case projects_1.UNMIGRATABLE_REASONS.LISTED_IN_MARKETPLACE:
|
|
33
|
+
return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.listedInMarketplace');
|
|
34
|
+
default:
|
|
35
|
+
return (0, lang_1.i18n)('commands.project.subcommands.migrateApp.unmigratableReasons.generic', {
|
|
36
|
+
reasonCode,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function handleMigrationSetup(derivedAccountId, options) {
|
|
41
|
+
const { name, dest, appId } = options;
|
|
42
|
+
const { data: { migratableApps, unmigratableApps }, } = await (0, migrate_1.listAppsForMigration)(derivedAccountId);
|
|
43
|
+
const migratableAppsWithoutProject = migratableApps.filter((app) => !app.projectName);
|
|
44
|
+
const unmigratableAppsWithoutProject = unmigratableApps.filter((app) => !app.projectName);
|
|
45
|
+
const allAppsWithoutProject = [
|
|
46
|
+
...migratableAppsWithoutProject,
|
|
47
|
+
...unmigratableAppsWithoutProject,
|
|
48
|
+
];
|
|
49
|
+
if (allAppsWithoutProject.length === 0) {
|
|
50
|
+
const reasons = unmigratableAppsWithoutProject.map(app => `${chalk_1.default.bold(app.appName)}: ${getUnmigratableReason(app.unmigratableReason)}`);
|
|
51
|
+
throw new Error(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.noAppsEligible`, {
|
|
52
|
+
accountId: (0, ui_1.uiAccountDescription)(derivedAccountId),
|
|
53
|
+
})}${reasons.length ? `\n - ${reasons.join('\n - ')}` : ''}`);
|
|
54
|
+
}
|
|
55
|
+
if (appId &&
|
|
56
|
+
!allAppsWithoutProject.some(app => {
|
|
57
|
+
return app.appId === appId;
|
|
58
|
+
})) {
|
|
59
|
+
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.chooseApp', {
|
|
60
|
+
appId,
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
const appChoices = allAppsWithoutProject.map(app => ({
|
|
64
|
+
name: app.isMigratable
|
|
65
|
+
? app.appName
|
|
66
|
+
: `[${chalk_1.default.yellow('DISABLED')}] ${app.appName} `,
|
|
67
|
+
value: app,
|
|
68
|
+
disabled: app.isMigratable
|
|
69
|
+
? false
|
|
70
|
+
: getUnmigratableReason(app.unmigratableReason),
|
|
71
|
+
}));
|
|
72
|
+
let appIdToMigrate = appId;
|
|
73
|
+
if (!appIdToMigrate) {
|
|
74
|
+
const { appId: selectedAppId } = await (0, promptUtils_1.listPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.chooseApp'), {
|
|
75
|
+
choices: appChoices,
|
|
76
|
+
});
|
|
77
|
+
appIdToMigrate = selectedAppId;
|
|
78
|
+
}
|
|
79
|
+
const selectedApp = allAppsWithoutProject.find(app => app.appId === appIdToMigrate);
|
|
80
|
+
const migratableComponents = [];
|
|
81
|
+
const unmigratableComponents = [];
|
|
82
|
+
selectedApp?.migrationComponents.forEach(component => {
|
|
83
|
+
if (component.isSupported) {
|
|
84
|
+
migratableComponents.push((0, transform_1.mapToUserFacingType)(component.componentType));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
unmigratableComponents.push((0, transform_1.mapToUserFacingType)(component.componentType));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (migratableComponents.length !== 0) {
|
|
91
|
+
logger_1.logger.log((0, lang_1.i18n)('commands.project.subcommands.migrateApp.componentsToBeMigrated', {
|
|
92
|
+
components: `\n - ${migratableComponents.join('\n - ')}`,
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
if (unmigratableComponents.length !== 0) {
|
|
96
|
+
logger_1.logger.log((0, lang_1.i18n)('commands.project.subcommands.migrateApp.componentsThatWillNotBeMigrated', {
|
|
97
|
+
components: `\n - ${unmigratableComponents.join('\n - ')}`,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
logger_1.logger.log();
|
|
101
|
+
const proceed = await (0, promptUtils_1.confirmPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.proceed'));
|
|
102
|
+
if (!proceed) {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
const projectName = name ||
|
|
106
|
+
(await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.inputName')));
|
|
107
|
+
const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, projectName, { allowCreate: false, noLogs: true });
|
|
108
|
+
if (projectExists) {
|
|
109
|
+
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.errors.projectAlreadyExists', {
|
|
110
|
+
projectName,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
const projectDest = dest ||
|
|
114
|
+
(await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.inputDest'), {
|
|
115
|
+
defaultAnswer: path_1.default.resolve((0, path_2.getCwd)(), (0, path_2.sanitizeFileName)(projectName)),
|
|
116
|
+
}));
|
|
117
|
+
return { appIdToMigrate, projectName, projectDest };
|
|
118
|
+
}
|
|
119
|
+
async function beginMigration(derivedAccountId, appId, platformVersion) {
|
|
120
|
+
SpinniesManager_1.default.add('beginningMigration', {
|
|
121
|
+
text: (0, lang_1.i18n)('commands.project.subcommands.migrateApp.spinners.beginningMigration'),
|
|
122
|
+
});
|
|
123
|
+
const uidMap = {};
|
|
124
|
+
const { data } = await (0, migrate_1.initializeMigration)(derivedAccountId, appId, platformVersion);
|
|
125
|
+
const { migrationId } = data;
|
|
126
|
+
const pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, [Migration_1.MIGRATION_STATUS.INPUT_REQUIRED]);
|
|
127
|
+
if (pollResponse.status !== Migration_1.MIGRATION_STATUS.INPUT_REQUIRED) {
|
|
128
|
+
SpinniesManager_1.default.fail('beginningMigration', {
|
|
129
|
+
text: (0, lang_1.i18n)('commands.project.subcommands.migrateApp.spinners.unableToStartMigration'),
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const { componentsRequiringUids } = pollResponse;
|
|
134
|
+
SpinniesManager_1.default.remove('beginningMigration');
|
|
135
|
+
if (Object.values(componentsRequiringUids).length !== 0) {
|
|
136
|
+
for (const [componentId, component] of Object.entries(componentsRequiringUids)) {
|
|
137
|
+
const { componentHint, componentType } = component;
|
|
138
|
+
uidMap[componentId] = await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.uidForComponent', {
|
|
139
|
+
componentName: componentHint
|
|
140
|
+
? `${componentHint} [${(0, transform_1.mapToUserFacingType)(componentType)}]`
|
|
141
|
+
: (0, transform_1.mapToUserFacingType)(componentType),
|
|
142
|
+
}), {
|
|
143
|
+
validate: (uid) => {
|
|
144
|
+
const result = (0, project_parsing_lib_1.validateUid)(uid);
|
|
145
|
+
return result === undefined ? true : result;
|
|
146
|
+
},
|
|
147
|
+
defaultAnswer: (componentHint || '')
|
|
148
|
+
.toLowerCase()
|
|
149
|
+
.replace(/[^a-z0-9_]/g, ''),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { migrationId, uidMap };
|
|
154
|
+
}
|
|
155
|
+
async function pollMigrationStatus(derivedAccountId, migrationId, successStates = []) {
|
|
156
|
+
return (0, polling_1.poll)(() => (0, migrate_1.checkMigrationStatusV2)(derivedAccountId, migrationId), {
|
|
157
|
+
successStates: [...successStates],
|
|
158
|
+
errorStates: [...polling_1.DEFAULT_POLLING_STATUS_LOOKUP.errorStates],
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async function finalizeMigration(derivedAccountId, migrationId, uidMap, projectName) {
|
|
162
|
+
let pollResponse;
|
|
163
|
+
try {
|
|
164
|
+
SpinniesManager_1.default.add('finishingMigration', {
|
|
165
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.finishingMigration`),
|
|
166
|
+
});
|
|
167
|
+
await (0, migrate_1.continueMigration)(derivedAccountId, migrationId, uidMap, projectName);
|
|
168
|
+
pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, [
|
|
169
|
+
Migration_1.MIGRATION_STATUS.SUCCESS,
|
|
170
|
+
]);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
SpinniesManager_1.default.fail('finishingMigration', {
|
|
174
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationFailed`),
|
|
175
|
+
});
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
if (pollResponse.status === Migration_1.MIGRATION_STATUS.SUCCESS) {
|
|
179
|
+
SpinniesManager_1.default.succeed('finishingMigration', {
|
|
180
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationComplete`),
|
|
181
|
+
});
|
|
182
|
+
return pollResponse.buildId;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
SpinniesManager_1.default.fail('finishingMigration', {
|
|
186
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationFailed`),
|
|
187
|
+
});
|
|
188
|
+
if (pollResponse.status === Migration_1.MIGRATION_STATUS.FAILURE) {
|
|
189
|
+
logger_1.logger.error(pollResponse.componentErrorDetails);
|
|
190
|
+
throw new Error(pollResponse.projectErrorsDetail);
|
|
191
|
+
}
|
|
192
|
+
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.errors.migrationFailed'));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest) {
|
|
196
|
+
try {
|
|
197
|
+
SpinniesManager_1.default.add('fetchingMigratedProject', {
|
|
198
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContents`),
|
|
199
|
+
});
|
|
200
|
+
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)();
|
|
204
|
+
await (0, archive_1.extractZipArchive)(zippedProject, (0, path_2.sanitizeFileName)(projectName), absoluteDestPath, {
|
|
205
|
+
includesRootDir: true,
|
|
206
|
+
hideLogs: true,
|
|
207
|
+
});
|
|
208
|
+
SpinniesManager_1.default.succeed('fetchingMigratedProject', {
|
|
209
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContentsComplete`),
|
|
210
|
+
});
|
|
211
|
+
logger_1.logger.success(`Saved ${projectName} to ${projectDest}`);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
SpinniesManager_1.default.fail('fetchingMigratedProject', {
|
|
215
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContentsFailed`),
|
|
216
|
+
});
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function migrateApp2025_2(derivedAccountId, options) {
|
|
221
|
+
SpinniesManager_1.default.init();
|
|
222
|
+
const { appIdToMigrate, projectName, projectDest } = await handleMigrationSetup(derivedAccountId, options);
|
|
223
|
+
if (!appIdToMigrate || !projectName || !projectDest) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const migrationInProgress = await beginMigration(derivedAccountId, appIdToMigrate, options.platformVersion);
|
|
227
|
+
if (!migrationInProgress) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const { migrationId, uidMap } = migrationInProgress;
|
|
231
|
+
const buildId = await finalizeMigration(derivedAccountId, migrationId, uidMap, projectName);
|
|
232
|
+
await downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest);
|
|
233
|
+
}
|
|
234
|
+
function logInvalidAccountError(i18nKey) {
|
|
235
|
+
(0, ui_1.uiLine)();
|
|
236
|
+
logger_1.logger.error((0, lang_1.i18n)(`${i18nKey}.errors.invalidAccountTypeTitle`));
|
|
237
|
+
logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.errors.invalidAccountTypeDescription`, {
|
|
238
|
+
useCommand: (0, ui_1.uiCommandReference)('hs accounts use'),
|
|
239
|
+
authCommand: (0, ui_1.uiCommandReference)('hs auth'),
|
|
240
|
+
}));
|
|
241
|
+
(0, ui_1.uiLine)();
|
|
242
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CLIAccount } from '@hubspot/local-dev-lib/types/Accounts';
|
|
2
|
+
import { ArgumentsCamelCase } from 'yargs';
|
|
3
|
+
import { MigrateAppOptions } from '../../types/Yargs';
|
|
4
|
+
export declare function migrateApp2023_2(derivedAccountId: number, options: ArgumentsCamelCase<MigrateAppOptions>, accountConfig: CLIAccount): Promise<void>;
|
|
@@ -0,0 +1,129 @@
|
|
|
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)('commands.project.subcommands.migrateApp');
|
|
32
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
33
|
+
}
|
|
34
|
+
const { appId } = 'appId' in options
|
|
35
|
+
? options
|
|
36
|
+
: await (0, selectPublicAppPrompt_1.selectPublicAppPrompt)({
|
|
37
|
+
accountId: derivedAccountId,
|
|
38
|
+
accountName,
|
|
39
|
+
isMigratingApp: true,
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
const { data: selectedApp } = await (0, appsDev_1.fetchPublicAppMetadata)(appId, derivedAccountId);
|
|
43
|
+
// preventProjectMigrations returns true if we have not added app to allowlist config.
|
|
44
|
+
// listingInfo will only exist for marketplace apps
|
|
45
|
+
const preventProjectMigrations = selectedApp.preventProjectMigrations;
|
|
46
|
+
const listingInfo = selectedApp.listingInfo;
|
|
47
|
+
if (preventProjectMigrations && listingInfo) {
|
|
48
|
+
logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.invalidApp`, {
|
|
49
|
+
appId,
|
|
50
|
+
}));
|
|
51
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
(0, errorHandlers_1.logError)(error, new errorHandlers_1.ApiErrorContext({ accountId: derivedAccountId }));
|
|
56
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
57
|
+
}
|
|
58
|
+
const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(options);
|
|
59
|
+
const { name: projectName, dest: projectDest } = createProjectPromptResponse;
|
|
60
|
+
const { projectExists } = await (0, projects_2.ensureProjectExists)(derivedAccountId, projectName, {
|
|
61
|
+
allowCreate: false,
|
|
62
|
+
noLogs: true,
|
|
63
|
+
});
|
|
64
|
+
if (projectExists) {
|
|
65
|
+
throw new Error((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.projectAlreadyExists`, {
|
|
66
|
+
projectName,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
await (0, usageTracking_1.trackCommandMetadataUsage)('migrate-app', { step: 'STARTED' }, derivedAccountId);
|
|
70
|
+
logger_1.logger.log('');
|
|
71
|
+
(0, ui_1.uiLine)();
|
|
72
|
+
logger_1.logger.warn(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.title`)}\n`);
|
|
73
|
+
logger_1.logger.log((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.projectConversion`));
|
|
74
|
+
logger_1.logger.log(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.appConfig`)}\n`);
|
|
75
|
+
logger_1.logger.log(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.buildAndDeploy`)}\n`);
|
|
76
|
+
logger_1.logger.log(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.existingApps`)}\n`);
|
|
77
|
+
logger_1.logger.log((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.warning.copyApp`));
|
|
78
|
+
(0, ui_1.uiLine)();
|
|
79
|
+
const { shouldCreateApp } = await (0, promptUtils_1.promptUser)({
|
|
80
|
+
name: 'shouldCreateApp',
|
|
81
|
+
type: 'confirm',
|
|
82
|
+
message: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.createAppPrompt`),
|
|
83
|
+
});
|
|
84
|
+
process.stdin.resume();
|
|
85
|
+
if (!shouldCreateApp) {
|
|
86
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
SpinniesManager_1.default.init();
|
|
90
|
+
SpinniesManager_1.default.add('migrateApp', {
|
|
91
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.migrationStatus.inProgress`),
|
|
92
|
+
});
|
|
93
|
+
(0, process_1.handleKeypress)(async (key) => {
|
|
94
|
+
if ((key.ctrl && key.name === 'c') || key.name === 'q') {
|
|
95
|
+
SpinniesManager_1.default.remove('migrateApp');
|
|
96
|
+
logger_1.logger.log((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.migrationInterrupted`));
|
|
97
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const { data: migrateResponse } = await (0, projects_1.migrateApp)(derivedAccountId, appId, projectName);
|
|
101
|
+
const { id } = migrateResponse;
|
|
102
|
+
const pollResponse = await (0, polling_1.poll)(() => (0, projects_1.checkMigrationStatus)(derivedAccountId, id));
|
|
103
|
+
const { status, project } = pollResponse;
|
|
104
|
+
if (status === 'SUCCESS') {
|
|
105
|
+
const absoluteDestPath = path_1.default.resolve((0, path_2.getCwd)(), projectDest);
|
|
106
|
+
const { env } = accountConfig;
|
|
107
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)(env);
|
|
108
|
+
const { data: zippedProject } = await (0, projects_1.downloadProject)(derivedAccountId, projectName, 1);
|
|
109
|
+
await (0, archive_1.extractZipArchive)(zippedProject, (0, path_2.sanitizeFileName)(projectName), path_1.default.resolve(absoluteDestPath), { includesRootDir: true, hideLogs: true });
|
|
110
|
+
SpinniesManager_1.default.succeed('migrateApp', {
|
|
111
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.migrationStatus.done`),
|
|
112
|
+
succeedColor: 'white',
|
|
113
|
+
});
|
|
114
|
+
logger_1.logger.log('');
|
|
115
|
+
(0, ui_1.uiLine)();
|
|
116
|
+
logger_1.logger.success((0, lang_1.i18n)(`commands.project.subcommands.migrateApp.migrationStatus.success`));
|
|
117
|
+
logger_1.logger.log('');
|
|
118
|
+
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)}`));
|
|
119
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
SpinniesManager_1.default.fail('migrateApp', {
|
|
124
|
+
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.migrationStatus.failure`),
|
|
125
|
+
failColor: 'white',
|
|
126
|
+
});
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleMigration = handleMigration;
|
|
4
|
+
exports.handleMerge = handleMerge;
|
|
5
|
+
const migrate_1 = require("@hubspot/local-dev-lib/config/migrate");
|
|
6
|
+
const config_1 = require("@hubspot/local-dev-lib/constants/config");
|
|
7
|
+
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
8
|
+
const promptUtils_1 = require("./prompts/promptUtils");
|
|
9
|
+
const lang_1 = require("./lang");
|
|
10
|
+
const usageTracking_1 = require("./usageTracking");
|
|
11
|
+
async function handleMigration(accountId, configPath) {
|
|
12
|
+
const { shouldMigrateConfig } = await (0, promptUtils_1.promptUser)({
|
|
13
|
+
name: 'shouldMigrateConfig',
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
message: (0, lang_1.i18n)('lib.configMigrate.migrateConfigPrompt', {
|
|
16
|
+
deprecatedConfigPath: (0, migrate_1.getConfigPath)(configPath, false) ||
|
|
17
|
+
config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
18
|
+
globalConfigPath: config_1.GLOBAL_CONFIG_PATH,
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
if (!shouldMigrateConfig) {
|
|
22
|
+
(0, usageTracking_1.trackCommandMetadataUsage)('config-migrate', {
|
|
23
|
+
command: 'hs config migrate',
|
|
24
|
+
type: 'migration',
|
|
25
|
+
step: 'Reject migration via prompt',
|
|
26
|
+
}, accountId);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const deprecatedConfig = (0, migrate_1.getDeprecatedConfig)(configPath);
|
|
30
|
+
(0, migrate_1.migrateConfig)(deprecatedConfig);
|
|
31
|
+
(0, usageTracking_1.trackCommandMetadataUsage)('config-migrate', {
|
|
32
|
+
command: 'hs config migrate',
|
|
33
|
+
type: 'migration',
|
|
34
|
+
step: 'Confirm migration via prompt',
|
|
35
|
+
successful: true,
|
|
36
|
+
}, accountId);
|
|
37
|
+
logger_1.logger.success((0, lang_1.i18n)('lib.configMigrate.migrationSuccess', {
|
|
38
|
+
globalConfigPath: config_1.GLOBAL_CONFIG_PATH,
|
|
39
|
+
}));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
async function mergeConfigProperties(globalConfig, deprecatedConfig, force) {
|
|
43
|
+
const { initialConfig, conflicts, } = (0, migrate_1.mergeConfigProperties)(globalConfig, deprecatedConfig, force);
|
|
44
|
+
if (conflicts.length > 0) {
|
|
45
|
+
for (const conflict of conflicts) {
|
|
46
|
+
const { property, newValue, oldValue } = conflict;
|
|
47
|
+
const { shouldOverwrite } = await (0, promptUtils_1.promptUser)({
|
|
48
|
+
name: 'shouldOverwrite',
|
|
49
|
+
type: 'confirm',
|
|
50
|
+
message: (0, lang_1.i18n)('lib.configMigrate.mergeConfigConflictPrompt', {
|
|
51
|
+
property,
|
|
52
|
+
oldValue: `${oldValue}`,
|
|
53
|
+
newValue: `${newValue}`,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
if (shouldOverwrite) {
|
|
57
|
+
// @ts-expect-error Cannot reconcile CLIConfig_NEW and CLIConfig_DEPRECATED
|
|
58
|
+
initialConfig[property] = oldValue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return initialConfig;
|
|
63
|
+
}
|
|
64
|
+
async function handleMerge(accountId, configPath, force) {
|
|
65
|
+
const { shouldMergeConfigs } = await (0, promptUtils_1.promptUser)({
|
|
66
|
+
name: 'shouldMergeConfigs',
|
|
67
|
+
type: 'confirm',
|
|
68
|
+
message: (0, lang_1.i18n)('lib.configMigrate.mergeConfigsPrompt', {
|
|
69
|
+
deprecatedConfigPath: (0, migrate_1.getConfigPath)(configPath, false) ||
|
|
70
|
+
config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
71
|
+
globalConfigPath: config_1.GLOBAL_CONFIG_PATH,
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
if (!shouldMergeConfigs) {
|
|
75
|
+
(0, usageTracking_1.trackCommandMetadataUsage)('config-migrate', {
|
|
76
|
+
command: 'hs config migrate',
|
|
77
|
+
type: 'merge',
|
|
78
|
+
step: 'Reject merge via prompt',
|
|
79
|
+
}, accountId);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const deprecatedConfig = (0, migrate_1.getDeprecatedConfig)(configPath);
|
|
83
|
+
const globalConfig = (0, migrate_1.getGlobalConfig)();
|
|
84
|
+
if (!deprecatedConfig || !globalConfig) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const mergedConfig = await mergeConfigProperties(globalConfig, deprecatedConfig, force);
|
|
88
|
+
const { skippedAccountIds } = (0, migrate_1.mergeExistingConfigs)(mergedConfig, deprecatedConfig);
|
|
89
|
+
if (skippedAccountIds.length > 0) {
|
|
90
|
+
logger_1.logger.log((0, lang_1.i18n)('lib.configMigrate.skippedExistingAccounts', {
|
|
91
|
+
skippedAccountIds: skippedAccountIds.join(', '),
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
logger_1.logger.success((0, lang_1.i18n)('lib.configMigrate.mergeSuccess', {
|
|
95
|
+
globalConfigPath: config_1.GLOBAL_CONFIG_PATH,
|
|
96
|
+
}));
|
|
97
|
+
(0, usageTracking_1.trackCommandMetadataUsage)('config-migrate', {
|
|
98
|
+
command: 'hs config migrate',
|
|
99
|
+
type: 'merge',
|
|
100
|
+
step: 'Confirm merge via prompt',
|
|
101
|
+
successful: true,
|
|
102
|
+
}, accountId);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export declare function isGloballyInstalled(command: string): Promise<boolean>;
|
|
2
|
+
export declare function getLatestCliVersion(): Promise<{
|
|
3
|
+
latest: string;
|
|
4
|
+
next: string;
|
|
5
|
+
}>;
|
|
1
6
|
export declare function installPackages({ packages, installLocations, }: {
|
|
2
7
|
packages?: string[];
|
|
3
8
|
installLocations?: string[];
|