@hubspot/cli 7.7.16-experimental.1 → 7.7.16-experimental.10
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/commands/account/auth.js +3 -3
- package/commands/app/install.d.ts +8 -0
- package/commands/app/install.js +127 -0
- package/commands/app.js +6 -1
- package/commands/auth.js +23 -25
- package/commands/getStarted.js +55 -8
- package/commands/init.js +29 -31
- package/commands/project/cloneApp.js +4 -4
- package/commands/project/create.js +9 -9
- package/commands/project/dev/deprecatedFlow.js +4 -4
- package/commands/project/dev/index.js +5 -5
- package/commands/project/dev/unifiedFlow.js +8 -0
- package/commands/sandbox/delete.js +5 -5
- package/commands/testAccount/create.js +53 -3
- package/lang/en.d.ts +67 -15
- package/lang/en.js +64 -12
- package/lib/accountTypes.d.ts +1 -0
- package/lib/accountTypes.js +20 -9
- package/lib/app/migrate_legacy.js +2 -3
- package/lib/app/urls.d.ts +1 -1
- package/lib/commonOpts.js +1 -1
- package/lib/middleware/__test__/configMiddleware.test.js +2 -2
- package/lib/middleware/configMiddleware.js +10 -2
- package/lib/parsing.d.ts +1 -0
- package/lib/parsing.js +11 -0
- package/lib/polling.d.ts +1 -1
- package/lib/polling.js +11 -1
- package/lib/projects/add/v3AddComponent.js +4 -0
- package/lib/projects/create/index.d.ts +3 -2
- package/lib/projects/create/index.js +11 -5
- package/lib/projects/create/v3.d.ts +3 -3
- package/lib/projects/create/v3.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.js +1 -1
- package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
- package/lib/projects/localDev/LocalDevProcess.js +16 -12
- package/lib/projects/localDev/LocalDevState.d.ts +10 -5
- package/lib/projects/localDev/LocalDevState.js +18 -20
- package/lib/projects/localDev/LocalDevWatcher.js +1 -1
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +2 -1
- package/lib/projects/upload.js +1 -0
- package/lib/prompts/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
- package/lib/prompts/projectNameAndDestPrompt.js +60 -0
- package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
- package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
- package/lib/validation.d.ts +1 -1
- package/lib/validation.js +4 -4
- package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
- package/package.json +3 -3
- package/types/LocalDev.d.ts +1 -0
- package/types/Yargs.d.ts +1 -1
- package/lib/prompts/createProjectPrompt.d.ts +0 -28
package/commands/account/auth.js
CHANGED
|
@@ -98,9 +98,9 @@ async function handleConfigMigration() {
|
|
|
98
98
|
const describe = en_1.commands.account.subcommands.auth.describe;
|
|
99
99
|
const command = 'auth';
|
|
100
100
|
async function handler(args) {
|
|
101
|
-
const {
|
|
101
|
+
const { disableTracking, personalAccessKey: providedPersonalAccessKey, derivedAccountId, } = args;
|
|
102
102
|
if (!disableTracking) {
|
|
103
|
-
(0, usageTracking_1.trackCommandUsage)('account-auth', {},
|
|
103
|
+
(0, usageTracking_1.trackCommandUsage)('account-auth', {}, derivedAccountId);
|
|
104
104
|
await (0, usageTracking_1.trackAuthAction)('account-auth', authType, TRACKING_STATUS.STARTED);
|
|
105
105
|
}
|
|
106
106
|
const configMigrationSuccess = await handleConfigMigration();
|
|
@@ -114,7 +114,7 @@ async function handler(args) {
|
|
|
114
114
|
}
|
|
115
115
|
(0, config_1.loadConfig)('');
|
|
116
116
|
(0, process_1.handleExit)(config_1.deleteEmptyConfigFile);
|
|
117
|
-
const updatedConfig = await updateConfigWithNewAccount(args.qa ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD, configAlreadyExists, providedPersonalAccessKey,
|
|
117
|
+
const updatedConfig = await updateConfigWithNewAccount(args.qa ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD, configAlreadyExists, providedPersonalAccessKey, derivedAccountId);
|
|
118
118
|
if (!updatedConfig) {
|
|
119
119
|
if (!disableTracking) {
|
|
120
120
|
await (0, usageTracking_1.trackAuthAction)('account-auth', authType, TRACKING_STATUS.ERROR);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule, JSONOutputArgs } from '../../types/Yargs';
|
|
2
|
+
type InstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
appUid?: string;
|
|
4
|
+
projectName?: string;
|
|
5
|
+
testAccountId: number;
|
|
6
|
+
};
|
|
7
|
+
declare const installAppCommand: YargsCommandModule<unknown, InstallAppArgs>;
|
|
8
|
+
export default installAppCommand;
|
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
const developerTestAccounts_1 = require("@hubspot/local-dev-lib/api/developerTestAccounts");
|
|
7
|
+
const usageTracking_1 = require("../../lib/usageTracking");
|
|
8
|
+
const en_1 = require("../../lang/en");
|
|
9
|
+
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
10
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
11
|
+
const constants_1 = require("../../lib/constants");
|
|
12
|
+
const logger_1 = require("../../lib/ui/logger");
|
|
13
|
+
const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
|
|
14
|
+
const errorHandlers_1 = require("../../lib/errorHandlers");
|
|
15
|
+
const polling_1 = require("../../lib/polling");
|
|
16
|
+
const config_1 = require("../../lib/projects/config");
|
|
17
|
+
const upload_1 = require("../../lib/projects/upload");
|
|
18
|
+
const structure_1 = require("../../lib/projects/structure");
|
|
19
|
+
const command = 'install <test-account-id>';
|
|
20
|
+
const describe = undefined; // commands.app.subcommands.install.describe;
|
|
21
|
+
async function handler(args) {
|
|
22
|
+
const { derivedAccountId, appUid, projectName, testAccountId, formatOutputAsJson, } = args;
|
|
23
|
+
(0, usageTracking_1.trackCommandUsage)('app-install', {}, derivedAccountId);
|
|
24
|
+
const jsonOutput = {};
|
|
25
|
+
let targetProjectName = projectName;
|
|
26
|
+
let targetAppUid = appUid;
|
|
27
|
+
const { projectConfig, projectDir } = await (0, config_1.getProjectConfig)();
|
|
28
|
+
if (!targetProjectName) {
|
|
29
|
+
(0, config_1.validateProjectConfig)(projectConfig, projectDir);
|
|
30
|
+
targetProjectName = projectConfig?.name;
|
|
31
|
+
}
|
|
32
|
+
if (!targetProjectName) {
|
|
33
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.mustSpecifyProjectName);
|
|
34
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
35
|
+
}
|
|
36
|
+
let isAppOauth = true;
|
|
37
|
+
if (!targetAppUid) {
|
|
38
|
+
const intermediateRepresentation = await (0, upload_1.handleTranslate)(projectDir, projectConfig, derivedAccountId, true, undefined);
|
|
39
|
+
if (intermediateRepresentation) {
|
|
40
|
+
Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).forEach(node => {
|
|
41
|
+
if ((0, structure_1.isAppIRNode)(node)) {
|
|
42
|
+
targetAppUid = node.uid;
|
|
43
|
+
isAppOauth = node.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!targetAppUid) {
|
|
49
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.noAppUidFound);
|
|
50
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
51
|
+
}
|
|
52
|
+
if (!isAppOauth) {
|
|
53
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.appMustBeOauth);
|
|
54
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const { data } = await (0, developerTestAccounts_1.installOauthAppIntoDeveloperTestAccount)(derivedAccountId, testAccountId, targetProjectName, targetAppUid);
|
|
58
|
+
if (data?.authCodes.length > 0) {
|
|
59
|
+
jsonOutput.authCode = data.authCodes[0].authCode;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
(0, errorHandlers_1.logError)(err);
|
|
64
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
65
|
+
}
|
|
66
|
+
SpinniesManager_1.default.init({
|
|
67
|
+
succeedColor: 'white',
|
|
68
|
+
});
|
|
69
|
+
SpinniesManager_1.default.add('installApp', {
|
|
70
|
+
text: en_1.commands.app.subcommands.install.polling.start,
|
|
71
|
+
});
|
|
72
|
+
let appInstallSucceeded = false;
|
|
73
|
+
try {
|
|
74
|
+
await (0, polling_1.poll)(() => (0, developerTestAccounts_1.fetchDeveloperTestAccountOauthAppInstallStatus)(derivedAccountId, targetProjectName, targetAppUid), {
|
|
75
|
+
successStates: ['SUCCESS'],
|
|
76
|
+
errorStates: [],
|
|
77
|
+
});
|
|
78
|
+
appInstallSucceeded = true;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
SpinniesManager_1.default.fail('installApp');
|
|
82
|
+
(0, errorHandlers_1.logError)(err);
|
|
83
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
84
|
+
}
|
|
85
|
+
if (!appInstallSucceeded) {
|
|
86
|
+
SpinniesManager_1.default.fail('installApp');
|
|
87
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
88
|
+
}
|
|
89
|
+
SpinniesManager_1.default.succeed('installApp', {
|
|
90
|
+
text: en_1.commands.app.subcommands.install.polling.success,
|
|
91
|
+
});
|
|
92
|
+
if (formatOutputAsJson) {
|
|
93
|
+
logger_1.uiLogger.json(jsonOutput);
|
|
94
|
+
}
|
|
95
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
96
|
+
}
|
|
97
|
+
function installAppBuilder(yargs) {
|
|
98
|
+
yargs.positional('test-account-id', {
|
|
99
|
+
describe: en_1.commands.app.subcommands.install.positionals.testAccountId,
|
|
100
|
+
required: true,
|
|
101
|
+
type: 'number',
|
|
102
|
+
});
|
|
103
|
+
yargs.option('app-uid', {
|
|
104
|
+
describe: en_1.commands.app.subcommands.install.options.appUid,
|
|
105
|
+
type: 'string',
|
|
106
|
+
});
|
|
107
|
+
yargs.option('project-name', {
|
|
108
|
+
describe: en_1.commands.app.subcommands.install.options.projectName,
|
|
109
|
+
type: 'string',
|
|
110
|
+
});
|
|
111
|
+
yargs.example('install 1234567890 --app-uid=my-app-uid --project-name=my-project', en_1.commands.app.subcommands.install.example);
|
|
112
|
+
return yargs;
|
|
113
|
+
}
|
|
114
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(installAppBuilder, command, en_1.commands.app.subcommands.install.describe, {
|
|
115
|
+
useGlobalOptions: true,
|
|
116
|
+
useAccountOptions: true,
|
|
117
|
+
useConfigOptions: true,
|
|
118
|
+
useEnvironmentOptions: true,
|
|
119
|
+
useJSONOutputOptions: true,
|
|
120
|
+
});
|
|
121
|
+
const installAppCommand = {
|
|
122
|
+
command,
|
|
123
|
+
describe,
|
|
124
|
+
handler,
|
|
125
|
+
builder,
|
|
126
|
+
};
|
|
127
|
+
exports.default = installAppCommand;
|
package/commands/app.js
CHANGED
|
@@ -5,12 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const migrate_1 = __importDefault(require("./app/migrate"));
|
|
7
7
|
const secret_1 = __importDefault(require("./app/secret"));
|
|
8
|
+
const install_1 = __importDefault(require("./app/install"));
|
|
8
9
|
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
9
10
|
const command = ['app', 'apps'];
|
|
10
11
|
// Keep the command hidden for now
|
|
11
12
|
const describe = undefined;
|
|
12
13
|
function appBuilder(yargs) {
|
|
13
|
-
yargs
|
|
14
|
+
yargs
|
|
15
|
+
.command(migrate_1.default)
|
|
16
|
+
.command(secret_1.default)
|
|
17
|
+
.command(install_1.default)
|
|
18
|
+
.demandCommand(1, '');
|
|
14
19
|
return yargs;
|
|
15
20
|
}
|
|
16
21
|
const builder = (0, yargsUtils_1.makeYargsBuilder)(appBuilder, command, describe);
|
package/commands/auth.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const git_1 = require("../lib/ui/git");
|
|
4
|
-
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
5
4
|
const auth_1 = require("@hubspot/local-dev-lib/constants/auth");
|
|
6
5
|
const environments_1 = require("@hubspot/local-dev-lib/constants/environments");
|
|
7
6
|
const config_1 = require("@hubspot/local-dev-lib/constants/config");
|
|
8
|
-
const lang_1 = require("../lib/lang");
|
|
9
7
|
const personalAccessKey_1 = require("@hubspot/local-dev-lib/personalAccessKey");
|
|
10
8
|
const config_2 = require("@hubspot/local-dev-lib/config");
|
|
11
9
|
const text_1 = require("@hubspot/local-dev-lib/text");
|
|
@@ -21,6 +19,8 @@ const exitCodes_1 = require("../lib/enums/exitCodes");
|
|
|
21
19
|
const ui_1 = require("../lib/ui");
|
|
22
20
|
const index_1 = require("../lib/errorHandlers/index");
|
|
23
21
|
const en_1 = require("../lang/en");
|
|
22
|
+
const logger_1 = require("../lib/ui/logger");
|
|
23
|
+
const parsing_1 = require("../lib/parsing");
|
|
24
24
|
const TRACKING_STATUS = {
|
|
25
25
|
STARTED: 'started',
|
|
26
26
|
ERROR: 'error',
|
|
@@ -32,9 +32,19 @@ const ALLOWED_AUTH_METHODS = [
|
|
|
32
32
|
];
|
|
33
33
|
const SUPPORTED_AUTHENTICATION_PROTOCOLS_TEXT = (0, text_1.commaSeparatedValues)(ALLOWED_AUTH_METHODS);
|
|
34
34
|
const command = 'auth';
|
|
35
|
-
const describe =
|
|
35
|
+
const describe = en_1.commands.auth.describe;
|
|
36
36
|
async function handler(args) {
|
|
37
|
-
const { authType: authTypeFlagValue, config: configFlagValue, qa,
|
|
37
|
+
const { authType: authTypeFlagValue, config: configFlagValue, qa, personalAccessKey: providedPersonalAccessKey, userProvidedAccount, } = args;
|
|
38
|
+
let parsedUserProvidedAccountId;
|
|
39
|
+
try {
|
|
40
|
+
if (userProvidedAccount) {
|
|
41
|
+
parsedUserProvidedAccountId = (0, parsing_1.parseStringToNumber)(userProvidedAccount);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
(0, index_1.logError)(en_1.commands.auth.errors.invalidAccountIdProvided);
|
|
46
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
47
|
+
}
|
|
38
48
|
const authType = (authTypeFlagValue && authTypeFlagValue.toLowerCase()) ||
|
|
39
49
|
auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value;
|
|
40
50
|
(0, commonOpts_1.setLogLevel)(args);
|
|
@@ -46,13 +56,11 @@ async function handler(args) {
|
|
|
46
56
|
(0, git_1.checkAndWarnGitInclusion)(configPath);
|
|
47
57
|
}
|
|
48
58
|
if ((0, config_2.configFileExists)(true)) {
|
|
49
|
-
logger_1.
|
|
50
|
-
accountAuthCommand: (0, ui_1.uiCommandReference)('hs account auth'),
|
|
51
|
-
}));
|
|
59
|
+
logger_1.uiLogger.error(en_1.commands.auth.errors.globalConfigFileExists('hs account auth'));
|
|
52
60
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
53
61
|
}
|
|
54
62
|
(0, usageTracking_1.trackCommandUsage)('auth');
|
|
55
|
-
(0, usageTracking_1.trackAuthAction)('auth', authType, TRACKING_STATUS.STARTED,
|
|
63
|
+
(0, usageTracking_1.trackAuthAction)('auth', authType, TRACKING_STATUS.STARTED, parsedUserProvidedAccountId);
|
|
56
64
|
let configData;
|
|
57
65
|
let updatedConfig;
|
|
58
66
|
let validName;
|
|
@@ -73,7 +81,7 @@ async function handler(args) {
|
|
|
73
81
|
? { personalAccessKey: providedPersonalAccessKey }
|
|
74
82
|
: await (0, personalAccessKeyPrompt_1.personalAccessKeyPrompt)({
|
|
75
83
|
env,
|
|
76
|
-
account:
|
|
84
|
+
account: parsedUserProvidedAccountId,
|
|
77
85
|
});
|
|
78
86
|
try {
|
|
79
87
|
token = await (0, personalAccessKey_1.getAccessToken)(personalAccessKey, env);
|
|
@@ -101,24 +109,17 @@ async function handler(args) {
|
|
|
101
109
|
successAuthMethod = auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.name;
|
|
102
110
|
break;
|
|
103
111
|
default:
|
|
104
|
-
logger_1.
|
|
105
|
-
supportedProtocols: SUPPORTED_AUTHENTICATION_PROTOCOLS_TEXT,
|
|
106
|
-
type: authType,
|
|
107
|
-
}));
|
|
112
|
+
logger_1.uiLogger.error(en_1.commands.auth.errors.unsupportedAuthType(authType, SUPPORTED_AUTHENTICATION_PROTOCOLS_TEXT));
|
|
108
113
|
break;
|
|
109
114
|
}
|
|
110
115
|
if (!successAuthMethod) {
|
|
111
|
-
await (0, usageTracking_1.trackAuthAction)('auth', authType, TRACKING_STATUS.ERROR,
|
|
116
|
+
await (0, usageTracking_1.trackAuthAction)('auth', authType, TRACKING_STATUS.ERROR, parsedUserProvidedAccountId);
|
|
112
117
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
113
118
|
}
|
|
114
119
|
const nameFromConfigData = configData && 'name' in configData ? configData.name : undefined;
|
|
115
120
|
const accountName = (updatedConfig && updatedConfig.name) || validName || nameFromConfigData;
|
|
116
121
|
await (0, setAsDefaultAccountPrompt_1.setAsDefaultAccountPrompt)(accountName);
|
|
117
|
-
logger_1.
|
|
118
|
-
configFilename: config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
119
|
-
authType: successAuthMethod,
|
|
120
|
-
accountName,
|
|
121
|
-
}));
|
|
122
|
+
logger_1.uiLogger.success(en_1.commands.auth.success.configFileUpdated(accountName, config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME, successAuthMethod));
|
|
122
123
|
(0, ui_1.uiFeatureHighlight)([
|
|
123
124
|
'accountsUseCommand',
|
|
124
125
|
'accountOption',
|
|
@@ -131,7 +132,7 @@ async function handler(args) {
|
|
|
131
132
|
function authBuilder(yargs) {
|
|
132
133
|
yargs.options({
|
|
133
134
|
'auth-type': {
|
|
134
|
-
describe:
|
|
135
|
+
describe: en_1.commands.auth.options.authType.describe,
|
|
135
136
|
type: 'string',
|
|
136
137
|
choices: [
|
|
137
138
|
`${auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value}`,
|
|
@@ -140,7 +141,7 @@ function authBuilder(yargs) {
|
|
|
140
141
|
default: auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value,
|
|
141
142
|
},
|
|
142
143
|
account: {
|
|
143
|
-
describe:
|
|
144
|
+
describe: en_1.commands.auth.options.account.describe,
|
|
144
145
|
type: 'string',
|
|
145
146
|
alias: 'a',
|
|
146
147
|
},
|
|
@@ -153,10 +154,7 @@ function authBuilder(yargs) {
|
|
|
153
154
|
});
|
|
154
155
|
return yargs;
|
|
155
156
|
}
|
|
156
|
-
const builder = (0, yargsUtils_1.makeYargsBuilder)(authBuilder, command,
|
|
157
|
-
authMethod: auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value,
|
|
158
|
-
configName: config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
159
|
-
}), {
|
|
157
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(authBuilder, command, en_1.commands.auth.verboseDescribe(auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value, config_1.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME), {
|
|
160
158
|
useGlobalOptions: true,
|
|
161
159
|
useConfigOptions: true,
|
|
162
160
|
useTestingOptions: true,
|
package/commands/getStarted.js
CHANGED
|
@@ -14,20 +14,25 @@ const usageTracking_1 = require("../lib/usageTracking");
|
|
|
14
14
|
const exitCodes_1 = require("../lib/enums/exitCodes");
|
|
15
15
|
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
16
16
|
const promptUtils_1 = require("../lib/prompts/promptUtils");
|
|
17
|
-
const
|
|
17
|
+
const projectNameAndDestPrompt_1 = require("../lib/prompts/projectNameAndDestPrompt");
|
|
18
18
|
const ui_1 = require("../lib/ui");
|
|
19
19
|
const logger_1 = require("../lib/ui/logger");
|
|
20
20
|
const errorHandlers_1 = require("../lib/errorHandlers");
|
|
21
21
|
const upload_1 = require("../lib/projects/upload");
|
|
22
22
|
const constants_1 = require("../lib/constants");
|
|
23
23
|
const config_1 = require("../lib/projects/config");
|
|
24
|
+
const dependencyManagement_1 = require("../lib/dependencyManagement");
|
|
24
25
|
const buildAndDeploy_1 = require("../lib/projects/buildAndDeploy");
|
|
25
|
-
const urls_1 = require("../lib/projects/urls");
|
|
26
26
|
const links_1 = require("../lib/links");
|
|
27
|
+
const urls_1 = require("../lib/app/urls");
|
|
28
|
+
const config_2 = require("@hubspot/local-dev-lib/config");
|
|
29
|
+
const environments_1 = require("@hubspot/local-dev-lib/constants/environments");
|
|
30
|
+
const appsDev_1 = require("@hubspot/local-dev-lib/api/appsDev");
|
|
27
31
|
exports.command = 'get-started';
|
|
28
32
|
exports.describe = undefined;
|
|
29
33
|
async function handler(args) {
|
|
30
34
|
const { derivedAccountId } = args;
|
|
35
|
+
const env = (0, config_2.getEnv)(derivedAccountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD;
|
|
31
36
|
// TODO: Put this in constants.ts once we have a defined place for the template before INBOUND
|
|
32
37
|
const templateSource = 'robrown-hubspot/hubspot-project-components-ua-app-objects-beta';
|
|
33
38
|
(0, usageTracking_1.trackCommandUsage)('get-started', {}, derivedAccountId);
|
|
@@ -73,10 +78,10 @@ async function handler(args) {
|
|
|
73
78
|
}
|
|
74
79
|
else {
|
|
75
80
|
logger_1.uiLogger.log(' ');
|
|
76
|
-
logger_1.uiLogger.log(en_1.commands.getStarted.
|
|
81
|
+
logger_1.uiLogger.log(en_1.commands.getStarted.logs.appSelected);
|
|
77
82
|
// 1. Fetch project templates
|
|
78
83
|
let latestRepoReleaseTag;
|
|
79
|
-
const { dest, name } = await (0,
|
|
84
|
+
const { dest, name } = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(args);
|
|
80
85
|
// Specific template for get-started command
|
|
81
86
|
const projectTemplate = {
|
|
82
87
|
name: 'private-app-get-started-template',
|
|
@@ -122,7 +127,44 @@ async function handler(args) {
|
|
|
122
127
|
logger_1.uiLogger.log(' ');
|
|
123
128
|
logger_1.uiLogger.log(en_1.commands.getStarted.prompts.projectCreated.description);
|
|
124
129
|
logger_1.uiLogger.log(' ');
|
|
125
|
-
// 5. Ask user if they want to
|
|
130
|
+
// 5. Install dependencies - Ask user if they want to install dependencies
|
|
131
|
+
const { shouldInstallDependencies } = await (0, promptUtils_1.promptUser)([
|
|
132
|
+
{
|
|
133
|
+
type: 'confirm',
|
|
134
|
+
name: 'shouldInstallDependencies',
|
|
135
|
+
message: en_1.commands.getStarted.prompts.installDependencies,
|
|
136
|
+
default: true,
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
if (shouldInstallDependencies) {
|
|
140
|
+
try {
|
|
141
|
+
// Change to the project directory to install dependencies
|
|
142
|
+
const originalCwd = process.cwd();
|
|
143
|
+
process.chdir(projectDest);
|
|
144
|
+
try {
|
|
145
|
+
await (0, dependencyManagement_1.installPackages)({});
|
|
146
|
+
logger_1.uiLogger.log(' ');
|
|
147
|
+
logger_1.uiLogger.success(en_1.commands.getStarted.logs.dependenciesInstalled);
|
|
148
|
+
logger_1.uiLogger.log(' ');
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
// Always restore the original working directory
|
|
152
|
+
process.chdir(originalCwd);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
logger_1.uiLogger.log(' ');
|
|
157
|
+
logger_1.uiLogger.error(en_1.commands.getStarted.errors.installDepsFailed);
|
|
158
|
+
console.log(err);
|
|
159
|
+
logger_1.uiLogger.log(' ');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
logger_1.uiLogger.log(' ');
|
|
164
|
+
logger_1.uiLogger.log(en_1.commands.getStarted.logs.dependenciesNotInstalled);
|
|
165
|
+
logger_1.uiLogger.log(' ');
|
|
166
|
+
}
|
|
167
|
+
// 6. Ask user if they want to upload the project
|
|
126
168
|
const { shouldUpload } = await (0, promptUtils_1.promptUser)([
|
|
127
169
|
{
|
|
128
170
|
type: 'confirm',
|
|
@@ -162,8 +204,9 @@ async function handler(args) {
|
|
|
162
204
|
(0, errorHandlers_1.debugError)(uploadError);
|
|
163
205
|
}
|
|
164
206
|
else if (result) {
|
|
165
|
-
logger_1.uiLogger.log(' ');
|
|
166
207
|
logger_1.uiLogger.success(en_1.commands.getStarted.logs.uploadSuccess);
|
|
208
|
+
const { data: { results }, } = await (0, appsDev_1.fetchPublicAppsForPortal)(derivedAccountId);
|
|
209
|
+
const lastCreatedApp = results.sort((a, b) => b.createdAt - a.createdAt)[0];
|
|
167
210
|
if (process.env.BROWSER !== 'none') {
|
|
168
211
|
logger_1.uiLogger.log(' ');
|
|
169
212
|
logger_1.uiLogger.log(en_1.commands.getStarted.developerOverviewBrowserOpenPrep);
|
|
@@ -172,11 +215,15 @@ async function handler(args) {
|
|
|
172
215
|
{
|
|
173
216
|
name: 'shouldOpenOverview',
|
|
174
217
|
type: 'confirm',
|
|
175
|
-
message: en_1.commands.getStarted.
|
|
218
|
+
message: en_1.commands.getStarted.openInstallUrl,
|
|
176
219
|
},
|
|
177
220
|
]);
|
|
178
221
|
if (shouldOpenOverview) {
|
|
179
|
-
(0, open_1.default)((0, urls_1.
|
|
222
|
+
(0, open_1.default)((0, urls_1.getStaticAuthAppInstallUrl)({
|
|
223
|
+
targetAccountId: derivedAccountId,
|
|
224
|
+
env: env,
|
|
225
|
+
appId: lastCreatedApp.id,
|
|
226
|
+
}), { url: true });
|
|
180
227
|
logger_1.uiLogger.log(' ');
|
|
181
228
|
logger_1.uiLogger.success(en_1.commands.getStarted.openedDeveloperOverview);
|
|
182
229
|
}
|
package/commands/init.js
CHANGED
|
@@ -13,13 +13,11 @@ const personalAccessKey_1 = require("@hubspot/local-dev-lib/personalAccessKey");
|
|
|
13
13
|
const path_2 = require("@hubspot/local-dev-lib/path");
|
|
14
14
|
const text_1 = require("@hubspot/local-dev-lib/text");
|
|
15
15
|
const environments_1 = require("@hubspot/local-dev-lib/constants/environments");
|
|
16
|
-
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
17
16
|
const getAccountIdentifier_1 = require("@hubspot/local-dev-lib/config/getAccountIdentifier");
|
|
18
17
|
const commonOpts_1 = require("../lib/commonOpts");
|
|
19
18
|
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
20
19
|
const process_1 = require("../lib/process");
|
|
21
20
|
const index_1 = require("../lib/errorHandlers/index");
|
|
22
|
-
const lang_1 = require("../lib/lang");
|
|
23
21
|
const usageTracking_1 = require("../lib/usageTracking");
|
|
24
22
|
const promptUtils_1 = require("../lib/prompts/promptUtils");
|
|
25
23
|
const personalAccessKeyPrompt_1 = require("../lib/prompts/personalAccessKeyPrompt");
|
|
@@ -27,6 +25,9 @@ const accountNamePrompt_1 = require("../lib/prompts/accountNamePrompt");
|
|
|
27
25
|
const oauth_1 = require("../lib/oauth");
|
|
28
26
|
const exitCodes_1 = require("../lib/enums/exitCodes");
|
|
29
27
|
const ui_1 = require("../lib/ui");
|
|
28
|
+
const logger_1 = require("../lib/ui/logger");
|
|
29
|
+
const en_1 = require("../lang/en");
|
|
30
|
+
const parsing_1 = require("../lib/parsing");
|
|
30
31
|
const TRACKING_STATUS = {
|
|
31
32
|
STARTED: 'started',
|
|
32
33
|
ERROR: 'error',
|
|
@@ -61,9 +62,19 @@ const AUTH_TYPE_NAMES = {
|
|
|
61
62
|
[auth_1.OAUTH_AUTH_METHOD.value]: auth_1.OAUTH_AUTH_METHOD.name,
|
|
62
63
|
};
|
|
63
64
|
const command = 'init';
|
|
64
|
-
const describe =
|
|
65
|
+
const describe = en_1.commands.init.describe;
|
|
65
66
|
async function handler(args) {
|
|
66
|
-
const { authType: authTypeFlagValue, c: configFlagValue,
|
|
67
|
+
const { authType: authTypeFlagValue, c: configFlagValue, disableTracking, useHiddenConfig, userProvidedAccount, } = args;
|
|
68
|
+
let parsedUserProvidedAccountId;
|
|
69
|
+
try {
|
|
70
|
+
if (userProvidedAccount) {
|
|
71
|
+
parsedUserProvidedAccountId = (0, parsing_1.parseStringToNumber)(userProvidedAccount);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
logger_1.uiLogger.error(en_1.commands.init.errors.invalidAccountIdProvided);
|
|
76
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
77
|
+
}
|
|
67
78
|
const authType = (authTypeFlagValue && authTypeFlagValue.toLowerCase()) ||
|
|
68
79
|
auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value;
|
|
69
80
|
const configPath = (configFlagValue && path_1.default.join((0, path_2.getCwd)(), configFlagValue)) ||
|
|
@@ -76,28 +87,24 @@ async function handler(args) {
|
|
|
76
87
|
}
|
|
77
88
|
const env = args.qa ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD;
|
|
78
89
|
if ((0, config_1.configFileExists)(true)) {
|
|
79
|
-
logger_1.
|
|
80
|
-
accountAuthCommand: (0, ui_1.uiCommandReference)('hs account auth'),
|
|
81
|
-
}));
|
|
90
|
+
logger_1.uiLogger.error(en_1.commands.init.errors.globalConfigFileExists);
|
|
82
91
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
83
92
|
}
|
|
84
93
|
if (fs_extra_1.default.existsSync(configPath)) {
|
|
85
|
-
logger_1.
|
|
86
|
-
|
|
87
|
-
}));
|
|
88
|
-
logger_1.logger.info((0, lang_1.i18n)(`commands.init.logs.updateConfig`));
|
|
94
|
+
logger_1.uiLogger.error(en_1.commands.init.errors.configFileExists(configPath));
|
|
95
|
+
logger_1.uiLogger.info(en_1.commands.init.logs.updateConfig);
|
|
89
96
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
90
97
|
}
|
|
91
98
|
if (!disableTracking) {
|
|
92
|
-
await (0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.STARTED,
|
|
99
|
+
await (0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.STARTED, parsedUserProvidedAccountId);
|
|
93
100
|
}
|
|
94
101
|
const doesOtherConfigFileExist = (0, config_1.configFileExists)(!useHiddenConfig);
|
|
95
102
|
if (doesOtherConfigFileExist) {
|
|
96
103
|
const path = (0, config_1.getConfigPath)('', !useHiddenConfig);
|
|
97
|
-
logger_1.
|
|
104
|
+
logger_1.uiLogger.error(en_1.commands.init.errors.bothConfigFilesNotAllowed(path));
|
|
98
105
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
99
106
|
}
|
|
100
|
-
(0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.STARTED,
|
|
107
|
+
(0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.STARTED, parsedUserProvidedAccountId);
|
|
101
108
|
(0, config_1.createEmptyConfigFile)({ path: configPath }, useHiddenConfig);
|
|
102
109
|
//Needed to load deprecated config
|
|
103
110
|
(0, config_1.loadConfig)(configPath, args);
|
|
@@ -106,7 +113,7 @@ async function handler(args) {
|
|
|
106
113
|
let accountId;
|
|
107
114
|
let name;
|
|
108
115
|
if (authType === auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value) {
|
|
109
|
-
const personalAccessKeyResult = await personalAccessKeyConfigCreationFlow(env,
|
|
116
|
+
const personalAccessKeyResult = await personalAccessKeyConfigCreationFlow(env, parsedUserProvidedAccountId);
|
|
110
117
|
if (personalAccessKeyResult) {
|
|
111
118
|
accountId = (0, getAccountIdentifier_1.getAccountIdentifier)(personalAccessKeyResult);
|
|
112
119
|
name = personalAccessKeyResult.name;
|
|
@@ -124,14 +131,9 @@ async function handler(args) {
|
|
|
124
131
|
catch (e) {
|
|
125
132
|
(0, index_1.debugError)(e);
|
|
126
133
|
}
|
|
127
|
-
logger_1.
|
|
128
|
-
logger_1.
|
|
129
|
-
|
|
130
|
-
}));
|
|
131
|
-
logger_1.logger.success((0, lang_1.i18n)(`commands.init.success.configFileUpdated`, {
|
|
132
|
-
authType: AUTH_TYPE_NAMES[authType],
|
|
133
|
-
account: name || accountId,
|
|
134
|
-
}));
|
|
134
|
+
logger_1.uiLogger.log('');
|
|
135
|
+
logger_1.uiLogger.success(en_1.commands.init.success.configFileCreated(configPath));
|
|
136
|
+
logger_1.uiLogger.success(en_1.commands.init.success.configFileUpdated(AUTH_TYPE_NAMES[authType], name || accountId));
|
|
135
137
|
(0, ui_1.uiFeatureHighlight)([
|
|
136
138
|
'getStartedCommand',
|
|
137
139
|
'helpCommand',
|
|
@@ -146,7 +148,7 @@ async function handler(args) {
|
|
|
146
148
|
catch (err) {
|
|
147
149
|
(0, index_1.logError)(err);
|
|
148
150
|
if (!disableTracking) {
|
|
149
|
-
await (0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.ERROR,
|
|
151
|
+
await (0, usageTracking_1.trackAuthAction)('init', authType, TRACKING_STATUS.ERROR, parsedUserProvidedAccountId);
|
|
150
152
|
}
|
|
151
153
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
152
154
|
}
|
|
@@ -154,7 +156,7 @@ async function handler(args) {
|
|
|
154
156
|
function initBuilder(yargs) {
|
|
155
157
|
yargs.options({
|
|
156
158
|
'auth-type': {
|
|
157
|
-
describe:
|
|
159
|
+
describe: en_1.commands.init.options.authType.describe,
|
|
158
160
|
type: 'string',
|
|
159
161
|
choices: [
|
|
160
162
|
`${auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value}`,
|
|
@@ -163,7 +165,7 @@ function initBuilder(yargs) {
|
|
|
163
165
|
default: auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value,
|
|
164
166
|
},
|
|
165
167
|
account: {
|
|
166
|
-
describe:
|
|
168
|
+
describe: en_1.commands.init.options.account.describe,
|
|
167
169
|
type: 'string',
|
|
168
170
|
alias: 'a',
|
|
169
171
|
},
|
|
@@ -176,11 +178,7 @@ function initBuilder(yargs) {
|
|
|
176
178
|
yargs.conflicts('use-hidden-config', 'config');
|
|
177
179
|
return yargs;
|
|
178
180
|
}
|
|
179
|
-
const builder = (0, yargsUtils_1.makeYargsBuilder)(initBuilder, command, (0,
|
|
180
|
-
command: (0, ui_1.uiCommandReference)('hs auth'),
|
|
181
|
-
configName: config_2.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
182
|
-
authMethod: auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value,
|
|
183
|
-
}), {
|
|
181
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(initBuilder, command, en_1.commands.init.verboseDescribe(config_2.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME, (0, ui_1.uiCommandReference)('hs auth'), auth_1.PERSONAL_ACCESS_KEY_AUTH_METHOD.value), {
|
|
184
182
|
useGlobalOptions: true,
|
|
185
183
|
useConfigOptions: true,
|
|
186
184
|
useTestingOptions: true,
|
|
@@ -8,7 +8,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const usageTracking_1 = require("../../lib/usageTracking");
|
|
9
9
|
const lang_1 = require("../../lib/lang");
|
|
10
10
|
const selectPublicAppForMigrationPrompt_1 = require("../../lib/prompts/selectPublicAppForMigrationPrompt");
|
|
11
|
-
const
|
|
11
|
+
const projectNameAndDestPrompt_1 = require("../../lib/prompts/projectNameAndDestPrompt");
|
|
12
12
|
const polling_1 = require("../../lib/polling");
|
|
13
13
|
const errorHandlers_1 = require("../../lib/errorHandlers");
|
|
14
14
|
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
@@ -53,9 +53,9 @@ async function handler(args) {
|
|
|
53
53
|
});
|
|
54
54
|
appId = appIdResponse.appId;
|
|
55
55
|
}
|
|
56
|
-
const
|
|
57
|
-
projectName =
|
|
58
|
-
projectDest =
|
|
56
|
+
const projectNameAndDestPromptResponse = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(args);
|
|
57
|
+
projectName = projectNameAndDestPromptResponse.name;
|
|
58
|
+
projectDest = projectNameAndDestPromptResponse.dest;
|
|
59
59
|
}
|
|
60
60
|
catch (error) {
|
|
61
61
|
(0, errorHandlers_1.logError)(error, new errorHandlers_1.ApiErrorContext({ accountId: derivedAccountId }));
|
|
@@ -39,15 +39,15 @@ async function handler(args) {
|
|
|
39
39
|
(0, errorHandlers_1.logError)(error);
|
|
40
40
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
41
41
|
}
|
|
42
|
-
const { authType, distribution, repoConfig, projectContents,
|
|
42
|
+
const { authType, distribution, repoConfig, projectContents, selectProjectTemplatePromptResponse, projectNameAndDestPromptResponse, } = handleResult;
|
|
43
43
|
(0, usageTracking_1.trackCommandUsage)('project-create', {
|
|
44
|
-
type:
|
|
45
|
-
(
|
|
44
|
+
type: selectProjectTemplatePromptResponse.projectTemplate?.name ||
|
|
45
|
+
(selectProjectTemplatePromptResponse.componentTemplates || [])
|
|
46
46
|
// @ts-expect-error
|
|
47
47
|
.map((item) => item.label)
|
|
48
48
|
.join(','),
|
|
49
49
|
}, derivedAccountId);
|
|
50
|
-
const projectDest = path_1.default.resolve((0, path_2.getCwd)(),
|
|
50
|
+
const projectDest = path_1.default.resolve((0, path_2.getCwd)(), projectNameAndDestPromptResponse.dest);
|
|
51
51
|
const { projectConfig: existingProjectConfig, projectDir: existingProjectDir, } = await (0, config_1.getProjectConfig)(projectDest);
|
|
52
52
|
// Exit if the target destination is within an existing project
|
|
53
53
|
if (existingProjectConfig &&
|
|
@@ -57,7 +57,7 @@ async function handler(args) {
|
|
|
57
57
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
58
58
|
}
|
|
59
59
|
const components = (0, v3_2.generateComponentPaths)({
|
|
60
|
-
|
|
60
|
+
selectProjectTemplatePromptResponse,
|
|
61
61
|
platformVersion,
|
|
62
62
|
repoConfig,
|
|
63
63
|
projectContents,
|
|
@@ -66,7 +66,7 @@ async function handler(args) {
|
|
|
66
66
|
});
|
|
67
67
|
try {
|
|
68
68
|
await (0, github_1.cloneGithubRepo)(repo, projectDest, {
|
|
69
|
-
sourceDir:
|
|
69
|
+
sourceDir: selectProjectTemplatePromptResponse.projectTemplate?.path || components,
|
|
70
70
|
hideLogs: true,
|
|
71
71
|
branch: 'main',
|
|
72
72
|
});
|
|
@@ -80,15 +80,15 @@ async function handler(args) {
|
|
|
80
80
|
const parsedConfigFile = JSON.parse(fs_extra_1.default.readFileSync(projectConfigPath).toString());
|
|
81
81
|
(0, config_1.writeProjectConfig)(projectConfigPath, {
|
|
82
82
|
...parsedConfigFile,
|
|
83
|
-
name:
|
|
83
|
+
name: projectNameAndDestPromptResponse.name,
|
|
84
84
|
});
|
|
85
85
|
// If the template is 'no-template', we need to manually create a src directory
|
|
86
|
-
if (
|
|
86
|
+
if (selectProjectTemplatePromptResponse.projectTemplate?.name ===
|
|
87
87
|
legacy_1.EMPTY_PROJECT_TEMPLATE_NAME ||
|
|
88
88
|
projectContents === v3_1.EMPTY_PROJECT) {
|
|
89
89
|
fs_extra_1.default.ensureDirSync(path_1.default.join(projectDest, 'src'));
|
|
90
90
|
}
|
|
91
|
-
logger_1.uiLogger.success(en_1.commands.project.create.logs.success(
|
|
91
|
+
logger_1.uiLogger.success(en_1.commands.project.create.logs.success(projectNameAndDestPromptResponse.name, projectDest));
|
|
92
92
|
logger_1.uiLogger.log(en_1.commands.project.create.logs.welcomeMessage);
|
|
93
93
|
(0, ui_1.uiFeatureHighlight)([
|
|
94
94
|
'projectCommandTip',
|