@hubspot/cli 7.7.16-experimental.0 → 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.
Files changed (106) hide show
  1. package/bin/cli.js +4 -0
  2. package/bin/hs +1 -1
  3. package/commands/account/auth.js +3 -3
  4. package/commands/app/install.d.ts +8 -0
  5. package/commands/app/install.js +127 -0
  6. package/commands/app.js +6 -1
  7. package/commands/auth.js +23 -25
  8. package/commands/getStarted.d.ts +9 -0
  9. package/commands/getStarted.js +274 -0
  10. package/commands/init.js +35 -32
  11. package/commands/mcp/setup.d.ts +2 -2
  12. package/commands/mcp/setup.js +2 -0
  13. package/commands/mcp/start.d.ts +2 -2
  14. package/commands/mcp/start.js +3 -1
  15. package/commands/project/cloneApp.js +4 -4
  16. package/commands/project/create.js +9 -9
  17. package/commands/project/deploy.d.ts +1 -0
  18. package/commands/project/deploy.js +29 -3
  19. package/commands/project/dev/deprecatedFlow.js +4 -4
  20. package/commands/project/dev/index.js +5 -5
  21. package/commands/project/dev/unifiedFlow.js +8 -0
  22. package/commands/project/upload.d.ts +2 -2
  23. package/commands/project/upload.js +18 -23
  24. package/commands/project/validate.d.ts +6 -0
  25. package/commands/project/validate.js +82 -0
  26. package/commands/project.js +2 -0
  27. package/commands/sandbox/delete.js +5 -5
  28. package/commands/testAccount/create.d.ts +6 -0
  29. package/commands/testAccount/create.js +160 -0
  30. package/commands/testAccount/createConfig.d.ts +10 -0
  31. package/commands/testAccount/createConfig.js +98 -0
  32. package/commands/testAccount/delete.d.ts +6 -0
  33. package/commands/testAccount/delete.js +48 -0
  34. package/commands/testAccount.d.ts +3 -0
  35. package/commands/testAccount.js +28 -0
  36. package/lang/en.d.ts +201 -35
  37. package/lang/en.js +201 -38
  38. package/lang/en.lyaml +9 -14
  39. package/lib/accountTypes.d.ts +1 -0
  40. package/lib/accountTypes.js +20 -9
  41. package/lib/app/migrate.js +15 -3
  42. package/lib/app/migrate_legacy.js +2 -3
  43. package/lib/app/urls.d.ts +1 -1
  44. package/lib/commonOpts.d.ts +2 -0
  45. package/lib/commonOpts.js +21 -9
  46. package/lib/constants.d.ts +5 -0
  47. package/lib/constants.js +6 -1
  48. package/lib/doctor/Doctor.js +1 -1
  49. package/lib/errorHandlers/index.js +7 -0
  50. package/lib/mcp/setup.d.ts +9 -0
  51. package/lib/mcp/setup.js +23 -21
  52. package/lib/middleware/__test__/configMiddleware.test.js +2 -2
  53. package/lib/middleware/configMiddleware.js +10 -2
  54. package/lib/parsing.d.ts +1 -0
  55. package/lib/parsing.js +11 -0
  56. package/lib/polling.d.ts +1 -1
  57. package/lib/polling.js +11 -1
  58. package/lib/projectProfiles.d.ts +1 -0
  59. package/lib/projectProfiles.js +18 -0
  60. package/lib/projects/add/v3AddComponent.js +4 -0
  61. package/lib/projects/buildAndDeploy.js +1 -1
  62. package/lib/projects/create/index.d.ts +3 -2
  63. package/lib/projects/create/index.js +11 -5
  64. package/lib/projects/create/v3.d.ts +3 -3
  65. package/lib/projects/create/v3.js +2 -2
  66. package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -0
  67. package/lib/projects/localDev/AppDevModeInterface.js +46 -17
  68. package/lib/projects/localDev/LocalDevManager.js +1 -1
  69. package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
  70. package/lib/projects/localDev/LocalDevProcess.js +16 -12
  71. package/lib/projects/localDev/LocalDevState.d.ts +10 -5
  72. package/lib/projects/localDev/LocalDevState.js +18 -20
  73. package/lib/projects/localDev/LocalDevWatcher.js +1 -1
  74. package/lib/projects/structure.d.ts +2 -2
  75. package/lib/projects/upload.d.ts +4 -0
  76. package/lib/projects/upload.js +57 -22
  77. package/lib/projects/urls.d.ts +2 -0
  78. package/lib/projects/urls.js +10 -0
  79. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +17 -0
  80. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +96 -0
  81. package/lib/prompts/installAppPrompt.d.ts +2 -1
  82. package/lib/prompts/installAppPrompt.js +12 -2
  83. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  84. package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
  85. package/lib/prompts/projectNameAndDestPrompt.js +60 -0
  86. package/lib/prompts/promptUtils.d.ts +1 -0
  87. package/lib/prompts/promptUtils.js +2 -0
  88. package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
  89. package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
  90. package/lib/ui/logger.d.ts +1 -0
  91. package/lib/ui/logger.js +1 -0
  92. package/lib/validation.d.ts +1 -1
  93. package/lib/validation.js +4 -4
  94. package/lib/yargsUtils.d.ts +1 -0
  95. package/lib/yargsUtils.js +3 -0
  96. package/mcp-server/tools/index.js +2 -0
  97. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
  98. package/mcp-server/tools/project/CreateProjectTool.js +5 -1
  99. package/mcp-server/tools/project/DeployProject.js +1 -1
  100. package/mcp-server/tools/project/UploadProjectTools.js +1 -1
  101. package/mcp-server/tools/project/ValidateProjectTool.d.ts +17 -0
  102. package/mcp-server/tools/project/ValidateProjectTool.js +35 -0
  103. package/package.json +10 -9
  104. package/types/LocalDev.d.ts +2 -0
  105. package/types/Yargs.d.ts +5 -1
  106. package/lib/prompts/createProjectPrompt.d.ts +0 -28
package/bin/cli.js CHANGED
@@ -44,6 +44,8 @@ const feedback_1 = __importDefault(require("../commands/feedback"));
44
44
  const doctor_1 = __importDefault(require("../commands/doctor"));
45
45
  const completion_1 = __importDefault(require("../commands/completion"));
46
46
  const app_1 = __importDefault(require("../commands/app"));
47
+ const testAccount_1 = __importDefault(require("../commands/testAccount"));
48
+ const getStarted_1 = __importDefault(require("../commands/getStarted"));
47
49
  const mcp_1 = __importDefault(require("../commands/mcp"));
48
50
  function getTerminalWidth() {
49
51
  const width = yargs_1.default.terminalWidth();
@@ -123,6 +125,8 @@ const argv = yargs_1.default
123
125
  .command(doctor_1.default)
124
126
  .command(completion_1.default)
125
127
  .command(app_1.default)
128
+ .command(testAccount_1.default)
129
+ .command(getStarted_1.default)
126
130
  .command(mcp_1.default)
127
131
  .help()
128
132
  .alias('h', 'help')
package/bin/hs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- require('./silenceErrors')
3
+ require('./silenceErrors');
4
4
 
5
5
  require('./cli');
@@ -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 { providedAccountId, disableTracking, personalAccessKey: providedPersonalAccessKey, } = args;
101
+ const { disableTracking, personalAccessKey: providedPersonalAccessKey, derivedAccountId, } = args;
102
102
  if (!disableTracking) {
103
- (0, usageTracking_1.trackCommandUsage)('account-auth', {}, providedAccountId);
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, providedAccountId);
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.command(migrate_1.default).command(secret_1.default).demandCommand(1, '');
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 = (0, lang_1.i18n)('commands.auth.describe');
35
+ const describe = en_1.commands.auth.describe;
36
36
  async function handler(args) {
37
- const { authType: authTypeFlagValue, config: configFlagValue, qa, providedAccountId, personalAccessKey: providedPersonalAccessKey, } = args;
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.logger.error((0, lang_1.i18n)(`commands.auth.errors.globalConfigFileExists`, {
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, providedAccountId);
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: providedAccountId,
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.logger.error((0, lang_1.i18n)('commands.auth.errors.unsupportedAuthType', {
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, providedAccountId);
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.logger.success((0, lang_1.i18n)('commands.auth.success.configFileUpdated', {
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: (0, lang_1.i18n)('commands.auth.options.authType.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: (0, lang_1.i18n)('commands.auth.options.account.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, (0, lang_1.i18n)('commands.auth.verboseDescribe', {
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,
@@ -0,0 +1,9 @@
1
+ import { AccountArgs, YargsCommandModule, CommonArgs, ConfigArgs, EnvironmentArgs } from '../types/Yargs';
2
+ export declare const command = "get-started";
3
+ export declare const describe: undefined;
4
+ type GetStartedArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
5
+ name?: string;
6
+ dest?: string;
7
+ };
8
+ declare const getStartedCommand: YargsCommandModule<unknown, GetStartedArgs>;
9
+ export default getStartedCommand;
@@ -0,0 +1,274 @@
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.describe = exports.command = void 0;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const open_1 = __importDefault(require("open"));
10
+ const path_2 = require("@hubspot/local-dev-lib/path");
11
+ const github_1 = require("@hubspot/local-dev-lib/github");
12
+ const en_1 = require("../lang/en");
13
+ const usageTracking_1 = require("../lib/usageTracking");
14
+ const exitCodes_1 = require("../lib/enums/exitCodes");
15
+ const yargsUtils_1 = require("../lib/yargsUtils");
16
+ const promptUtils_1 = require("../lib/prompts/promptUtils");
17
+ const projectNameAndDestPrompt_1 = require("../lib/prompts/projectNameAndDestPrompt");
18
+ const ui_1 = require("../lib/ui");
19
+ const logger_1 = require("../lib/ui/logger");
20
+ const errorHandlers_1 = require("../lib/errorHandlers");
21
+ const upload_1 = require("../lib/projects/upload");
22
+ const constants_1 = require("../lib/constants");
23
+ const config_1 = require("../lib/projects/config");
24
+ const dependencyManagement_1 = require("../lib/dependencyManagement");
25
+ const buildAndDeploy_1 = require("../lib/projects/buildAndDeploy");
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");
31
+ exports.command = 'get-started';
32
+ exports.describe = undefined;
33
+ async function handler(args) {
34
+ const { derivedAccountId } = args;
35
+ const env = (0, config_2.getEnv)(derivedAccountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD;
36
+ // TODO: Put this in constants.ts once we have a defined place for the template before INBOUND
37
+ const templateSource = 'robrown-hubspot/hubspot-project-components-ua-app-objects-beta';
38
+ (0, usageTracking_1.trackCommandUsage)('get-started', {}, derivedAccountId);
39
+ (0, ui_1.uiInfoSection)(en_1.commands.getStarted.startTitle, () => {
40
+ logger_1.uiLogger.log(en_1.commands.getStarted.startDescription);
41
+ });
42
+ const { default: selectedOption } = await (0, promptUtils_1.promptUser)([
43
+ {
44
+ type: 'list',
45
+ name: 'default',
46
+ message: en_1.commands.getStarted.prompts.selectOption,
47
+ choices: [
48
+ {
49
+ name: en_1.commands.getStarted.prompts.options.app,
50
+ value: constants_1.GET_STARTED_OPTIONS.APP,
51
+ },
52
+ {
53
+ name: en_1.commands.getStarted.prompts.options.cms,
54
+ value: constants_1.GET_STARTED_OPTIONS.CMS,
55
+ },
56
+ ],
57
+ default: constants_1.GET_STARTED_OPTIONS.APP,
58
+ },
59
+ ]);
60
+ if (selectedOption === constants_1.GET_STARTED_OPTIONS.CMS) {
61
+ logger_1.uiLogger.log(' ');
62
+ logger_1.uiLogger.log(en_1.commands.getStarted.designManager);
63
+ if (process.env.BROWSER !== 'none') {
64
+ logger_1.uiLogger.log(' ');
65
+ const { shouldOpen } = await (0, promptUtils_1.promptUser)([
66
+ {
67
+ name: 'shouldOpen',
68
+ type: 'confirm',
69
+ message: en_1.commands.getStarted.openDesignManagerPrompt,
70
+ },
71
+ ]);
72
+ if (shouldOpen) {
73
+ logger_1.uiLogger.log('');
74
+ (0, links_1.openLink)(derivedAccountId, 'design-manager');
75
+ }
76
+ }
77
+ process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
78
+ }
79
+ else {
80
+ logger_1.uiLogger.log(' ');
81
+ logger_1.uiLogger.log(en_1.commands.getStarted.logs.appSelected);
82
+ // 1. Fetch project templates
83
+ let latestRepoReleaseTag;
84
+ const { dest, name } = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(args);
85
+ // Specific template for get-started command
86
+ const projectTemplate = {
87
+ name: 'private-app-get-started-template',
88
+ label: 'CRM getting started project with private apps',
89
+ path: 'projects/private-app-get-started-template',
90
+ };
91
+ // 3. Create the project files
92
+ const projectDest = path_1.default.resolve((0, path_2.getCwd)(), dest);
93
+ const { projectConfig: existingProjectConfig, projectDir: existingProjectDir, } = await (0, config_1.getProjectConfig)(projectDest);
94
+ if (existingProjectConfig &&
95
+ existingProjectDir &&
96
+ projectDest.startsWith(existingProjectDir)) {
97
+ logger_1.uiLogger.log(' ');
98
+ logger_1.uiLogger.error(en_1.commands.project.create.errors.cannotNestProjects(existingProjectDir));
99
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
100
+ }
101
+ const repo = templateSource || constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
102
+ // 4. Clone the project template from GitHub
103
+ // This is temporary until we have the UA template in the main repo
104
+ try {
105
+ await (0, github_1.cloneGithubRepo)(repo, projectDest, {
106
+ sourceDir: projectTemplate.path,
107
+ tag: latestRepoReleaseTag,
108
+ hideLogs: true,
109
+ });
110
+ }
111
+ catch (err) {
112
+ (0, errorHandlers_1.debugError)(err);
113
+ logger_1.uiLogger.log(' ');
114
+ logger_1.uiLogger.error(en_1.commands.project.create.errors.failedToDownloadProject);
115
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
116
+ }
117
+ const projectConfigPath = path_1.default.join(projectDest, constants_1.PROJECT_CONFIG_FILE);
118
+ const parsedConfigFile = JSON.parse(fs_extra_1.default.readFileSync(projectConfigPath).toString());
119
+ (0, config_1.writeProjectConfig)(projectConfigPath, {
120
+ ...parsedConfigFile,
121
+ name,
122
+ });
123
+ logger_1.uiLogger.log(' ');
124
+ logger_1.uiLogger.success(en_1.commands.project.create.logs.success(name, projectDest));
125
+ logger_1.uiLogger.log(' ');
126
+ logger_1.uiLogger.log(en_1.commands.getStarted.prompts.projectCreated.title);
127
+ logger_1.uiLogger.log(' ');
128
+ logger_1.uiLogger.log(en_1.commands.getStarted.prompts.projectCreated.description);
129
+ logger_1.uiLogger.log(' ');
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
168
+ const { shouldUpload } = await (0, promptUtils_1.promptUser)([
169
+ {
170
+ type: 'confirm',
171
+ name: 'shouldUpload',
172
+ message: en_1.commands.getStarted.prompts.uploadProject,
173
+ default: true,
174
+ },
175
+ ]);
176
+ if (shouldUpload) {
177
+ try {
178
+ // Get the project config for the newly created project
179
+ const { projectConfig: newProjectConfig, projectDir: newProjectDir } = await (0, config_1.getProjectConfig)(projectDest);
180
+ if (!newProjectConfig || !newProjectDir) {
181
+ logger_1.uiLogger.log(' ');
182
+ logger_1.uiLogger.error(en_1.commands.getStarted.errors.configFileNotFound);
183
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
184
+ }
185
+ (0, config_1.validateProjectConfig)(newProjectConfig, newProjectDir);
186
+ const targetAccountId = derivedAccountId;
187
+ logger_1.uiLogger.log(' ');
188
+ logger_1.uiLogger.log(en_1.commands.getStarted.logs.uploadingProject);
189
+ logger_1.uiLogger.log(' ');
190
+ const { result, uploadError } = await (0, upload_1.handleProjectUpload)({
191
+ accountId: targetAccountId,
192
+ projectConfig: newProjectConfig,
193
+ projectDir: newProjectDir,
194
+ callbackFunc: buildAndDeploy_1.pollProjectBuildAndDeploy,
195
+ uploadMessage: 'Initial upload from get-started command',
196
+ forceCreate: true, // Auto-create project on HubSpot
197
+ isUploadCommand: false,
198
+ sendIR: (0, buildAndDeploy_1.useV3Api)(newProjectConfig.platformVersion),
199
+ skipValidation: false,
200
+ });
201
+ if (uploadError) {
202
+ logger_1.uiLogger.log(' ');
203
+ logger_1.uiLogger.error(en_1.commands.getStarted.errors.uploadFailed);
204
+ (0, errorHandlers_1.debugError)(uploadError);
205
+ }
206
+ else if (result) {
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];
210
+ if (process.env.BROWSER !== 'none') {
211
+ logger_1.uiLogger.log(' ');
212
+ logger_1.uiLogger.log(en_1.commands.getStarted.developerOverviewBrowserOpenPrep);
213
+ logger_1.uiLogger.log(' ');
214
+ const { shouldOpenOverview } = await (0, promptUtils_1.promptUser)([
215
+ {
216
+ name: 'shouldOpenOverview',
217
+ type: 'confirm',
218
+ message: en_1.commands.getStarted.openInstallUrl,
219
+ },
220
+ ]);
221
+ if (shouldOpenOverview) {
222
+ (0, open_1.default)((0, urls_1.getStaticAuthAppInstallUrl)({
223
+ targetAccountId: derivedAccountId,
224
+ env: env,
225
+ appId: lastCreatedApp.id,
226
+ }), { url: true });
227
+ logger_1.uiLogger.log(' ');
228
+ logger_1.uiLogger.success(en_1.commands.getStarted.openedDeveloperOverview);
229
+ }
230
+ }
231
+ logger_1.uiLogger.log(' ');
232
+ (0, ui_1.uiFeatureHighlight)(['projectDevCommand']);
233
+ }
234
+ }
235
+ catch (err) {
236
+ logger_1.uiLogger.log(' ');
237
+ logger_1.uiLogger.error(en_1.commands.getStarted.errors.uploadFailed);
238
+ (0, errorHandlers_1.debugError)(err);
239
+ process.exit(exitCodes_1.EXIT_CODES.ERROR);
240
+ }
241
+ }
242
+ }
243
+ process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
244
+ }
245
+ function getStartedBuilder(yargs) {
246
+ yargs.options({
247
+ name: {
248
+ describe: en_1.commands.getStarted.options.name.describe,
249
+ type: 'string',
250
+ },
251
+ dest: {
252
+ describe: en_1.commands.getStarted.options.dest.describe,
253
+ type: 'string',
254
+ },
255
+ 'template-source': {
256
+ describe: en_1.commands.getStarted.options.templateSource.describe,
257
+ type: 'string',
258
+ },
259
+ });
260
+ return yargs;
261
+ }
262
+ const builder = (0, yargsUtils_1.makeYargsBuilder)(getStartedBuilder, exports.command, en_1.commands.getStarted.verboseDescribe, {
263
+ useGlobalOptions: true,
264
+ useAccountOptions: true,
265
+ useConfigOptions: true,
266
+ useEnvironmentOptions: true,
267
+ });
268
+ const getStartedCommand = {
269
+ command: exports.command,
270
+ describe: exports.describe,
271
+ handler,
272
+ builder,
273
+ };
274
+ exports.default = getStartedCommand;