@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.
Files changed (53) hide show
  1. package/commands/account/auth.js +3 -3
  2. package/commands/app/install.d.ts +8 -0
  3. package/commands/app/install.js +127 -0
  4. package/commands/app.js +6 -1
  5. package/commands/auth.js +23 -25
  6. package/commands/getStarted.js +55 -8
  7. package/commands/init.js +29 -31
  8. package/commands/project/cloneApp.js +4 -4
  9. package/commands/project/create.js +9 -9
  10. package/commands/project/dev/deprecatedFlow.js +4 -4
  11. package/commands/project/dev/index.js +5 -5
  12. package/commands/project/dev/unifiedFlow.js +8 -0
  13. package/commands/sandbox/delete.js +5 -5
  14. package/commands/testAccount/create.js +53 -3
  15. package/lang/en.d.ts +67 -15
  16. package/lang/en.js +64 -12
  17. package/lib/accountTypes.d.ts +1 -0
  18. package/lib/accountTypes.js +20 -9
  19. package/lib/app/migrate_legacy.js +2 -3
  20. package/lib/app/urls.d.ts +1 -1
  21. package/lib/commonOpts.js +1 -1
  22. package/lib/middleware/__test__/configMiddleware.test.js +2 -2
  23. package/lib/middleware/configMiddleware.js +10 -2
  24. package/lib/parsing.d.ts +1 -0
  25. package/lib/parsing.js +11 -0
  26. package/lib/polling.d.ts +1 -1
  27. package/lib/polling.js +11 -1
  28. package/lib/projects/add/v3AddComponent.js +4 -0
  29. package/lib/projects/create/index.d.ts +3 -2
  30. package/lib/projects/create/index.js +11 -5
  31. package/lib/projects/create/v3.d.ts +3 -3
  32. package/lib/projects/create/v3.js +2 -2
  33. package/lib/projects/localDev/AppDevModeInterface.js +1 -1
  34. package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
  35. package/lib/projects/localDev/LocalDevProcess.js +16 -12
  36. package/lib/projects/localDev/LocalDevState.d.ts +10 -5
  37. package/lib/projects/localDev/LocalDevState.js +18 -20
  38. package/lib/projects/localDev/LocalDevWatcher.js +1 -1
  39. package/lib/projects/structure.d.ts +2 -2
  40. package/lib/projects/upload.d.ts +2 -1
  41. package/lib/projects/upload.js +1 -0
  42. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  43. package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
  44. package/lib/prompts/projectNameAndDestPrompt.js +60 -0
  45. package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
  46. package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
  47. package/lib/validation.d.ts +1 -1
  48. package/lib/validation.js +4 -4
  49. package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
  50. package/package.json +3 -3
  51. package/types/LocalDev.d.ts +1 -0
  52. package/types/Yargs.d.ts +1 -1
  53. package/lib/prompts/createProjectPrompt.d.ts +0 -28
@@ -18,7 +18,7 @@ const ui_1 = require("../ui");
18
18
  const lang_1 = require("../lang");
19
19
  const accountTypes_1 = require("../accountTypes");
20
20
  const selectPublicAppForMigrationPrompt_1 = require("../prompts/selectPublicAppForMigrationPrompt");
21
- const createProjectPrompt_1 = require("../prompts/createProjectPrompt");
21
+ const projectNameAndDestPrompt_1 = require("../prompts/projectNameAndDestPrompt");
22
22
  const ensureProjectExists_1 = require("../projects/ensureProjectExists");
23
23
  const usageTracking_1 = require("../usageTracking");
24
24
  const SpinniesManager_1 = __importDefault(require("../ui/SpinniesManager"));
@@ -58,8 +58,7 @@ async function migrateApp2023_2(derivedAccountId, options, accountConfig) {
58
58
  (0, errorHandlers_1.logError)(error, new errorHandlers_1.ApiErrorContext({ accountId: derivedAccountId }));
59
59
  return process.exit(exitCodes_1.EXIT_CODES.ERROR);
60
60
  }
61
- const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(options);
62
- const { name: projectName, dest: projectDest } = createProjectPromptResponse;
61
+ const { name: projectName, dest: projectDest } = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(options);
63
62
  const { projectExists } = await (0, ensureProjectExists_1.ensureProjectExists)(derivedAccountId, projectName, {
64
63
  allowCreate: false,
65
64
  noLogs: true,
package/lib/app/urls.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Environment } from '@hubspot/local-dev-lib/types/Config';
2
2
  type PrivateAppInstallUrlArgs = {
3
3
  targetAccountId: number;
4
4
  env: Environment;
5
- appId: string;
5
+ appId: number;
6
6
  };
7
7
  type PublicAppInstallUrlArgs = {
8
8
  targetAccountId: number;
package/lib/commonOpts.js CHANGED
@@ -136,7 +136,7 @@ async function addCustomHelpOutput(yargs, command, describe) {
136
136
  function setLogLevel(options) {
137
137
  const { debug, networkDebug, json } = options;
138
138
  if (json) {
139
- (0, logger_1.setLogLevel)(logger_1.LOG_LEVEL.NONE);
139
+ (0, logger_1.setLogLevel)(logger_1.LOG_LEVEL.ERROR);
140
140
  }
141
141
  else if (debug) {
142
142
  (0, logger_1.setLogLevel)(logger_1.LOG_LEVEL.DEBUG);
@@ -109,7 +109,7 @@ describe('lib/middleware/configMiddleware', () => {
109
109
  $0: 'hs',
110
110
  };
111
111
  await (0, configMiddleware_1.injectAccountIdMiddleware)(argv);
112
- expect(argv.providedAccountId).toBeUndefined();
112
+ expect(argv.userProvidedAccount).toBeUndefined();
113
113
  expect(argv.derivedAccountId).toBe(123);
114
114
  expect(getAccountIdSpy).not.toHaveBeenCalled();
115
115
  process.env = originalEnv;
@@ -123,7 +123,7 @@ describe('lib/middleware/configMiddleware', () => {
123
123
  $0: 'hs',
124
124
  };
125
125
  await (0, configMiddleware_1.injectAccountIdMiddleware)(argv);
126
- expect(argv.providedAccountId).toBe('test-account');
126
+ expect(argv.userProvidedAccount).toBe('test-account');
127
127
  expect(argv.derivedAccountId).toBe(456);
128
128
  expect(getAccountIdSpy).toHaveBeenCalledWith('test-account');
129
129
  });
@@ -11,6 +11,9 @@ const exitCodes_1 = require("../enums/exitCodes");
11
11
  const lang_1 = require("../lang");
12
12
  const ui_1 = require("../ui");
13
13
  const utils_1 = require("./utils");
14
+ const parsing_1 = require("../parsing");
15
+ const logger_2 = require("../ui/logger");
16
+ const en_1 = require("../../lang/en");
14
17
  function handleDeprecatedEnvVariables(argv) {
15
18
  // HUBSPOT_PORTAL_ID is deprecated, but we'll still support it for now
16
19
  // The HubSpot GH Deploy Action still uses HUBSPOT_PORTAL_ID
@@ -29,9 +32,14 @@ function handleDeprecatedEnvVariables(argv) {
29
32
  async function injectAccountIdMiddleware(argv) {
30
33
  const { account } = argv;
31
34
  // Preserves the original --account flag for certain commands.
32
- argv.providedAccountId = account;
35
+ argv.userProvidedAccount = account;
33
36
  if (argv.useEnv && process.env.HUBSPOT_ACCOUNT_ID) {
34
- argv.derivedAccountId = parseInt(process.env.HUBSPOT_ACCOUNT_ID, 10);
37
+ try {
38
+ argv.derivedAccountId = (0, parsing_1.parseStringToNumber)(process.env.HUBSPOT_ACCOUNT_ID);
39
+ }
40
+ catch (err) {
41
+ logger_2.uiLogger.error(en_1.lib.configMiddleWare.invalidAccountIdEnvironmentVariable);
42
+ }
35
43
  }
36
44
  else {
37
45
  argv.derivedAccountId = (0, config_1.getAccountId)(account);
@@ -0,0 +1 @@
1
+ export declare function parseStringToNumber(maybeNumber: string): number;
package/lib/parsing.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseStringToNumber = parseStringToNumber;
4
+ const en_1 = require("../lang/en");
5
+ function parseStringToNumber(maybeNumber) {
6
+ const result = parseInt(maybeNumber, 10);
7
+ if (Number.isNaN(result) || !/^-?\d+$/.test(maybeNumber)) {
8
+ throw new Error(en_1.lib.parsing.unableToParseStringToNumber);
9
+ }
10
+ return result;
11
+ }
package/lib/polling.d.ts CHANGED
@@ -17,5 +17,5 @@ type PollingCallback<T extends GenericPollingResponse> = () => HubSpotPromise<T>
17
17
  export declare function poll<T extends GenericPollingResponse>(callback: PollingCallback<T>, statusLookup?: {
18
18
  successStates: string[];
19
19
  errorStates: string[];
20
- }): Promise<T>;
20
+ }, timeoutMs?: number): Promise<T>;
21
21
  export {};
package/lib/polling.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_POLLING_STATUS_LOOKUP = exports.DEFAULT_POLLING_STATES = void 0;
4
4
  exports.poll = poll;
5
5
  const constants_1 = require("./constants");
6
+ const en_1 = require("../lang/en");
6
7
  exports.DEFAULT_POLLING_STATES = {
7
8
  STARTED: 'STARTED',
8
9
  SUCCESS: 'SUCCESS',
@@ -18,7 +19,8 @@ exports.DEFAULT_POLLING_STATUS_LOOKUP = {
18
19
  exports.DEFAULT_POLLING_STATES.FAILURE,
19
20
  ],
20
21
  };
21
- function poll(callback, statusLookup = exports.DEFAULT_POLLING_STATUS_LOOKUP) {
22
+ function poll(callback, statusLookup = exports.DEFAULT_POLLING_STATUS_LOOKUP, timeoutMs = 60000 // Default 60 second timeout
23
+ ) {
22
24
  return new Promise((resolve, reject) => {
23
25
  const pollInterval = setInterval(async () => {
24
26
  try {
@@ -26,17 +28,25 @@ function poll(callback, statusLookup = exports.DEFAULT_POLLING_STATUS_LOOKUP) {
26
28
  const { status } = pollResp;
27
29
  if (statusLookup.successStates.includes(status)) {
28
30
  clearInterval(pollInterval);
31
+ clearTimeout(timeoutId);
29
32
  resolve(pollResp);
30
33
  }
31
34
  else if (statusLookup.errorStates.includes(status)) {
32
35
  clearInterval(pollInterval);
36
+ clearTimeout(timeoutId);
33
37
  reject(pollResp);
34
38
  }
35
39
  }
36
40
  catch (error) {
37
41
  clearInterval(pollInterval);
42
+ clearTimeout(timeoutId);
38
43
  reject(error);
39
44
  }
40
45
  }, constants_1.DEFAULT_POLLING_DELAY);
46
+ // Set a timeout to stop polling after specified duration
47
+ const timeoutId = setTimeout(() => {
48
+ clearInterval(pollInterval);
49
+ reject(new Error(en_1.lib.polling.timeoutError(timeoutMs)));
50
+ }, timeoutMs);
41
51
  });
42
52
  }
@@ -66,6 +66,10 @@ async function v3AddComponent(args, projectDir, projectConfig) {
66
66
  components.push(path_1.default.join(projectConfig.platformVersion, parentComponent.path));
67
67
  }
68
68
  }
69
+ if (components.length === 0) {
70
+ logger_1.uiLogger.log(en_1.lib.projects.add.nothingAdded);
71
+ return;
72
+ }
69
73
  await (0, github_1.cloneGithubRepo)(constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDir, {
70
74
  sourceDir: components,
71
75
  hideLogs: true,
@@ -1,6 +1,6 @@
1
1
  import { ArgumentsCamelCase } from 'yargs';
2
2
  import { ProjectTemplateRepoConfig } from '../../../types/Projects';
3
- import { CreateProjectPromptResponse } from '../../prompts/createProjectPrompt';
3
+ import { SelectProjectTemplatePromptResponse, ProjectNameAndDestPromptResponse } from '../../prompts/selectProjectTemplatePrompt';
4
4
  import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs } from '../../../types/Yargs';
5
5
  import { RepoPath } from '@hubspot/local-dev-lib/types/Github';
6
6
  export type ProjectCreateArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
@@ -19,5 +19,6 @@ export declare function handleProjectCreationFlow(args: ArgumentsCamelCase<Proje
19
19
  distribution?: string;
20
20
  repoConfig?: ProjectTemplateRepoConfig;
21
21
  projectContents?: string;
22
- createProjectPromptResponse: CreateProjectPromptResponse;
22
+ selectProjectTemplatePromptResponse: SelectProjectTemplatePromptResponse;
23
+ projectNameAndDestPromptResponse: ProjectNameAndDestPromptResponse;
23
24
  }>;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleProjectCreationFlow = handleProjectCreationFlow;
4
- const createProjectPrompt_1 = require("../../prompts/createProjectPrompt");
4
+ const selectProjectTemplatePrompt_1 = require("../../prompts/selectProjectTemplatePrompt");
5
+ const projectNameAndDestPrompt_1 = require("../../prompts/projectNameAndDestPrompt");
5
6
  const constants_1 = require("../../constants");
6
7
  const buildAndDeploy_1 = require("../buildAndDeploy");
7
8
  const v3_1 = require("./v3");
@@ -12,15 +13,17 @@ const exitCodes_1 = require("../../enums/exitCodes");
12
13
  async function handleProjectCreationFlow(args) {
13
14
  const { platformVersion, templateSource, projectBase, auth: providedAuth, distribution: providedDistribution, } = args;
14
15
  const repo = templateSource || constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
16
+ const projectNameAndDestPromptResponse = await (0, projectNameAndDestPrompt_1.projectNameAndDestPrompt)(args);
15
17
  if ((0, buildAndDeploy_1.useV3Api)(platformVersion)) {
16
18
  const { componentTemplateChoices, authType, distribution, repoConfig, projectContents, } = await (0, v3_1.v3ComponentFlow)(platformVersion, projectBase, providedAuth, providedDistribution);
17
- const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(args, undefined, projectContents !== v3_1.EMPTY_PROJECT ? componentTemplateChoices : undefined);
19
+ const selectProjectTemplatePromptResponse = await (0, selectProjectTemplatePrompt_1.selectProjectTemplatePrompt)(args, undefined, projectContents !== v3_1.EMPTY_PROJECT ? componentTemplateChoices : undefined);
18
20
  return {
19
21
  authType,
20
22
  distribution,
21
23
  repoConfig,
22
24
  projectContents,
23
- createProjectPromptResponse,
25
+ selectProjectTemplatePromptResponse,
26
+ projectNameAndDestPromptResponse,
24
27
  };
25
28
  }
26
29
  const projectTemplates = await (0, legacy_1.getProjectTemplateListFromRepo)(repo, 'main');
@@ -28,6 +31,9 @@ async function handleProjectCreationFlow(args) {
28
31
  logger_1.uiLogger.error(en_1.commands.project.create.errors.failedToFetchProjectList);
29
32
  process.exit(exitCodes_1.EXIT_CODES.ERROR);
30
33
  }
31
- const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(args, projectTemplates);
32
- return { createProjectPromptResponse };
34
+ const selectProjectTemplatePromptResponse = await (0, selectProjectTemplatePrompt_1.selectProjectTemplatePrompt)(args, projectTemplates);
35
+ return {
36
+ selectProjectTemplatePromptResponse,
37
+ projectNameAndDestPromptResponse,
38
+ };
33
39
  }
@@ -1,6 +1,6 @@
1
1
  import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplateRepoConfig } from '../../../types/Projects';
2
2
  import { ProjectMetadata } from '@hubspot/project-parsing-lib/src/lib/project';
3
- import { CreateProjectPromptResponse } from '../../prompts/createProjectPrompt';
3
+ import { SelectProjectTemplatePromptResponse } from '../../prompts/selectProjectTemplatePrompt';
4
4
  export declare const EMPTY_PROJECT = "empty";
5
5
  export declare const PROJECT_WITH_APP = "app";
6
6
  export declare function createV3App(providedAuth: string | undefined, providedDistribution: string | undefined): Promise<{
@@ -16,8 +16,8 @@ type V3ComponentInfo = {
16
16
  componentTemplateChoices?: ComponentTemplateChoice[];
17
17
  };
18
18
  export declare function v3ComponentFlow(platformVersion: string, projectBase: string | undefined, providedAuth: string | undefined, providedDistribution: string | undefined): Promise<V3ComponentInfo>;
19
- export declare function generateComponentPaths({ createProjectPromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }: {
20
- createProjectPromptResponse: CreateProjectPromptResponse;
19
+ export declare function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }: {
20
+ selectProjectTemplatePromptResponse: SelectProjectTemplatePromptResponse;
21
21
  platformVersion: string;
22
22
  repoConfig?: ProjectTemplateRepoConfig;
23
23
  projectContents?: string;
@@ -134,11 +134,11 @@ async function v3ComponentFlow(platformVersion, projectBase, providedAuth, provi
134
134
  repoConfig,
135
135
  };
136
136
  }
137
- function generateComponentPaths({ createProjectPromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }) {
137
+ function generateComponentPaths({ selectProjectTemplatePromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }) {
138
138
  if (!(0, buildAndDeploy_1.useV3Api)(platformVersion)) {
139
139
  return [];
140
140
  }
141
- const components = createProjectPromptResponse.componentTemplates?.map((componentTemplate) => {
141
+ const components = selectProjectTemplatePromptResponse.componentTemplates?.map((componentTemplate) => {
142
142
  return path_1.default.join(platformVersion, componentTemplate.path);
143
143
  }) || [];
144
144
  if (projectContents && projectContents !== exports.EMPTY_PROJECT) {
@@ -84,7 +84,7 @@ class AppDevModeInterface {
84
84
  return (0, urls_1.getStaticAuthAppInstallUrl)({
85
85
  targetAccountId: this.localDevState.targetTestingAccountId,
86
86
  env: this.localDevState.env,
87
- appId: `${app.id}`,
87
+ appId: app.id,
88
88
  });
89
89
  }
90
90
  async fetchAppData() {
@@ -16,15 +16,16 @@ declare class LocalDevProcess {
16
16
  [key: string]: IntermediateRepresentationNodeLocalDev;
17
17
  };
18
18
  get logger(): LocalDevLogger;
19
- get configFilesUpdatedSinceLastUpload(): Set<string>;
20
19
  private setupDevServers;
21
20
  private startDevServers;
22
21
  private cleanupDevServers;
23
22
  private compareLocalProjectToDeployed;
24
23
  private projectConfigValidForUpload;
24
+ private getIntermediateRepresentation;
25
25
  private updateProjectNodes;
26
+ private updateProjectNodesAfterUpload;
26
27
  handleFileChange(filePath: string, event: string): Promise<void>;
27
- handleConfigFileChange(filePath: string, event: string): Promise<void>;
28
+ handleConfigFileChange(): Promise<void>;
28
29
  start(): Promise<void>;
29
30
  stop(showProgress?: boolean): Promise<void>;
30
31
  uploadProject(): Promise<boolean>;
@@ -46,9 +46,6 @@ class LocalDevProcess {
46
46
  get logger() {
47
47
  return this._logger;
48
48
  }
49
- get configFilesUpdatedSinceLastUpload() {
50
- return this.state.configFilesUpdatedSinceLastUpload;
51
- }
52
49
  async setupDevServers() {
53
50
  try {
54
51
  await this.devServerManager.setup();
@@ -105,17 +102,28 @@ class LocalDevProcess {
105
102
  });
106
103
  return true;
107
104
  }
108
- async updateProjectNodes() {
109
- const intermediateRepresentation = await (0, project_parsing_lib_1.translateForLocalDev)({
105
+ getIntermediateRepresentation(projectNodesAtLastUpload) {
106
+ return (0, project_parsing_lib_1.translateForLocalDev)({
110
107
  projectSourceDir: path_1.default.join(this.state.projectDir, this.state.projectConfig.srcDir),
111
108
  platformVersion: this.state.projectConfig.platformVersion,
112
109
  accountId: this.state.targetProjectAccountId,
113
110
  }, {
114
- configFilesUpdatedSinceLastUpload: this.state.configFilesUpdatedSinceLastUpload,
111
+ projectNodesAtLastUpload,
112
+ profile: this.state.profile,
115
113
  });
114
+ }
115
+ async updateProjectNodes() {
116
+ const intermediateRepresentation = await this.getIntermediateRepresentation(this.state.projectNodesAtLastUpload);
116
117
  this.state.projectNodes =
117
118
  intermediateRepresentation.intermediateNodesIndexedByUid;
118
119
  }
120
+ async updateProjectNodesAfterUpload() {
121
+ const intermediateRepresentation = await this.getIntermediateRepresentation();
122
+ this.state.projectNodes =
123
+ intermediateRepresentation.intermediateNodesIndexedByUid;
124
+ this.state.projectNodesAtLastUpload =
125
+ intermediateRepresentation.intermediateNodesIndexedByUid;
126
+ }
119
127
  async handleFileChange(filePath, event) {
120
128
  await this.updateProjectNodes();
121
129
  try {
@@ -125,10 +133,7 @@ class LocalDevProcess {
125
133
  this.logger.fileChangeError(e);
126
134
  }
127
135
  }
128
- async handleConfigFileChange(filePath, event) {
129
- if (event === 'add' || event === 'change') {
130
- this.state.addUpdatedConfigFileUpdatedSinceLastUpload(filePath);
131
- }
136
+ async handleConfigFileChange() {
132
137
  await this.updateProjectNodes();
133
138
  this.logger.uploadWarning();
134
139
  }
@@ -185,8 +190,7 @@ class LocalDevProcess {
185
190
  this.logger.uploadError(uploadError);
186
191
  return false;
187
192
  }
188
- this.state.resetConfigFilesUpdatedSinceLastUpload();
189
- this.updateProjectNodes();
193
+ await this.updateProjectNodesAfterUpload();
190
194
  this.logger.uploadSuccess();
191
195
  this.logger.clearUploadWarnings();
192
196
  return true;
@@ -6,6 +6,7 @@ import { LocalDevStateConstructorOptions, LocalDevStateListener, AppLocalDevData
6
6
  declare class LocalDevState {
7
7
  private _targetProjectAccountId;
8
8
  private _targetTestingAccountId;
9
+ private _profile?;
9
10
  private _projectConfig;
10
11
  private _projectDir;
11
12
  private _projectId;
@@ -14,15 +15,16 @@ declare class LocalDevState {
14
15
  private _deployedBuild?;
15
16
  private _isGithubLinked;
16
17
  private _projectNodes;
18
+ private _projectNodesAtLastUpload;
17
19
  private _env;
18
20
  private _listeners;
19
- private _configFilesUpdatedSinceLastUpload;
20
21
  private _appData;
21
22
  private _devServerMessage;
22
- constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }: LocalDevStateConstructorOptions);
23
+ constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, profile, env, }: LocalDevStateConstructorOptions);
23
24
  private runListeners;
24
25
  get targetProjectAccountId(): number;
25
26
  get targetTestingAccountId(): number;
27
+ get profile(): string | undefined;
26
28
  get projectConfig(): ProjectConfig;
27
29
  get projectDir(): string;
28
30
  get projectId(): number;
@@ -36,10 +38,13 @@ declare class LocalDevState {
36
38
  set projectNodes(nodes: {
37
39
  [key: string]: IntermediateRepresentationNodeLocalDev;
38
40
  });
41
+ get projectNodesAtLastUpload(): {
42
+ [key: string]: IntermediateRepresentationNodeLocalDev;
43
+ };
44
+ set projectNodesAtLastUpload(nodes: {
45
+ [key: string]: IntermediateRepresentationNodeLocalDev;
46
+ });
39
47
  get env(): Environment;
40
- get configFilesUpdatedSinceLastUpload(): Set<string>;
41
- addUpdatedConfigFileUpdatedSinceLastUpload(filePath: string): void;
42
- resetConfigFilesUpdatedSinceLastUpload(): void;
43
48
  get appData(): Record<string, AppLocalDevData>;
44
49
  getAppDataByUid(uid: string): AppLocalDevData | undefined;
45
50
  setAppDataForUid(uid: string, appData: AppLocalDevData): void;
@@ -4,6 +4,7 @@ const constants_1 = require("../../constants");
4
4
  class LocalDevState {
5
5
  _targetProjectAccountId;
6
6
  _targetTestingAccountId;
7
+ _profile;
7
8
  _projectConfig;
8
9
  _projectDir;
9
10
  _projectId;
@@ -12,14 +13,15 @@ class LocalDevState {
12
13
  _deployedBuild;
13
14
  _isGithubLinked;
14
15
  _projectNodes;
16
+ _projectNodesAtLastUpload;
15
17
  _env;
16
18
  _listeners;
17
- _configFilesUpdatedSinceLastUpload;
18
19
  _appData;
19
20
  _devServerMessage;
20
- constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, env, }) {
21
+ constructor({ targetProjectAccountId, targetTestingAccountId, projectConfig, projectDir, projectId, projectName, debug, deployedBuild, isGithubLinked, initialProjectNodes, profile, env, }) {
21
22
  this._targetProjectAccountId = targetProjectAccountId;
22
23
  this._targetTestingAccountId = targetTestingAccountId;
24
+ this._profile = profile;
23
25
  this._projectConfig = projectConfig;
24
26
  this._projectDir = projectDir;
25
27
  this._projectId = projectId;
@@ -28,8 +30,8 @@ class LocalDevState {
28
30
  this._deployedBuild = deployedBuild;
29
31
  this._isGithubLinked = isGithubLinked;
30
32
  this._projectNodes = initialProjectNodes;
33
+ this._projectNodesAtLastUpload = initialProjectNodes;
31
34
  this._env = env;
32
- this._configFilesUpdatedSinceLastUpload = new Set();
33
35
  this._appData = {};
34
36
  this._devServerMessage = constants_1.LOCAL_DEV_SERVER_MESSAGE_TYPES.INITIAL;
35
37
  this._listeners = {};
@@ -45,10 +47,11 @@ class LocalDevState {
45
47
  get targetTestingAccountId() {
46
48
  return this._targetTestingAccountId;
47
49
  }
50
+ get profile() {
51
+ return this._profile;
52
+ }
48
53
  get projectConfig() {
49
- return {
50
- ...this._projectConfig,
51
- };
54
+ return structuredClone(this._projectConfig);
52
55
  }
53
56
  get projectDir() {
54
57
  return this._projectDir;
@@ -63,34 +66,29 @@ class LocalDevState {
63
66
  return this._debug;
64
67
  }
65
68
  get deployedBuild() {
66
- return (this._deployedBuild && {
67
- ...this._deployedBuild,
68
- });
69
+ return this._deployedBuild && structuredClone(this._deployedBuild);
69
70
  }
70
71
  get isGithubLinked() {
71
72
  return this._isGithubLinked;
72
73
  }
73
74
  get projectNodes() {
74
- return { ...this._projectNodes };
75
+ return structuredClone(this._projectNodes);
75
76
  }
76
77
  set projectNodes(nodes) {
77
78
  this._projectNodes = nodes;
78
79
  this.runListeners('projectNodes');
79
80
  }
80
- get env() {
81
- return this._env;
82
- }
83
- get configFilesUpdatedSinceLastUpload() {
84
- return this._configFilesUpdatedSinceLastUpload;
81
+ get projectNodesAtLastUpload() {
82
+ return structuredClone(this._projectNodesAtLastUpload);
85
83
  }
86
- addUpdatedConfigFileUpdatedSinceLastUpload(filePath) {
87
- this._configFilesUpdatedSinceLastUpload.add(filePath);
84
+ set projectNodesAtLastUpload(nodes) {
85
+ this._projectNodesAtLastUpload = nodes;
88
86
  }
89
- resetConfigFilesUpdatedSinceLastUpload() {
90
- this._configFilesUpdatedSinceLastUpload.clear();
87
+ get env() {
88
+ return this._env;
91
89
  }
92
90
  get appData() {
93
- return { ...this._appData };
91
+ return structuredClone(this._appData);
94
92
  }
95
93
  getAppDataByUid(uid) {
96
94
  return { ...this._appData[uid] };
@@ -21,7 +21,7 @@ class LocalDevWatcher {
21
21
  }
22
22
  handleWatchEvent(filePath, event, configPaths) {
23
23
  if (configPaths.includes(filePath)) {
24
- return this.localDevProcess.handleConfigFileChange(filePath, event);
24
+ return this.localDevProcess.handleConfigFileChange();
25
25
  }
26
26
  return this.localDevProcess.handleFileChange(filePath, event);
27
27
  }
@@ -1,5 +1,5 @@
1
1
  import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects';
2
- import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
2
+ import { IntermediateRepresentationNode, IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
3
3
  import { AppIRNode } from '../../types/ProjectComponents';
4
4
  export declare const CONFIG_FILES: {
5
5
  [k in ComponentTypes]: string;
@@ -15,4 +15,4 @@ export declare function getProjectComponentTypes(components: Array<Component>):
15
15
  export declare function getComponentUid(component?: Component | null): string | null;
16
16
  export declare function componentIsApp(component?: Component | null): component is Component<PublicAppComponentConfig | PrivateAppComponentConfig>;
17
17
  export declare function componentIsPublicApp(component?: Component | null): component is Component<PublicAppComponentConfig>;
18
- export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev): component is AppIRNode;
18
+ export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev | IntermediateRepresentationNode): component is AppIRNode;
@@ -1,4 +1,5 @@
1
1
  import { FileResult } from 'tmp';
2
+ import { IntermediateRepresentation } from '@hubspot/project-parsing-lib';
2
3
  import { ProjectConfig } from '../../types/Projects';
3
4
  type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
4
5
  type ProjectUploadResult<T> = {
@@ -20,5 +21,5 @@ type HandleProjectUploadArg<T> = {
20
21
  export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
21
22
  export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
22
23
  export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
23
- export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<unknown>;
24
+ export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
24
25
  export {};
@@ -149,4 +149,5 @@ async function handleTranslate(projectDir, projectConfig, accountId, skipValidat
149
149
  (0, errorHandlers_1.logError)(e);
150
150
  }
151
151
  }
152
+ return undefined;
152
153
  }
@@ -29,7 +29,7 @@ async function personalAccessKeyPrompt({ env, account, }) {
29
29
  if (account) {
30
30
  url = `${websiteOrigin}/personal-access-key/${account}`;
31
31
  }
32
- const { personalAcessKeyBrowserOpenPrep: choice } = await (0, promptUtils_1.promptUser)([
32
+ const { personalAccessKeyBrowserOpenPrep: choice } = await (0, promptUtils_1.promptUser)([
33
33
  PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP,
34
34
  ]);
35
35
  if (!choice) {
@@ -94,7 +94,7 @@ const CLIENT_SECRET = {
94
94
  },
95
95
  };
96
96
  const PERSONAL_ACCESS_KEY_BROWSER_OPEN_PREP = {
97
- name: 'personalAcessKeyBrowserOpenPrep',
97
+ name: 'personalAccessKeyBrowserOpenPrep',
98
98
  type: 'list',
99
99
  message: 'Choose your preferred method of authentication',
100
100
  choices: Object.values(en_1.lib.prompts.personalAccessKeyPrompt.personalAccessKeyPromptChoices),
@@ -0,0 +1,3 @@
1
+ import { PromptOptionsArg, ProjectNameAndDestPromptResponse } from './selectProjectTemplatePrompt';
2
+ export declare function projectNameAndDestPrompt(promptOptions: PromptOptionsArg): Promise<ProjectNameAndDestPromptResponse>;
3
+ export declare function validateProjectDirectory(input?: string): string | boolean;
@@ -0,0 +1,60 @@
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.projectNameAndDestPrompt = projectNameAndDestPrompt;
7
+ exports.validateProjectDirectory = validateProjectDirectory;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const path_2 = require("@hubspot/local-dev-lib/path");
11
+ const en_1 = require("../../lang/en");
12
+ const promptUtils_1 = require("./promptUtils");
13
+ const constants_1 = require("../constants");
14
+ async function projectNameAndDestPrompt(promptOptions) {
15
+ const result = await (0, promptUtils_1.promptUser)([
16
+ {
17
+ name: 'name',
18
+ message: en_1.lib.prompts.projectNameAndDestPrompt.enterName,
19
+ when: !promptOptions.name,
20
+ validate: (input) => {
21
+ if (!input) {
22
+ return en_1.lib.prompts.projectNameAndDestPrompt.errors.nameRequired;
23
+ }
24
+ return true;
25
+ },
26
+ },
27
+ {
28
+ name: 'dest',
29
+ message: en_1.lib.prompts.projectNameAndDestPrompt.enterDest,
30
+ when: !promptOptions.dest,
31
+ default: answers => {
32
+ const projectName = (0, path_2.sanitizeFileName)(promptOptions.name || answers.name);
33
+ return path_1.default.resolve((0, path_2.getCwd)(), projectName);
34
+ },
35
+ validate: validateProjectDirectory,
36
+ filter: input => {
37
+ return (0, path_2.untildify)(input);
38
+ },
39
+ },
40
+ ]);
41
+ if (!result.name) {
42
+ result.name = promptOptions.name;
43
+ }
44
+ if (!result.dest) {
45
+ result.dest = promptOptions.dest;
46
+ }
47
+ return result;
48
+ }
49
+ function validateProjectDirectory(input) {
50
+ if (!input) {
51
+ return en_1.lib.prompts.projectNameAndDestPrompt.errors.destRequired;
52
+ }
53
+ if (fs_1.default.existsSync(path_1.default.resolve((0, path_2.getCwd)(), path_1.default.join(input, constants_1.PROJECT_CONFIG_FILE)))) {
54
+ return en_1.lib.prompts.projectNameAndDestPrompt.errors.invalidDest;
55
+ }
56
+ if (!(0, path_2.isValidPath)(input)) {
57
+ return en_1.lib.prompts.projectNameAndDestPrompt.errors.invalidCharacters;
58
+ }
59
+ return true;
60
+ }