@hubspot/cli 6.4.0 → 7.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/bin/cli.js +110 -16
  2. package/bin/hs +2 -0
  3. package/bin/hscms +2 -0
  4. package/bin/silenceErrors.d.ts +2 -0
  5. package/bin/silenceErrors.js +12 -0
  6. package/commands/{accounts → account}/clean.js +10 -11
  7. package/commands/{accounts → account}/info.js +10 -16
  8. package/commands/{accounts → account}/list.js +16 -16
  9. package/commands/{accounts → account}/remove.js +12 -15
  10. package/commands/{accounts → account}/rename.js +4 -7
  11. package/commands/{accounts → account}/use.js +8 -14
  12. package/commands/account.js +26 -0
  13. package/commands/auth.js +30 -24
  14. package/commands/cms/getReactModule.js +70 -0
  15. package/commands/cms/lighthouseScore.js +19 -21
  16. package/commands/cms.js +4 -3
  17. package/commands/completion.js +22 -0
  18. package/commands/config/set.js +22 -24
  19. package/commands/config.js +2 -2
  20. package/commands/create.js +6 -3
  21. package/commands/customObject/create.js +19 -15
  22. package/commands/customObject/schema/create.js +15 -16
  23. package/commands/customObject/schema/delete.js +29 -11
  24. package/commands/customObject/schema/fetch-all.js +14 -11
  25. package/commands/customObject/schema/fetch.js +22 -14
  26. package/commands/customObject/schema/list.js +3 -6
  27. package/commands/customObject/schema/update.js +28 -18
  28. package/commands/customObject/schema.js +1 -1
  29. package/commands/customObject.js +3 -4
  30. package/commands/doctor.js +4 -2
  31. package/commands/feedback.js +2 -0
  32. package/commands/fetch.js +13 -13
  33. package/commands/filemanager/fetch.js +6 -7
  34. package/commands/filemanager/upload.js +10 -12
  35. package/commands/filemanager.js +1 -8
  36. package/commands/{functions → function}/deploy.js +13 -13
  37. package/commands/{functions → function}/list.js +7 -9
  38. package/commands/{functions → function}/server.js +5 -8
  39. package/commands/function.js +16 -0
  40. package/commands/hubdb/clear.js +14 -10
  41. package/commands/hubdb/create.js +37 -13
  42. package/commands/hubdb/delete.js +31 -10
  43. package/commands/hubdb/fetch.js +14 -9
  44. package/commands/hubdb.js +2 -3
  45. package/commands/init.js +37 -14
  46. package/commands/lint.js +6 -7
  47. package/commands/list.js +5 -7
  48. package/commands/logs.js +24 -15
  49. package/commands/module/marketplace-validate.js +6 -9
  50. package/commands/module.js +2 -1
  51. package/commands/mv.js +11 -13
  52. package/commands/open.js +11 -10
  53. package/commands/project/add.js +2 -5
  54. package/commands/project/cloneApp.js +28 -32
  55. package/commands/project/create.js +8 -10
  56. package/commands/project/deploy.js +19 -16
  57. package/commands/project/dev.js +17 -18
  58. package/commands/project/download.js +18 -15
  59. package/commands/project/listBuilds.js +36 -32
  60. package/commands/project/logs.js +6 -8
  61. package/commands/project/migrateApp.js +27 -27
  62. package/commands/project/open.js +9 -11
  63. package/commands/project/upload.js +30 -32
  64. package/commands/project/watch.js +17 -24
  65. package/commands/project.js +3 -4
  66. package/commands/remove.js +14 -13
  67. package/commands/sandbox/create.js +12 -15
  68. package/commands/sandbox/delete.js +19 -20
  69. package/commands/sandbox.js +4 -8
  70. package/commands/{secrets → secret}/addSecret.js +25 -12
  71. package/commands/secret/deleteSecret.js +71 -0
  72. package/commands/{secrets → secret}/listSecrets.js +7 -9
  73. package/commands/{secrets → secret}/updateSecret.js +21 -13
  74. package/commands/secret.js +22 -0
  75. package/commands/theme/generate-selectors.js +8 -8
  76. package/commands/theme/marketplace-validate.js +10 -13
  77. package/commands/theme/preview.js +7 -10
  78. package/commands/theme.js +3 -1
  79. package/commands/upload.js +32 -26
  80. package/commands/watch.js +19 -20
  81. package/lang/en.lyaml +200 -126
  82. package/lib/DevServerManager.js +1 -1
  83. package/lib/LocalDevManager.js +4 -4
  84. package/lib/buildAccount.js +5 -11
  85. package/lib/commonOpts.d.ts +15 -6
  86. package/lib/commonOpts.js +53 -39
  87. package/lib/configOptions.d.ts +13 -1
  88. package/lib/configOptions.js +54 -57
  89. package/lib/constants.d.ts +1 -4
  90. package/lib/dependencyManagement.d.ts +4 -1
  91. package/lib/dependencyManagement.js +2 -2
  92. package/lib/developerTestAccounts.d.ts +5 -1
  93. package/lib/developerTestAccounts.js +45 -39
  94. package/lib/doctor/DiagnosticInfoBuilder.js +8 -4
  95. package/lib/doctor/Doctor.js +11 -6
  96. package/lib/generateSelectors.d.ts +19 -0
  97. package/lib/generateSelectors.js +23 -23
  98. package/lib/localDev.js +3 -2
  99. package/lib/marketplaceValidate.d.ts +6 -1
  100. package/lib/marketplaceValidate.js +76 -77
  101. package/lib/oauth.d.ts +2 -1
  102. package/lib/oauth.js +49 -37
  103. package/lib/polling.d.ts +8 -0
  104. package/lib/polling.js +9 -12
  105. package/lib/projects/ProjectLogsManager.d.ts +20 -0
  106. package/lib/projects/ProjectLogsManager.js +105 -0
  107. package/lib/projects/buildAndDeploy.d.ts +16 -0
  108. package/lib/projects/buildAndDeploy.js +342 -0
  109. package/lib/projects/index.d.ts +24 -0
  110. package/lib/projects/index.js +256 -0
  111. package/lib/projects/structure.d.ts +78 -0
  112. package/lib/projects/structure.js +151 -0
  113. package/lib/projects/upload.d.ts +8 -0
  114. package/lib/projects/upload.js +107 -0
  115. package/lib/projects/urls.d.ts +4 -0
  116. package/lib/projects/urls.js +27 -0
  117. package/lib/{projectsWatch.js → projects/watch.js} +3 -3
  118. package/lib/prompts/accountNamePrompt.d.ts +11 -0
  119. package/lib/prompts/accountNamePrompt.js +45 -46
  120. package/lib/prompts/accountsPrompt.d.ts +1 -1
  121. package/lib/prompts/accountsPrompt.js +21 -19
  122. package/lib/prompts/cmsFieldPrompt.d.ts +1 -1
  123. package/lib/prompts/cmsFieldPrompt.js +23 -24
  124. package/lib/prompts/createApiSamplePrompt.d.ts +17 -0
  125. package/lib/prompts/createApiSamplePrompt.js +47 -44
  126. package/lib/prompts/createFunctionPrompt.d.ts +7 -0
  127. package/lib/prompts/createFunctionPrompt.js +17 -20
  128. package/lib/prompts/createModulePrompt.d.ts +8 -0
  129. package/lib/prompts/createModulePrompt.js +29 -17
  130. package/lib/prompts/createProjectPrompt.d.ts +13 -0
  131. package/lib/prompts/createProjectPrompt.js +48 -49
  132. package/lib/prompts/createTemplatePrompt.d.ts +8 -0
  133. package/lib/prompts/createTemplatePrompt.js +15 -17
  134. package/lib/prompts/downloadProjectPrompt.d.ts +8 -0
  135. package/lib/prompts/downloadProjectPrompt.js +25 -23
  136. package/lib/prompts/installPublicAppPrompt.d.ts +1 -1
  137. package/lib/prompts/installPublicAppPrompt.js +21 -19
  138. package/lib/prompts/personalAccessKeyPrompt.d.ts +28 -0
  139. package/lib/prompts/personalAccessKeyPrompt.js +46 -52
  140. package/lib/prompts/previewPrompt.d.ts +14 -0
  141. package/lib/prompts/previewPrompt.js +24 -24
  142. package/lib/prompts/projectAddPrompt.d.ts +9 -0
  143. package/lib/prompts/projectAddPrompt.js +11 -14
  144. package/lib/prompts/projectDevTargetAccountPrompt.d.ts +6 -1
  145. package/lib/prompts/projectDevTargetAccountPrompt.js +87 -69
  146. package/lib/prompts/projectsLogsPrompt.d.ts +11 -0
  147. package/lib/prompts/projectsLogsPrompt.js +8 -11
  148. package/lib/prompts/promptUtils.d.ts +7 -6
  149. package/lib/prompts/promptUtils.js +21 -8
  150. package/lib/prompts/sandboxesPrompt.d.ts +8 -0
  151. package/lib/prompts/sandboxesPrompt.js +43 -45
  152. package/lib/prompts/secretPrompt.d.ts +12 -0
  153. package/lib/prompts/secretPrompt.js +32 -19
  154. package/lib/prompts/selectHubDBTablePrompt.d.ts +12 -0
  155. package/lib/prompts/selectHubDBTablePrompt.js +69 -0
  156. package/lib/prompts/selectPublicAppPrompt.d.ts +8 -0
  157. package/lib/prompts/selectPublicAppPrompt.js +28 -27
  158. package/lib/prompts/setAsDefaultAccountPrompt.d.ts +1 -1
  159. package/lib/prompts/setAsDefaultAccountPrompt.js +12 -14
  160. package/lib/prompts/uploadPrompt.d.ts +8 -0
  161. package/lib/prompts/uploadPrompt.js +18 -18
  162. package/lib/sandboxSync.js +5 -2
  163. package/lib/sandboxes.js +12 -7
  164. package/lib/ui/index.d.ts +1 -1
  165. package/lib/ui/index.js +1 -1
  166. package/lib/usageTracking.d.ts +21 -2
  167. package/lib/usageTracking.js +53 -81
  168. package/lib/validation.d.ts +11 -1
  169. package/lib/validation.js +98 -91
  170. package/package.json +12 -6
  171. package/types/Projects.d.ts +43 -0
  172. package/types/Projects.js +2 -0
  173. package/types/Prompts.d.ts +25 -0
  174. package/types/Prompts.js +2 -0
  175. package/commands/accounts.js +0 -30
  176. package/commands/cms/reactModules.js +0 -60
  177. package/commands/functions.js +0 -24
  178. package/commands/secrets/deleteSecret.js +0 -46
  179. package/commands/secrets.js +0 -23
  180. package/lib/ProjectLogsManager.js +0 -91
  181. package/lib/projectStructure.js +0 -116
  182. package/lib/projects.d.ts +0 -4
  183. package/lib/projects.js +0 -681
  184. package/lib/projectsWatch.d.ts +0 -1
  185. package/lib/prompts/cleanUploadPrompt.d.ts +0 -1
  186. package/lib/prompts/cleanUploadPrompt.js +0 -20
  187. /package/commands/{accounts → account}/clean.d.ts +0 -0
  188. /package/commands/{accounts → account}/info.d.ts +0 -0
  189. /package/commands/{accounts → account}/list.d.ts +0 -0
  190. /package/commands/{accounts → account}/remove.d.ts +0 -0
  191. /package/commands/{accounts → account}/rename.d.ts +0 -0
  192. /package/commands/{accounts → account}/use.d.ts +0 -0
  193. /package/commands/{accounts.d.ts → account.d.ts} +0 -0
  194. /package/commands/cms/{reactModules.d.ts → getReactModule.d.ts} +0 -0
  195. /package/commands/{functions.d.ts → completion.d.ts} +0 -0
  196. /package/commands/{functions/list.d.ts → function/deploy.d.ts} +0 -0
  197. /package/commands/{functions/server.d.ts → function/list.d.ts} +0 -0
  198. /package/commands/{secrets.d.ts → function/server.d.ts} +0 -0
  199. /package/commands/{functions/deploy.d.ts → function.d.ts} +0 -0
  200. /package/commands/{secrets/deleteSecret.d.ts → secret/addSecret.d.ts} +0 -0
  201. /package/commands/{secrets/listSecrets.d.ts → secret/deleteSecret.d.ts} +0 -0
  202. /package/commands/{secrets/updateSecret.d.ts → secret/listSecrets.d.ts} +0 -0
  203. /package/{lib/ProjectLogsManager.d.ts → commands/secret/updateSecret.d.ts} +0 -0
  204. /package/commands/{secrets/addSecret.d.ts → secret.d.ts} +0 -0
  205. /package/lib/{projectStructure.d.ts → projects/watch.d.ts} +0 -0
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProjectLogsManager = void 0;
4
+ const index_1 = require("./index");
5
+ const projects_1 = require("@hubspot/local-dev-lib/api/projects");
6
+ const logger_1 = require("@hubspot/local-dev-lib/logger");
7
+ const lang_1 = require("../lang");
8
+ const ui_1 = require("../ui");
9
+ const i18nKey = 'commands.project.subcommands.logs';
10
+ class _ProjectLogsManager {
11
+ projectName;
12
+ projectId;
13
+ accountId;
14
+ functions;
15
+ selectedFunction;
16
+ functionName;
17
+ appId;
18
+ isPublicFunction;
19
+ endpointName;
20
+ reset() {
21
+ this.projectName = undefined;
22
+ this.projectId = undefined;
23
+ this.accountId = undefined;
24
+ this.functions = [];
25
+ this.selectedFunction = undefined;
26
+ this.functionName = undefined;
27
+ this.appId = undefined;
28
+ this.isPublicFunction = undefined;
29
+ this.endpointName = undefined;
30
+ }
31
+ constructor() {
32
+ this.functions = [];
33
+ }
34
+ async init(accountId) {
35
+ const { projectConfig } = await (0, index_1.getProjectConfig)();
36
+ if (!projectConfig || !projectConfig.name) {
37
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.noProjectConfig`));
38
+ }
39
+ const { name: projectName } = projectConfig;
40
+ this.projectName = projectName;
41
+ this.accountId = accountId;
42
+ this.functions = [];
43
+ const { project } = await (0, index_1.ensureProjectExists)(this.accountId, this.projectName, {
44
+ allowCreate: false,
45
+ });
46
+ if (!project ||
47
+ !project.deployedBuild ||
48
+ !project.deployedBuild.subbuildStatuses) {
49
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.failedToFetchProjectDetails`));
50
+ }
51
+ this.projectId = project.id;
52
+ await this.fetchFunctionDetails();
53
+ }
54
+ async fetchFunctionDetails() {
55
+ if (!this.projectId) {
56
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.noProjectConfig`));
57
+ }
58
+ if (!this.accountId) {
59
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.errors.projectLogsManagerNotInitialized`));
60
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.generic`));
61
+ }
62
+ const { data: { topLevelComponentMetadata }, } = await (0, projects_1.fetchProjectComponentsMetadata)(this.accountId, this.projectId);
63
+ const apps = topLevelComponentMetadata.filter(componentMetadata => {
64
+ const { type } = componentMetadata;
65
+ return type && type.name === 'PRIVATE_APP';
66
+ });
67
+ apps.forEach(app => {
68
+ this.functions.push(
69
+ // If component type is APP_FUNCTION, we can safely cast as AppFunctionComponentMetadata
70
+ ...app.featureComponents.filter(component => component.type.name === 'APP_FUNCTION'));
71
+ });
72
+ if (this.functions.length === 0) {
73
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.noFunctionsInProject`, {
74
+ link: (0, ui_1.uiLink)((0, lang_1.i18n)(`${i18nKey}.errors.noFunctionsLinkText`), 'https://developers.hubspot.com/docs/platform/serverless-functions'),
75
+ }));
76
+ }
77
+ }
78
+ getFunctionNames() {
79
+ return this.functions.map(serverlessFunction => serverlessFunction.componentName);
80
+ }
81
+ setFunction(functionName) {
82
+ if (!(this.functions.length > 0)) {
83
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.noFunctionsInProject`, {
84
+ link: (0, ui_1.uiLink)((0, lang_1.i18n)(`${i18nKey}.errors.noFunctionsLinkText`), 'https://developers.hubspot.com/docs/platform/serverless-functions'),
85
+ }));
86
+ }
87
+ this.selectedFunction = this.functions.find(serverlessFunction => serverlessFunction.componentName === functionName);
88
+ if (!this.selectedFunction) {
89
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.noFunctionWithName`, { name: functionName }));
90
+ }
91
+ this.functionName = functionName;
92
+ if (!this.selectedFunction.deployOutput) {
93
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.functionNotDeployed`, { name: functionName }));
94
+ }
95
+ this.appId = this.selectedFunction.deployOutput.appId;
96
+ if (this.selectedFunction.deployOutput.endpoint) {
97
+ this.endpointName = this.selectedFunction.deployOutput.endpoint.path;
98
+ this.isPublicFunction = true;
99
+ }
100
+ else {
101
+ this.isPublicFunction = false;
102
+ }
103
+ }
104
+ }
105
+ exports.ProjectLogsManager = new _ProjectLogsManager();
@@ -0,0 +1,16 @@
1
+ import { FileResult } from 'tmp';
2
+ import { Build } from '@hubspot/local-dev-lib/types/Build';
3
+ import { Deploy } from '@hubspot/local-dev-lib/types/Deploy';
4
+ import { ProjectConfig, ProjectTask } from '../../types/Projects';
5
+ type PollTaskStatusFunction<T extends ProjectTask> = (accountId: number, taskName: string, taskId: number, deployedBuildId: number | null, silenceLogs: boolean) => Promise<T>;
6
+ export declare const pollBuildStatus: PollTaskStatusFunction<Build>;
7
+ export declare const pollDeployStatus: PollTaskStatusFunction<Deploy>;
8
+ type ProjectPollResult = {
9
+ succeeded: boolean;
10
+ buildId: number;
11
+ buildResult: Build;
12
+ deployResult: Deploy | null;
13
+ };
14
+ export declare function displayWarnLogs(accountId: number, projectName: string, taskId: number, isDeploy?: boolean): Promise<void>;
15
+ export declare function pollProjectBuildAndDeploy(accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number, silenceLogs?: boolean): Promise<ProjectPollResult>;
16
+ export {};
@@ -0,0 +1,342 @@
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.pollDeployStatus = exports.pollBuildStatus = void 0;
7
+ exports.displayWarnLogs = displayWarnLogs;
8
+ exports.pollProjectBuildAndDeploy = pollProjectBuildAndDeploy;
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const logger_1 = require("@hubspot/local-dev-lib/logger");
11
+ const projects_1 = require("@hubspot/local-dev-lib/api/projects");
12
+ const constants_1 = require("../constants");
13
+ const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
14
+ const lang_1 = require("../lang");
15
+ const errorHandlers_1 = require("../errorHandlers");
16
+ const ui_1 = require("../ui");
17
+ const urls_1 = require("./urls");
18
+ const i18nKey = 'lib.projectBuildAndDeploy';
19
+ const SPINNER_STATUS = {
20
+ SPINNING: 'spinning',
21
+ };
22
+ function getSubtasks(task) {
23
+ if ('subbuildStatuses' in task) {
24
+ return task.subbuildStatuses;
25
+ }
26
+ return task.subdeployStatuses;
27
+ }
28
+ function getSubtaskName(task) {
29
+ if ('buildName' in task) {
30
+ return task.buildName;
31
+ }
32
+ return task.deployName;
33
+ }
34
+ function getSubtaskType(task) {
35
+ if ('buildType' in task) {
36
+ return task.buildType;
37
+ }
38
+ return task.deployType;
39
+ }
40
+ function makePollTaskStatusFunc({ statusFn, structureFn, statusText, statusStrings, linkToHubSpot, }) {
41
+ return async function (accountId, taskName, taskId, deployedBuildId = null, silenceLogs = false) {
42
+ const displayId = deployedBuildId || taskId;
43
+ if (linkToHubSpot && !silenceLogs) {
44
+ logger_1.logger.log(`\n${linkToHubSpot(accountId, taskName, taskId, deployedBuildId)}\n`);
45
+ }
46
+ SpinniesManager_1.default.init();
47
+ const overallTaskSpinniesKey = `overallTaskStatus-${statusText.STATUS_TEXT}`;
48
+ SpinniesManager_1.default.add(overallTaskSpinniesKey, {
49
+ text: 'Beginning',
50
+ succeedColor: 'white',
51
+ failColor: 'white',
52
+ failPrefix: chalk_1.default.bold('!'),
53
+ });
54
+ const [{ data: initialTaskStatus }, { data: { topLevelComponentsWithChildren: taskStructure }, },] = await Promise.all([
55
+ statusFn(accountId, taskName, taskId),
56
+ structureFn(accountId, taskName, taskId),
57
+ ]);
58
+ const subtasks = getSubtasks(initialTaskStatus);
59
+ const tasksById = subtasks.reduce((acc, subtask) => {
60
+ const { id, visible } = subtask;
61
+ if (visible) {
62
+ acc[id] = subtask;
63
+ }
64
+ return acc;
65
+ }, {});
66
+ const structuredTasks = Object.keys(taskStructure).map(key => {
67
+ return {
68
+ ...tasksById[key],
69
+ subtasks: taskStructure[key]
70
+ .filter(taskId => Boolean(tasksById[taskId]))
71
+ .map(taskId => tasksById[taskId]),
72
+ };
73
+ });
74
+ const numComponents = structuredTasks.length;
75
+ const componentCountText = silenceLogs
76
+ ? ''
77
+ : (0, lang_1.i18n)(numComponents === 1
78
+ ? `${i18nKey}.makePollTaskStatusFunc.componentCountSingular`
79
+ : `${i18nKey}.makePollTaskStatusFunc.componentCount`, { numComponents }) + '\n';
80
+ SpinniesManager_1.default.update(overallTaskSpinniesKey, {
81
+ text: `${statusStrings.INITIALIZE(taskName, displayId)}\n${componentCountText}`,
82
+ });
83
+ if (!silenceLogs) {
84
+ function addTaskSpinner(subtask, indent, newline) {
85
+ const taskName = getSubtaskName(subtask);
86
+ const taskType = getSubtaskType(subtask);
87
+ const formattedTaskType = constants_1.PROJECT_TASK_TYPES[taskType]
88
+ ? `[${constants_1.PROJECT_TASK_TYPES[taskType]}]`
89
+ : '';
90
+ const text = `${indent <= 2 ? statusText.STATUS_TEXT : ''} ${chalk_1.default.bold(taskName)} ${formattedTaskType} ...${newline ? '\n' : ''}`;
91
+ SpinniesManager_1.default.add(subtask.id, {
92
+ text,
93
+ indent,
94
+ succeedColor: 'white',
95
+ failColor: 'white',
96
+ });
97
+ }
98
+ structuredTasks.forEach(task => {
99
+ addTaskSpinner(task, 2, !task.subtasks || task.subtasks.length === 0);
100
+ task.subtasks.forEach((subtask, i) => addTaskSpinner(subtask, 4, i === task.subtasks.length - 1));
101
+ });
102
+ }
103
+ return new Promise((resolve, reject) => {
104
+ const pollInterval = setInterval(async () => {
105
+ let taskStatus;
106
+ try {
107
+ const { data } = await statusFn(accountId, taskName, taskId);
108
+ taskStatus = data;
109
+ }
110
+ catch (e) {
111
+ logger_1.logger.debug(e);
112
+ (0, errorHandlers_1.logError)(e, new errorHandlers_1.ApiErrorContext({
113
+ accountId,
114
+ projectName: taskName,
115
+ }));
116
+ return reject(new Error((0, lang_1.i18n)(`${i18nKey}.makePollTaskStatusFunc.errorFetchingTaskStatus`, {
117
+ taskType: statusText.TYPE_KEY === constants_1.PROJECT_BUILD_TEXT.TYPE_KEY
118
+ ? 'build'
119
+ : 'deploy',
120
+ })));
121
+ }
122
+ const subtasks = getSubtasks(taskStatus);
123
+ if (!taskStatus || !taskStatus.status || !subtasks) {
124
+ return reject(new Error((0, lang_1.i18n)(`${i18nKey}.makePollTaskStatusFunc.errorFetchingTaskStatus`, {
125
+ taskType: statusText.TYPE_KEY === constants_1.PROJECT_BUILD_TEXT.TYPE_KEY
126
+ ? 'build'
127
+ : 'deploy',
128
+ })));
129
+ }
130
+ const { status } = taskStatus;
131
+ if (SpinniesManager_1.default.hasActiveSpinners()) {
132
+ subtasks.forEach(subtask => {
133
+ const { id, status } = subtask;
134
+ const spinner = SpinniesManager_1.default.pick(id);
135
+ if (!spinner || spinner.status !== SPINNER_STATUS.SPINNING) {
136
+ return;
137
+ }
138
+ const topLevelTask = structuredTasks.find(t => t.id == id);
139
+ if (status === statusText.STATES.SUCCESS ||
140
+ status === statusText.STATES.FAILURE) {
141
+ const taskStatusText = subtask.status === statusText.STATES.SUCCESS
142
+ ? (0, lang_1.i18n)(`${i18nKey}.makePollTaskStatusFunc.successStatusText`)
143
+ : (0, lang_1.i18n)(`${i18nKey}.makePollTaskStatusFunc.failedStatusText`);
144
+ const hasNewline = spinner?.text?.includes('\n') || Boolean(topLevelTask);
145
+ const updatedText = `${spinner?.text?.replace('\n', '')} ${taskStatusText}${hasNewline ? '\n' : ''}`;
146
+ if (status === statusText.STATES.SUCCESS) {
147
+ SpinniesManager_1.default.succeed(id, { text: updatedText });
148
+ }
149
+ else {
150
+ SpinniesManager_1.default.fail(id, { text: updatedText });
151
+ }
152
+ if (topLevelTask) {
153
+ topLevelTask.subtasks.forEach(currentSubtask => SpinniesManager_1.default.remove(currentSubtask.id));
154
+ }
155
+ }
156
+ });
157
+ if (status === statusText.STATES.SUCCESS) {
158
+ SpinniesManager_1.default.succeed(overallTaskSpinniesKey, {
159
+ text: statusStrings.SUCCESS(taskName, displayId),
160
+ });
161
+ clearInterval(pollInterval);
162
+ resolve(taskStatus);
163
+ }
164
+ else if (status === statusText.STATES.FAILURE) {
165
+ SpinniesManager_1.default.fail(overallTaskSpinniesKey, {
166
+ text: statusStrings.FAIL(taskName, displayId),
167
+ });
168
+ if (!silenceLogs) {
169
+ const failedSubtasks = subtasks.filter(subtask => subtask.status === 'FAILURE');
170
+ (0, ui_1.uiLine)();
171
+ logger_1.logger.log(`${statusStrings.SUBTASK_FAIL(failedSubtasks.length === 1
172
+ ? getSubtaskName(failedSubtasks[0])
173
+ : failedSubtasks.length + ' components', displayId)}\n`);
174
+ logger_1.logger.log('See below for a summary of errors.');
175
+ (0, ui_1.uiLine)();
176
+ const displayErrors = failedSubtasks.filter(subtask => subtask?.standardError?.subCategory !==
177
+ constants_1.PROJECT_ERROR_TYPES.SUBBUILD_FAILED &&
178
+ subtask?.standardError?.subCategory !==
179
+ constants_1.PROJECT_ERROR_TYPES.SUBDEPLOY_FAILED);
180
+ displayErrors.forEach(subTask => {
181
+ logger_1.logger.log(`\n--- ${chalk_1.default.bold(getSubtaskName(subTask))} failed with the following error ---`);
182
+ logger_1.logger.error(subTask.errorMessage);
183
+ // Log nested errors
184
+ if (subTask.standardError && subTask.standardError.errors) {
185
+ logger_1.logger.log();
186
+ subTask.standardError.errors.forEach(error => {
187
+ logger_1.logger.log(error.message);
188
+ });
189
+ }
190
+ });
191
+ }
192
+ clearInterval(pollInterval);
193
+ resolve(taskStatus);
194
+ }
195
+ else if (!subtasks.length) {
196
+ clearInterval(pollInterval);
197
+ resolve(taskStatus);
198
+ }
199
+ }
200
+ }, constants_1.POLLING_DELAY);
201
+ });
202
+ };
203
+ }
204
+ function pollBuildAutodeployStatus(accountId, taskName, buildId) {
205
+ return new Promise((resolve, reject) => {
206
+ let maxIntervals = (30 * 1000) / constants_1.POLLING_DELAY; // Num of intervals in ~30s
207
+ const pollInterval = setInterval(async () => {
208
+ let build;
209
+ try {
210
+ const response = await (0, projects_1.getBuildStatus)(accountId, taskName, buildId);
211
+ build = response.data;
212
+ }
213
+ catch (e) {
214
+ logger_1.logger.debug(e);
215
+ return reject(new Error((0, lang_1.i18n)(`${i18nKey}.pollBuildAutodeployStatusError`, { buildId })));
216
+ }
217
+ if (!build || !build.status) {
218
+ return reject(new Error((0, lang_1.i18n)(`${i18nKey}.pollBuildAutodeployStatusError`, { buildId })));
219
+ }
220
+ if (build.deployStatusTaskLocator || maxIntervals <= 0) {
221
+ clearInterval(pollInterval);
222
+ resolve(build);
223
+ }
224
+ else {
225
+ maxIntervals -= 1;
226
+ }
227
+ }, constants_1.POLLING_DELAY);
228
+ });
229
+ }
230
+ exports.pollBuildStatus = makePollTaskStatusFunc({
231
+ linkToHubSpot: (accountId, taskName, taskId) => (0, ui_1.uiLink)(`View build #${taskId} in HubSpot`, (0, urls_1.getProjectBuildDetailUrl)(taskName, taskId, accountId)),
232
+ statusFn: projects_1.getBuildStatus,
233
+ structureFn: projects_1.getBuildStructure,
234
+ statusText: constants_1.PROJECT_BUILD_TEXT,
235
+ statusStrings: {
236
+ INITIALIZE: (name, buildId) => `Building ${chalk_1.default.bold(name)} #${buildId}`,
237
+ SUCCESS: (name, buildId) => `Built ${chalk_1.default.bold(name)} #${buildId}`,
238
+ FAIL: (name, buildId) => `Failed to build ${chalk_1.default.bold(name)} #${buildId}`,
239
+ SUBTASK_FAIL: (buildId, name) => `Build #${buildId} failed because there was a problem\nbuilding ${chalk_1.default.bold(name)}`,
240
+ },
241
+ });
242
+ exports.pollDeployStatus = makePollTaskStatusFunc({
243
+ linkToHubSpot: (accountId, taskName, taskId, deployedBuildId) => (0, ui_1.uiLink)(`View deploy of build #${deployedBuildId} in HubSpot`, (0, urls_1.getProjectDeployDetailUrl)(taskName, taskId, accountId)),
244
+ statusFn: projects_1.getDeployStatus,
245
+ structureFn: projects_1.getDeployStructure,
246
+ statusText: constants_1.PROJECT_DEPLOY_TEXT,
247
+ statusStrings: {
248
+ INITIALIZE: (name, buildId) => `Deploying build #${buildId} in ${chalk_1.default.bold(name)}`,
249
+ SUCCESS: (name, buildId) => `Deployed build #${buildId} in ${chalk_1.default.bold(name)}`,
250
+ FAIL: (name, buildId) => `Failed to deploy build #${buildId} in ${chalk_1.default.bold(name)}`,
251
+ SUBTASK_FAIL: (deployedBuildId, name) => `Deploy for build #${deployedBuildId} failed because there was a\nproblem deploying ${chalk_1.default.bold(name)}`,
252
+ },
253
+ });
254
+ async function displayWarnLogs(accountId, projectName, taskId, isDeploy = false) {
255
+ let result;
256
+ if (isDeploy) {
257
+ try {
258
+ const { data } = await (0, projects_1.fetchDeployWarnLogs)(accountId, projectName, taskId);
259
+ result = data;
260
+ }
261
+ catch (e) {
262
+ (0, errorHandlers_1.logError)(e);
263
+ }
264
+ }
265
+ else {
266
+ try {
267
+ const { data } = await (0, projects_1.fetchBuildWarnLogs)(accountId, projectName, taskId);
268
+ result = data;
269
+ }
270
+ catch (e) {
271
+ (0, errorHandlers_1.logError)(e);
272
+ }
273
+ }
274
+ if (result && result.logs) {
275
+ const logLength = result.logs.length;
276
+ result.logs.forEach((log, i) => {
277
+ logger_1.logger.warn(log.message);
278
+ if (i < logLength - 1) {
279
+ logger_1.logger.log('');
280
+ }
281
+ });
282
+ }
283
+ }
284
+ async function pollProjectBuildAndDeploy(accountId, projectConfig, tempFile, buildId, silenceLogs = false) {
285
+ let buildStatus = await (0, exports.pollBuildStatus)(accountId, projectConfig.name, buildId, null, silenceLogs);
286
+ if (!silenceLogs) {
287
+ (0, ui_1.uiLine)();
288
+ }
289
+ const result = {
290
+ succeeded: true,
291
+ buildId,
292
+ buildResult: buildStatus,
293
+ deployResult: null,
294
+ };
295
+ if (buildStatus.status === 'FAILURE') {
296
+ result.succeeded = false;
297
+ return result;
298
+ }
299
+ else if (buildStatus.isAutoDeployEnabled) {
300
+ if (!silenceLogs) {
301
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.pollProjectBuildAndDeploy.buildSucceededAutomaticallyDeploying`, {
302
+ accountIdentifier: (0, ui_1.uiAccountDescription)(accountId),
303
+ buildId,
304
+ }));
305
+ await displayWarnLogs(accountId, projectConfig.name, buildId);
306
+ }
307
+ // autoDeployId of 0 indicates a skipped deploy
308
+ const getIsDeploying = () => buildStatus.autoDeployId > 0 && buildStatus.deployStatusTaskLocator;
309
+ // Sometimes the deploys do not immediately initiate, give them a chance to kick off
310
+ if (!getIsDeploying()) {
311
+ buildStatus = await pollBuildAutodeployStatus(accountId, projectConfig.name, buildId);
312
+ }
313
+ if (getIsDeploying()) {
314
+ const deployStatus = await (0, exports.pollDeployStatus)(accountId, projectConfig.name, Number(buildStatus.deployStatusTaskLocator.id), buildId, silenceLogs);
315
+ result.deployResult = deployStatus;
316
+ if (deployStatus.status === 'FAILURE') {
317
+ result.succeeded = false;
318
+ }
319
+ }
320
+ else if (!silenceLogs) {
321
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.pollProjectBuildAndDeploy.unableToFindAutodeployStatus`, {
322
+ buildId,
323
+ viewDeploysLink: (0, ui_1.uiLink)((0, lang_1.i18n)(`${i18nKey}.pollProjectBuildAndDeploy.viewDeploys`), (0, urls_1.getProjectActivityUrl)(projectConfig.name, accountId)),
324
+ }));
325
+ }
326
+ }
327
+ try {
328
+ if (tempFile) {
329
+ tempFile.removeCallback();
330
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.pollProjectBuildAndDeploy.cleanedUpTempFile`, {
331
+ path: tempFile.name,
332
+ }));
333
+ }
334
+ }
335
+ catch (e) {
336
+ logger_1.logger.error(e);
337
+ }
338
+ if (result && result.deployResult) {
339
+ await displayWarnLogs(accountId, projectConfig.name, result.deployResult.deployId, true);
340
+ }
341
+ return result;
342
+ }
@@ -0,0 +1,24 @@
1
+ import { RepoPath } from '@hubspot/local-dev-lib/types/Github';
2
+ import { Project } from '@hubspot/local-dev-lib/types/Project';
3
+ import { ProjectTemplate, ProjectConfig, ProjectAddComponentData, ComponentTemplate } from '../../types/Projects';
4
+ export declare function writeProjectConfig(configPath: string, config: ProjectConfig): boolean;
5
+ export declare function getIsInProject(dir?: string): boolean;
6
+ export declare function getProjectConfig(dir?: string): Promise<{
7
+ projectDir: string | null;
8
+ projectConfig: ProjectConfig | null;
9
+ }>;
10
+ export declare function createProjectConfig(projectPath: string, projectName: string, template: ProjectTemplate, templateSource: RepoPath, githubRef: string): Promise<boolean>;
11
+ export declare function validateProjectConfig(projectConfig: ProjectConfig, projectDir: string): void;
12
+ export declare function ensureProjectExists(accountId: number, projectName: string, { forceCreate, allowCreate, noLogs, withPolling, uploadCommand, }?: {
13
+ forceCreate?: boolean | undefined;
14
+ allowCreate?: boolean | undefined;
15
+ noLogs?: boolean | undefined;
16
+ withPolling?: boolean | undefined;
17
+ uploadCommand?: boolean | undefined;
18
+ }): Promise<{
19
+ projectExists: boolean;
20
+ project?: Project;
21
+ }>;
22
+ export declare function logFeedbackMessage(buildId: number): void;
23
+ export declare function createProjectComponent(component: ProjectAddComponentData, name: string, projectComponentsVersion: string): Promise<void>;
24
+ export declare function getProjectComponentsByVersion(projectComponentsVersion: string): Promise<ComponentTemplate[]>;