@hubspot/cli 7.7.16-experimental.1 → 7.7.16-experimental.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/account/auth.js +3 -3
- package/commands/app/install.d.ts +8 -0
- package/commands/app/install.js +127 -0
- package/commands/app.js +6 -1
- package/commands/auth.js +23 -25
- package/commands/getStarted.js +55 -8
- package/commands/init.js +29 -31
- package/commands/project/cloneApp.js +4 -4
- package/commands/project/create.js +9 -9
- package/commands/project/dev/deprecatedFlow.js +4 -4
- package/commands/project/dev/index.js +5 -5
- package/commands/project/dev/unifiedFlow.js +8 -0
- package/commands/sandbox/delete.js +5 -5
- package/commands/testAccount/create.js +53 -3
- package/lang/en.d.ts +67 -15
- package/lang/en.js +64 -12
- package/lib/accountTypes.d.ts +1 -0
- package/lib/accountTypes.js +20 -9
- package/lib/app/migrate_legacy.js +2 -3
- package/lib/app/urls.d.ts +1 -1
- package/lib/commonOpts.js +1 -1
- package/lib/middleware/__test__/configMiddleware.test.js +2 -2
- package/lib/middleware/configMiddleware.js +10 -2
- package/lib/parsing.d.ts +1 -0
- package/lib/parsing.js +11 -0
- package/lib/polling.d.ts +1 -1
- package/lib/polling.js +11 -1
- package/lib/projects/add/v3AddComponent.js +4 -0
- package/lib/projects/create/index.d.ts +3 -2
- package/lib/projects/create/index.js +11 -5
- package/lib/projects/create/v3.d.ts +3 -3
- package/lib/projects/create/v3.js +2 -2
- package/lib/projects/localDev/AppDevModeInterface.js +1 -1
- package/lib/projects/localDev/LocalDevProcess.d.ts +3 -2
- package/lib/projects/localDev/LocalDevProcess.js +16 -12
- package/lib/projects/localDev/LocalDevState.d.ts +10 -5
- package/lib/projects/localDev/LocalDevState.js +18 -20
- package/lib/projects/localDev/LocalDevWatcher.js +1 -1
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +2 -1
- package/lib/projects/upload.js +1 -0
- package/lib/prompts/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectNameAndDestPrompt.d.ts +3 -0
- package/lib/prompts/projectNameAndDestPrompt.js +60 -0
- package/lib/prompts/selectProjectTemplatePrompt.d.ts +26 -0
- package/lib/prompts/{createProjectPrompt.js → selectProjectTemplatePrompt.js} +6 -55
- package/lib/validation.d.ts +1 -1
- package/lib/validation.js +4 -4
- package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
- package/package.json +3 -3
- package/types/LocalDev.d.ts +1 -0
- package/types/Yargs.d.ts +1 -1
- package/lib/prompts/createProjectPrompt.d.ts +0 -28
|
@@ -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
|
|
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
|
|
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
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.
|
|
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.
|
|
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.
|
|
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.
|
|
35
|
+
argv.userProvidedAccount = account;
|
|
33
36
|
if (argv.useEnv && process.env.HUBSPOT_ACCOUNT_ID) {
|
|
34
|
-
|
|
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);
|
package/lib/parsing.d.ts
ADDED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
32
|
-
return {
|
|
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 {
|
|
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({
|
|
20
|
-
|
|
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({
|
|
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 =
|
|
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) {
|
|
@@ -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(
|
|
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
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
81
|
-
return this.
|
|
82
|
-
}
|
|
83
|
-
get configFilesUpdatedSinceLastUpload() {
|
|
84
|
-
return this._configFilesUpdatedSinceLastUpload;
|
|
81
|
+
get projectNodesAtLastUpload() {
|
|
82
|
+
return structuredClone(this._projectNodesAtLastUpload);
|
|
85
83
|
}
|
|
86
|
-
|
|
87
|
-
this.
|
|
84
|
+
set projectNodesAtLastUpload(nodes) {
|
|
85
|
+
this._projectNodesAtLastUpload = nodes;
|
|
88
86
|
}
|
|
89
|
-
|
|
90
|
-
this.
|
|
87
|
+
get env() {
|
|
88
|
+
return this._env;
|
|
91
89
|
}
|
|
92
90
|
get appData() {
|
|
93
|
-
return
|
|
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(
|
|
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;
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -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<
|
|
24
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
|
|
24
25
|
export {};
|
package/lib/projects/upload.js
CHANGED
|
@@ -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 {
|
|
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: '
|
|
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
|
+
}
|