@hubspot/cli 7.5.3-experimental.0 → 7.5.4-experimental.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/migrate.d.ts +1 -2
- package/api/migrate.js +0 -7
- package/bin/cli.js +2 -0
- package/commands/account/auth.d.ts +10 -0
- package/commands/account/auth.js +168 -0
- package/commands/account/clean.js +38 -5
- package/commands/account/createOverride.d.ts +10 -0
- package/commands/account/createOverride.js +104 -0
- package/commands/account/info.js +23 -0
- package/commands/account/list.js +23 -7
- package/commands/account/remove.js +28 -0
- package/commands/account/removeOverride.d.ts +10 -0
- package/commands/account/removeOverride.js +76 -0
- package/commands/account/use.js +13 -0
- package/commands/account.js +7 -2
- package/commands/auth.js +6 -2
- 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 +29 -29
- package/commands/config.d.ts +4 -1
- package/commands/config.js +45 -11
- package/commands/init.js +9 -10
- package/commands/project.js +0 -2
- package/lang/en.js +5 -0
- package/lang/en.lyaml +89 -16
- package/lib/app/migrate.d.ts +2 -2
- package/lib/app/migrate.js +35 -77
- package/lib/app/migrate_legacy.js +3 -5
- package/lib/configMigrate.d.ts +2 -0
- package/lib/configMigrate.js +104 -0
- 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 +18 -0
- package/lib/middleware/configMiddleware.js +5 -1
- package/lib/middleware/fireAlarmMiddleware.d.ts +4 -0
- package/lib/middleware/fireAlarmMiddleware.js +137 -0
- package/lib/projects/index.d.ts +2 -3
- package/lib/ui/index.d.ts +1 -0
- package/lib/ui/index.js +5 -0
- package/package.json +5 -4
- package/types/Yargs.d.ts +3 -6
- package/commands/project/migrate.d.ts +0 -8
- package/commands/project/migrate.js +0 -48
package/lang/en.lyaml
CHANGED
|
@@ -10,6 +10,9 @@ en:
|
|
|
10
10
|
portalEnvVarDeprecated: "The HUBSPOT_PORTAL_ID environment variable is deprecated. Please use HUBSPOT_ACCOUNT_ID instead."
|
|
11
11
|
loadConfigMiddleware:
|
|
12
12
|
configFileExists: "A configuration file already exists at {{ configPath }}. To specify a new configuration file, delete the existing one and try again."
|
|
13
|
+
injectAccountIdMiddleware:
|
|
14
|
+
invalidAccountId: "In the default override file ({{ hsAccountFileName }}), the account ID must be a number. Please delete the current file and generate a new one using {{ overrideCommand }}."
|
|
15
|
+
accountNotFound: "The account in the default override file ({{ hsAccountFileName }}) wasn't found in your configured accounts. You can authorize this account using {{ authCommand }}."
|
|
13
16
|
completion:
|
|
14
17
|
describe: "Enable bash completion shortcuts for commands. Concat the generated script to your .bashrc, .bash_profile, or .zshrc file."
|
|
15
18
|
examples:
|
|
@@ -17,11 +20,51 @@ en:
|
|
|
17
20
|
account:
|
|
18
21
|
describe: "Commands for managing configured accounts."
|
|
19
22
|
subcommands:
|
|
23
|
+
auth:
|
|
24
|
+
describe: "Configure authentication for your HubSpot account."
|
|
25
|
+
options:
|
|
26
|
+
account:
|
|
27
|
+
describe: "HubSpot account to authenticate"
|
|
28
|
+
errors:
|
|
29
|
+
failedToUpdateConfig: "Failed to update the configuration file. Please try again."
|
|
30
|
+
bothConfigFilesNotAllowed: "Unable to create config file, because there is an existing \"{{ deprecatedConfig }}\" file. To create a new config file, delete the existing one and try again."
|
|
31
|
+
success:
|
|
32
|
+
configFileCreated: "Created config file \"{{ configPath }}\""
|
|
33
|
+
configFileUpdated: "Connected account \"{{ account }}\" and set it as the default account"
|
|
34
|
+
createOverride:
|
|
35
|
+
describe: "Create a new default account override file ({{ hsAccountFileName }}) in the current working directory."
|
|
36
|
+
success: "Default account override file created at {{ overrideFilePath }}"
|
|
37
|
+
accountOverride: "An account override file already exists at {{ overrideFilePath }} associated with account \"{{ accountOverride }}\"."
|
|
38
|
+
prompts:
|
|
39
|
+
replaceOverrideFile: "Replace existing account override file?"
|
|
40
|
+
errors:
|
|
41
|
+
accountNotFound: "The specified account could not be found in the config file {{ configPath }}"
|
|
42
|
+
options:
|
|
43
|
+
account:
|
|
44
|
+
describe: "Name or ID of the account to create an override file for."
|
|
45
|
+
examples:
|
|
46
|
+
default: "Create a new default account override file ({{ hsAccountFileName }}) in the current working directory"
|
|
47
|
+
idBased: "Create a new default account override file ({{ hsAccountFileName }}) in the current working directory, using the account with accountId \"1234567\""
|
|
48
|
+
nameBased: "Create a new default account override file ({{ hsAccountFileName }}) in the current working directory, using the account with name \"MyAccount\""
|
|
49
|
+
removeOverride:
|
|
50
|
+
describe: "Remove the default account override file ({{ overrideFile }}) from the current working directory."
|
|
51
|
+
accountOverride: "There is an account override file at {{ overrideFilePath }} associated with account \"{{ accountOverride }}\"."
|
|
52
|
+
prompts:
|
|
53
|
+
deleteOverrideFile: "Delete account override file?"
|
|
54
|
+
success: "Removed the default account override file."
|
|
55
|
+
noOverrideFile: "No default account override file found in the current working directory. No action required."
|
|
56
|
+
options:
|
|
57
|
+
force:
|
|
58
|
+
describe: "Skip confirmation prompt when removing the override file"
|
|
20
59
|
list:
|
|
21
|
-
accounts: "{{#bold}}Accounts{{/bold}}:"
|
|
22
|
-
defaultAccount: "{{#bold}}Default account{{/bold}}: {{ account }}"
|
|
23
60
|
describe: "List names of accounts defined in config."
|
|
24
|
-
|
|
61
|
+
accounts: "{{#bold}}Accounts{{/bold}}:"
|
|
62
|
+
defaultAccountTitle: "{{#bold}}Default Account{{/bold}}"
|
|
63
|
+
defaultAccount: "Account: {{ account }}"
|
|
64
|
+
configPath: "Source: {{ configPath }}"
|
|
65
|
+
overrideFilePathTitle: "{{#bold}}Default Account Override{{/bold}}"
|
|
66
|
+
overrideFilePath: "Source: {{ overrideFilePath }}"
|
|
67
|
+
overrideAccount: "Account: {{ account }}"
|
|
25
68
|
labels:
|
|
26
69
|
accountId: "Account ID"
|
|
27
70
|
authType: "Auth Type"
|
|
@@ -39,6 +82,8 @@ en:
|
|
|
39
82
|
describe: "Set the Hubspot account to use as the default account. The default account can be overridden with the \"--account\" option."
|
|
40
83
|
errors:
|
|
41
84
|
accountNotFound: "The account \"{{ specifiedAccount }}\" could not be found in {{ configPath }}"
|
|
85
|
+
accountOverride: "This project currently has an account override set: \"{{ accountOverride }}\". Account \"{{accountOverride}}\" will continue to act as the default account for this project."
|
|
86
|
+
accountOverrideCommands: "Use {{ createOverrideCommand }} to change override accounts, or {{ removeOverrideCommand }} to remove the override and use your default account."
|
|
42
87
|
examples:
|
|
43
88
|
default: "Select a HubSpot account to use as the default account"
|
|
44
89
|
idBased: "Set the default account to the account in the config with accountId equal to \"1234567\""
|
|
@@ -54,6 +99,7 @@ en:
|
|
|
54
99
|
logs:
|
|
55
100
|
replaceDefaultAccount: "The removed account was the default account."
|
|
56
101
|
prompts:
|
|
102
|
+
deleteOverrideFile: "Delete the override file ({{ overrideFilePath }}) associated with {{ accountName }}?"
|
|
57
103
|
selectAccountToRemove: "Select an account to remove from the config"
|
|
58
104
|
errors:
|
|
59
105
|
accountNotFound: "The account \"{{ specifiedAccount }}\" could not be found in {{ configPath }}"
|
|
@@ -69,6 +115,12 @@ en:
|
|
|
69
115
|
info:
|
|
70
116
|
accountId: "{{#bold}}Account ID{{/bold}}: {{ accountId }}"
|
|
71
117
|
describe: "Print information about the default account, or about the account specified with the \"account\" option."
|
|
118
|
+
defaultAccountTitle: "{{#bold}}Default Account{{/bold}}"
|
|
119
|
+
defaultAccount: "Account: {{ account }}"
|
|
120
|
+
configPath: "Source: {{ configPath }}"
|
|
121
|
+
overrideFilePathTitle: "{{#bold}}Default Account Override{{/bold}}"
|
|
122
|
+
overrideFilePath: "Source: {{ overrideFilePath }}"
|
|
123
|
+
overrideAccount: "Account: {{ account }}"
|
|
72
124
|
errors:
|
|
73
125
|
notUsingPersonalAccessKey: "This command currently only supports fetching scopes for the personal access key auth type."
|
|
74
126
|
options:
|
|
@@ -91,13 +143,15 @@ en:
|
|
|
91
143
|
confirm:
|
|
92
144
|
one: "Remove 1 inactive account from the CLI config?"
|
|
93
145
|
other: "Remove {{ count }} inactive accounts from the CLI config?"
|
|
146
|
+
defaultAccountOverride: "\n(This will also delete the default account override file at {{ overrideFilePath }})"
|
|
147
|
+
replaceDefaultAccount: "The default account was removed."
|
|
94
148
|
removeSuccess: "Removed {{ accountName }} from the CLI config."
|
|
95
149
|
auth:
|
|
96
150
|
describe: "Configure authentication for your HubSpot account."
|
|
97
151
|
verboseDescribe: "Configure authentication for a HubSpot account. This will update the {{ configName }} file that stores your account information.\n\nThe recommended authentication method is {{#bold}}{{ authMethod }}{{/bold}}, which uses an access token tied to a specific user account."
|
|
98
152
|
errors:
|
|
99
|
-
noConfigFileFound: "No config file was found. To create a new config file, use the \"hs init\" command."
|
|
100
153
|
unsupportedAuthType: "Unsupported auth type: {{ type }}. The only supported authentication protocols are {{ supportedProtocols }}."
|
|
154
|
+
globalConfigFileExists: "A global config file exists at {{ configPath }}. To authorize an account, please use {{ authCommand }}."
|
|
101
155
|
options:
|
|
102
156
|
authType:
|
|
103
157
|
describe: "Authentication method"
|
|
@@ -108,6 +162,16 @@ en:
|
|
|
108
162
|
config:
|
|
109
163
|
describe: "Commands for managing the CLI config file."
|
|
110
164
|
subcommands:
|
|
165
|
+
migrate:
|
|
166
|
+
describe: "Migrate from the deprecated {{ deprecatedConfigPath }} file to the new global config file at {{ globalConfigPath }}."
|
|
167
|
+
migrationAlreadyCompleted: "No {{ deprecatedConfigPath }} deprecated configuration file found. No migration necessary."
|
|
168
|
+
errors:
|
|
169
|
+
configNotFound: "A configuration file at {{ configPath }} could not be found. Please try again with a valid file path."
|
|
170
|
+
options:
|
|
171
|
+
force: "When merging a deprecated configuration file with an existing global configuration file, overwrite any conflicting values in the global config with the deprecated config values."
|
|
172
|
+
examples:
|
|
173
|
+
default: "Migrate from the deprecated {{ deprecatedConfigPath }} file to the new global config file at {{ globalConfigPath }}"
|
|
174
|
+
configFlag: "Migrate a specific config file (specified with the config flag) to the new global config file at {{ globalConfigPath }}"
|
|
111
175
|
set:
|
|
112
176
|
describe: "Set various configuration options within the hubspot.config.yml file."
|
|
113
177
|
promptMessage: "Select a config option to update"
|
|
@@ -455,8 +519,6 @@ en:
|
|
|
455
519
|
describe: "Authentication method"
|
|
456
520
|
account:
|
|
457
521
|
describe: "HubSpot account to authenticate"
|
|
458
|
-
useHiddenConfig:
|
|
459
|
-
describe: "Use the new HubSpot configuration file located in a hidden file in the user's home directory"
|
|
460
522
|
success:
|
|
461
523
|
configFileCreated: "Created config file \"{{ configPath }}\""
|
|
462
524
|
configFileUpdated: "Connected account \"{{ account }}\" using \"{{ authType }}\" and set it as the default account"
|
|
@@ -464,7 +526,7 @@ en:
|
|
|
464
526
|
updateConfig: "To update an existing config file, use the \"hs auth\" command."
|
|
465
527
|
errors:
|
|
466
528
|
configFileExists: "The config file {{ configPath }} already exists."
|
|
467
|
-
|
|
529
|
+
globalConfigFileExists: "A global config file already exists at {{ configPath }}. To specify a new local config file, delete the existing one and try again."
|
|
468
530
|
lint:
|
|
469
531
|
issuesFound: "{{ count }} issues found."
|
|
470
532
|
groupName: "Linting {{ path }}"
|
|
@@ -588,7 +650,6 @@ en:
|
|
|
588
650
|
componentsToBeMigrated: "The following component types will be migrated: {{ components }}"
|
|
589
651
|
componentsThatWillNotBeMigrated: "[NOTE] These component types are not yet supported for migration but will be available later: {{ components }}"
|
|
590
652
|
errors:
|
|
591
|
-
noAppsForProject: "No apps associated with project {{ projectName }}"
|
|
592
653
|
noAppsEligible: "No apps in account {{ accountId }} are currently migratable"
|
|
593
654
|
noAccountConfig: "There is no account associated with {{ accountId }} in the config file. Please choose another account and try again, or authenticate {{ accountId }} using {{ authCommand }}."
|
|
594
655
|
invalidAccountTypeTitle: "{{#bold}}Developer account not targeted{{/bold}}"
|
|
@@ -656,12 +717,6 @@ en:
|
|
|
656
717
|
examples:
|
|
657
718
|
default: "Create a component within your project"
|
|
658
719
|
withFlags: "Use --name and --type flags to bypass the prompt."
|
|
659
|
-
migrate:
|
|
660
|
-
describe: "Migrate a project to the projects framework."
|
|
661
|
-
errors:
|
|
662
|
-
noProjectConfig: "No project detected. Please run this command again from a project directory."
|
|
663
|
-
examples:
|
|
664
|
-
default: "Migrate a project to the projects framework"
|
|
665
720
|
deploy:
|
|
666
721
|
describe: "Deploy a project build."
|
|
667
722
|
deployBuildIdPrompt: "[--build] Deploy which build?"
|
|
@@ -1201,6 +1256,9 @@ en:
|
|
|
1201
1256
|
compressed: "Project files compressed: {{ byteCount }} bytes"
|
|
1202
1257
|
compressing: "Compressing build files to \"{{ path }}\""
|
|
1203
1258
|
fileFiltered: "Ignore rule triggered for \"{{ filename }}\""
|
|
1259
|
+
middleware:
|
|
1260
|
+
fireAlarm:
|
|
1261
|
+
failedToLoadBoxen: "Failed to load boxen util."
|
|
1204
1262
|
ui:
|
|
1205
1263
|
betaTag: "{{#bold}}[BETA]{{/bold}}"
|
|
1206
1264
|
betaWarning:
|
|
@@ -1221,11 +1279,14 @@ en:
|
|
|
1221
1279
|
command: "--account"
|
|
1222
1280
|
message: "Use the {{ command }} option with any command to override the default account"
|
|
1223
1281
|
accountsListCommand:
|
|
1224
|
-
command: hs
|
|
1282
|
+
command: "hs account list"
|
|
1225
1283
|
message: "Run {{ command }} to see a list of configured HubSpot accounts"
|
|
1226
1284
|
accountsUseCommand:
|
|
1227
|
-
command: "hs
|
|
1285
|
+
command: "hs account use"
|
|
1228
1286
|
message: "Run {{ command }} to set the Hubspot account that the CLI will target by default"
|
|
1287
|
+
accountAuthCommand:
|
|
1288
|
+
command: "hs account auth"
|
|
1289
|
+
message: "Run {{ command }} to connect the CLI to additional HubSpot accounts"
|
|
1229
1290
|
authCommand:
|
|
1230
1291
|
command: "hs auth"
|
|
1231
1292
|
message: "Run {{ command }} to connect the CLI to additional HubSpot accounts"
|
|
@@ -1290,6 +1351,13 @@ en:
|
|
|
1290
1351
|
describe: "Use environment variable config"
|
|
1291
1352
|
debug:
|
|
1292
1353
|
describe: "Set log level to debug"
|
|
1354
|
+
configMigrate:
|
|
1355
|
+
migrateConfigPrompt: "Migrate config?\n From deprecated config file: {{ deprecatedConfigPath }}\n To new global config file: {{ globalConfigPath }}\n (This action will delete the deprecated config file).\n"
|
|
1356
|
+
mergeConfigConflictPrompt: "Change the {{ property }} property in the global config from {{ newValue }} to {{ oldValue }}?"
|
|
1357
|
+
mergeConfigsPrompt: "Two config files detected. Merge them?\n Deprecated config file: {{ deprecatedConfigPath }}\n Global config: {{ globalConfigPath }}\n (This action will delete the deprecated config file).\n"
|
|
1358
|
+
migrationSuccess: "The deprecated config file has been migrated to the new global config file at {{ globalConfigPath }}."
|
|
1359
|
+
mergeSuccess: "The deprecated config file has been merged with the global config file at {{ globalConfigPath }}."
|
|
1360
|
+
skippedExistingAccounts: "\nThe following accounts were not merged, because they already exist in the global config: {{ skippedAccountIds }}.\n"
|
|
1293
1361
|
prompts:
|
|
1294
1362
|
projectDevTargetAccountPrompt:
|
|
1295
1363
|
createNewSandboxOption: "<Test on a new development sandbox>"
|
|
@@ -1576,6 +1644,9 @@ en:
|
|
|
1576
1644
|
doctor:
|
|
1577
1645
|
runningDiagnostics: "Running diagnostics..."
|
|
1578
1646
|
diagnosticsComplete: "Diagnostics complete"
|
|
1647
|
+
defaultAccountOverrideFileChecks:
|
|
1648
|
+
overrideActive: "Default account override file active: {{ defaultAccountOverrideFile }}"
|
|
1649
|
+
overrideAccountId: "Active account ID: {{ overrideAccountId }}"
|
|
1579
1650
|
accountChecks:
|
|
1580
1651
|
active: "Default account active"
|
|
1581
1652
|
inactive: "Default account isn't active"
|
|
@@ -1627,6 +1698,8 @@ en:
|
|
|
1627
1698
|
settings:
|
|
1628
1699
|
httpUseLocalhost: "The setting {{#bold}}httpUseLocalhost{{/bold}} is enabled"
|
|
1629
1700
|
httpUseLocalhostSecondary: "This setting causes all CLI requests to route to localhost"
|
|
1701
|
+
defaultAccountOverrideFile:
|
|
1702
|
+
header: "Default account override file path:"
|
|
1630
1703
|
projectConfig:
|
|
1631
1704
|
header: "Project configuration"
|
|
1632
1705
|
projectDirSubHeader: "Project dir: {{#bold}}{{ projectDir }}{{/bold}}"
|
package/lib/app/migrate.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArgumentsCamelCase } from 'yargs';
|
|
2
|
-
import { LoadedProjectConfig } from '../projects';
|
|
3
2
|
import { MigrateAppOptions } from '../../types/Yargs';
|
|
4
|
-
export declare function
|
|
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
5
|
export declare function logInvalidAccountError(i18nKey: string): void;
|
package/lib/app/migrate.js
CHANGED
|
@@ -3,6 +3,7 @@ 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;
|
|
6
7
|
exports.migrateApp2025_2 = migrateApp2025_2;
|
|
7
8
|
exports.logInvalidAccountError = logInvalidAccountError;
|
|
8
9
|
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
@@ -22,7 +23,6 @@ const projects_3 = require("../projects");
|
|
|
22
23
|
const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
|
|
23
24
|
const polling_1 = require("../polling");
|
|
24
25
|
const migrate_1 = require("../../api/migrate");
|
|
25
|
-
const fs_1 = __importDefault(require("fs"));
|
|
26
26
|
function getUnmigratableReason(reasonCode) {
|
|
27
27
|
switch (reasonCode) {
|
|
28
28
|
case projects_1.UNMIGRATABLE_REASONS.UP_TO_DATE:
|
|
@@ -37,42 +37,30 @@ function getUnmigratableReason(reasonCode) {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
function
|
|
41
|
-
return (app) => {
|
|
42
|
-
if (projectConfig) {
|
|
43
|
-
return app.projectName === projectConfig?.projectConfig?.name;
|
|
44
|
-
}
|
|
45
|
-
return !app.projectName;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
async function handleMigrationSetup(derivedAccountId, options, projectConfig) {
|
|
40
|
+
async function handleMigrationSetup(derivedAccountId, options) {
|
|
49
41
|
const { name, dest, appId } = options;
|
|
50
42
|
const { data: { migratableApps, unmigratableApps }, } = await (0, migrate_1.listAppsForMigration)(derivedAccountId);
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
const reasons =
|
|
59
|
-
if (projectConfig) {
|
|
60
|
-
// TODO: i18n, get copy from UX
|
|
61
|
-
throw new Error('No migratable apps in project');
|
|
62
|
-
}
|
|
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)}`);
|
|
63
51
|
throw new Error(`${(0, lang_1.i18n)(`commands.project.subcommands.migrateApp.errors.noAppsEligible`, {
|
|
64
52
|
accountId: (0, ui_1.uiAccountDescription)(derivedAccountId),
|
|
65
53
|
})}${reasons.length ? `\n - ${reasons.join('\n - ')}` : ''}`);
|
|
66
54
|
}
|
|
67
55
|
if (appId &&
|
|
68
|
-
!
|
|
56
|
+
!allAppsWithoutProject.some(app => {
|
|
69
57
|
return app.appId === appId;
|
|
70
58
|
})) {
|
|
71
59
|
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.chooseApp', {
|
|
72
60
|
appId,
|
|
73
61
|
}));
|
|
74
62
|
}
|
|
75
|
-
const appChoices =
|
|
63
|
+
const appChoices = allAppsWithoutProject.map(app => ({
|
|
76
64
|
name: app.isMigratable
|
|
77
65
|
? app.appName
|
|
78
66
|
: `[${chalk_1.default.yellow('DISABLED')}] ${app.appName} `,
|
|
@@ -88,7 +76,7 @@ async function handleMigrationSetup(derivedAccountId, options, projectConfig) {
|
|
|
88
76
|
});
|
|
89
77
|
appIdToMigrate = selectedAppId;
|
|
90
78
|
}
|
|
91
|
-
const selectedApp =
|
|
79
|
+
const selectedApp = allAppsWithoutProject.find(app => app.appId === appIdToMigrate);
|
|
92
80
|
const migratableComponents = [];
|
|
93
81
|
const unmigratableComponents = [];
|
|
94
82
|
selectedApp?.migrationComponents.forEach(component => {
|
|
@@ -114,18 +102,7 @@ async function handleMigrationSetup(derivedAccountId, options, projectConfig) {
|
|
|
114
102
|
if (!proceed) {
|
|
115
103
|
return {};
|
|
116
104
|
}
|
|
117
|
-
|
|
118
|
-
if (projectConfig &&
|
|
119
|
-
projectConfig?.projectConfig &&
|
|
120
|
-
projectConfig?.projectDir) {
|
|
121
|
-
return {
|
|
122
|
-
appIdToMigrate,
|
|
123
|
-
projectName: projectConfig.projectConfig.name,
|
|
124
|
-
projectDest: projectConfig.projectDir,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
const projectName = projectConfig?.projectConfig?.name ||
|
|
128
|
-
name ||
|
|
105
|
+
const projectName = name ||
|
|
129
106
|
(await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.inputName')));
|
|
130
107
|
const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, projectName, { allowCreate: false, noLogs: true });
|
|
131
108
|
if (projectExists) {
|
|
@@ -160,7 +137,7 @@ async function beginMigration(derivedAccountId, appId, platformVersion) {
|
|
|
160
137
|
const { componentHint, componentType } = component;
|
|
161
138
|
uidMap[componentId] = await (0, promptUtils_1.inputPrompt)((0, lang_1.i18n)('commands.project.subcommands.migrateApp.prompt.uidForComponent', {
|
|
162
139
|
componentName: componentHint
|
|
163
|
-
? `${(0, transform_1.mapToUserFacingType)(componentType)}
|
|
140
|
+
? `${componentHint} [${(0, transform_1.mapToUserFacingType)(componentType)}]`
|
|
164
141
|
: (0, transform_1.mapToUserFacingType)(componentType),
|
|
165
142
|
}), {
|
|
166
143
|
validate: (uid) => {
|
|
@@ -196,43 +173,34 @@ async function finalizeMigration(derivedAccountId, migrationId, uidMap, projectN
|
|
|
196
173
|
SpinniesManager_1.default.fail('finishingMigration', {
|
|
197
174
|
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationFailed`),
|
|
198
175
|
});
|
|
199
|
-
|
|
200
|
-
throw new Error(error.projectErrorDetail);
|
|
201
|
-
}
|
|
202
|
-
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.errors.migrationFailed'), {
|
|
203
|
-
cause: error,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
if (pollResponse.status !== Migration_1.MIGRATION_STATUS.SUCCESS) {
|
|
207
|
-
throw new Error((0, lang_1.i18n)('commands.project.subcommands.migrateApp.errors.migrationFailed'));
|
|
176
|
+
throw error;
|
|
208
177
|
}
|
|
209
178
|
if (pollResponse.status === Migration_1.MIGRATION_STATUS.SUCCESS) {
|
|
210
179
|
SpinniesManager_1.default.succeed('finishingMigration', {
|
|
211
180
|
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.migrationComplete`),
|
|
212
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'));
|
|
213
193
|
}
|
|
214
|
-
return pollResponse.buildId;
|
|
215
194
|
}
|
|
216
|
-
async function downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest
|
|
195
|
+
async function downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest) {
|
|
217
196
|
try {
|
|
218
197
|
SpinniesManager_1.default.add('fetchingMigratedProject', {
|
|
219
198
|
text: (0, lang_1.i18n)(`commands.project.subcommands.migrateApp.spinners.downloadingProjectContents`),
|
|
220
199
|
});
|
|
221
200
|
const { data: zippedProject } = await (0, projects_2.downloadProject)(derivedAccountId, projectName, buildId);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
absoluteDestPath = projectDir;
|
|
226
|
-
const { srcDir } = projectConfig.projectConfig;
|
|
227
|
-
const archiveDest = path_1.default.join(projectDir, 'archive');
|
|
228
|
-
// Move the existing source directory to archive
|
|
229
|
-
fs_1.default.renameSync(path_1.default.join(projectDir, srcDir), archiveDest);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
absoluteDestPath = projectDest
|
|
233
|
-
? path_1.default.resolve((0, path_2.getCwd)(), projectDest)
|
|
234
|
-
: (0, path_2.getCwd)();
|
|
235
|
-
}
|
|
201
|
+
const absoluteDestPath = projectDest
|
|
202
|
+
? path_1.default.resolve((0, path_2.getCwd)(), projectDest)
|
|
203
|
+
: (0, path_2.getCwd)();
|
|
236
204
|
await (0, archive_1.extractZipArchive)(zippedProject, (0, path_2.sanitizeFileName)(projectName), absoluteDestPath, {
|
|
237
205
|
includesRootDir: true,
|
|
238
206
|
hideLogs: true,
|
|
@@ -249,19 +217,9 @@ async function downloadProjectFiles(derivedAccountId, projectName, buildId, proj
|
|
|
249
217
|
throw error;
|
|
250
218
|
}
|
|
251
219
|
}
|
|
252
|
-
async function migrateApp2025_2(derivedAccountId, options
|
|
220
|
+
async function migrateApp2025_2(derivedAccountId, options) {
|
|
253
221
|
SpinniesManager_1.default.init();
|
|
254
|
-
|
|
255
|
-
if (!projectConfig?.projectConfig || !projectConfig?.projectDir) {
|
|
256
|
-
throw new Error('Invalid project config');
|
|
257
|
-
}
|
|
258
|
-
// TODO: i18n
|
|
259
|
-
const { projectExists } = await (0, projects_3.ensureProjectExists)(derivedAccountId, projectConfig.projectConfig.name, { allowCreate: false, noLogs: true });
|
|
260
|
-
if (!projectExists) {
|
|
261
|
-
throw new Error('Project does not exist, unable to migrate');
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
const { appIdToMigrate, projectName, projectDest } = await handleMigrationSetup(derivedAccountId, options, projectConfig);
|
|
222
|
+
const { appIdToMigrate, projectName, projectDest } = await handleMigrationSetup(derivedAccountId, options);
|
|
265
223
|
if (!appIdToMigrate || !projectName || !projectDest) {
|
|
266
224
|
return;
|
|
267
225
|
}
|
|
@@ -270,8 +228,8 @@ async function migrateApp2025_2(derivedAccountId, options, projectConfig) {
|
|
|
270
228
|
return;
|
|
271
229
|
}
|
|
272
230
|
const { migrationId, uidMap } = migrationInProgress;
|
|
273
|
-
const buildId = await finalizeMigration(derivedAccountId, migrationId, uidMap,
|
|
274
|
-
await downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest
|
|
231
|
+
const buildId = await finalizeMigration(derivedAccountId, migrationId, uidMap, projectName);
|
|
232
|
+
await downloadProjectFiles(derivedAccountId, projectName, buildId, projectDest);
|
|
275
233
|
}
|
|
276
234
|
function logInvalidAccountError(i18nKey) {
|
|
277
235
|
(0, ui_1.uiLine)();
|
|
@@ -31,15 +31,13 @@ async function migrateApp2023_2(derivedAccountId, options, accountConfig) {
|
|
|
31
31
|
(0, migrate_1.logInvalidAccountError)('commands.project.subcommands.migrateApp');
|
|
32
32
|
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const { appId } = 'appId' in options
|
|
35
|
+
? options
|
|
36
|
+
: await (0, selectPublicAppPrompt_1.selectPublicAppPrompt)({
|
|
37
37
|
accountId: derivedAccountId,
|
|
38
38
|
accountName,
|
|
39
39
|
isMigratingApp: true,
|
|
40
40
|
});
|
|
41
|
-
appId = selectAppId;
|
|
42
|
-
}
|
|
43
41
|
try {
|
|
44
42
|
const { data: selectedApp } = await (0, appsDev_1.fetchPublicAppMetadata)(appId, derivedAccountId);
|
|
45
43
|
// preventProjectMigrations returns true if we have not added app to allowlist config.
|
|
@@ -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
|
+
}
|
|
@@ -11,16 +11,15 @@ interface Section {
|
|
|
11
11
|
export declare class Diagnosis {
|
|
12
12
|
private readonly prefixes;
|
|
13
13
|
private readonly diagnosis;
|
|
14
|
-
private readonly indentation;
|
|
15
14
|
private errorCount;
|
|
16
15
|
private warningCount;
|
|
17
16
|
constructor({ diagnosticInfo, accountId }: DiagnosisOptions);
|
|
18
|
-
private indent;
|
|
19
17
|
getErrorCount(): number;
|
|
20
18
|
getWarningCount(): number;
|
|
21
19
|
addCliSection(section: Section): void;
|
|
22
20
|
addProjectSection(section: Section): void;
|
|
23
21
|
addCLIConfigSection(section: Section): void;
|
|
22
|
+
addDefaultAccountOverrideFileSection(section: Section): void;
|
|
24
23
|
toString(): string;
|
|
25
24
|
private generateSections;
|
|
26
25
|
}
|
package/lib/doctor/Diagnosis.js
CHANGED
|
@@ -5,12 +5,12 @@ const spinniesUtils_1 = require("../ui/spinniesUtils");
|
|
|
5
5
|
const chalk_1 = require("chalk");
|
|
6
6
|
const interpolation_1 = require("../interpolation");
|
|
7
7
|
const ui_1 = require("../ui");
|
|
8
|
+
const index_1 = require("../ui/index");
|
|
8
9
|
const { i18n } = require('../lang');
|
|
9
10
|
const i18nKey = `lib.doctor.diagnosis`;
|
|
10
11
|
class Diagnosis {
|
|
11
12
|
prefixes;
|
|
12
13
|
diagnosis;
|
|
13
|
-
indentation = ' ';
|
|
14
14
|
errorCount = 0;
|
|
15
15
|
warningCount = 0;
|
|
16
16
|
constructor({ diagnosticInfo, accountId }) {
|
|
@@ -29,6 +29,10 @@ class Diagnosis {
|
|
|
29
29
|
header: i18n(`${i18nKey}.cliConfig.header`),
|
|
30
30
|
sections: [],
|
|
31
31
|
},
|
|
32
|
+
defaultAccountOverrideFile: {
|
|
33
|
+
header: i18n(`${i18nKey}.defaultAccountOverrideFile.header`),
|
|
34
|
+
sections: [],
|
|
35
|
+
},
|
|
32
36
|
project: {
|
|
33
37
|
header: i18n(`${i18nKey}.projectConfig.header`),
|
|
34
38
|
subheaders: [
|
|
@@ -53,9 +57,6 @@ class Diagnosis {
|
|
|
53
57
|
];
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
|
-
indent(level) {
|
|
57
|
-
return this.indentation.repeat(level);
|
|
58
|
-
}
|
|
59
60
|
getErrorCount() {
|
|
60
61
|
return this.errorCount;
|
|
61
62
|
}
|
|
@@ -71,6 +72,9 @@ class Diagnosis {
|
|
|
71
72
|
addCLIConfigSection(section) {
|
|
72
73
|
this.diagnosis.cliConfig.sections.push(section);
|
|
73
74
|
}
|
|
75
|
+
addDefaultAccountOverrideFileSection(section) {
|
|
76
|
+
this.diagnosis.defaultAccountOverrideFile.sections.push(section);
|
|
77
|
+
}
|
|
74
78
|
toString() {
|
|
75
79
|
const output = [];
|
|
76
80
|
for (const value of Object.values(this.diagnosis)) {
|
|
@@ -108,9 +112,9 @@ class Diagnosis {
|
|
|
108
112
|
else if (section.type === 'warning') {
|
|
109
113
|
this.warningCount++;
|
|
110
114
|
}
|
|
111
|
-
output.push(`${
|
|
115
|
+
output.push(`${(0, index_1.indent)(1)}${this.prefixes[section.type]} ${section.message}`);
|
|
112
116
|
if (section.secondaryMessaging) {
|
|
113
|
-
output.push(`${
|
|
117
|
+
output.push(`${(0, index_1.indent)(2)}- ${section.secondaryMessaging}`);
|
|
114
118
|
}
|
|
115
119
|
});
|
|
116
120
|
return output.join('\n');
|
|
@@ -64,6 +64,7 @@ class DiagnosticInfoBuilder {
|
|
|
64
64
|
arch,
|
|
65
65
|
path: mainModule?.path,
|
|
66
66
|
config: (0, config_2.getConfigPath)(),
|
|
67
|
+
defaultAccountOverrideFile: (0, config_1.getDefaultAccountOverrideFilePath)(),
|
|
67
68
|
configSettings: this.configSettings,
|
|
68
69
|
versions: {
|
|
69
70
|
[hubspotCli]: package_json_1.default.version,
|