@hubspot/cli 7.7.1-experimental.0 → 7.7.2-experimental.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.
- package/commands/account/auth.js +51 -82
- package/commands/auth.js +2 -15
- package/commands/config/migrate.js +17 -36
- package/commands/init.js +1 -2
- package/commands/module/marketplace-validate.js +6 -8
- package/commands/module.js +2 -1
- package/commands/project/add.d.ts +5 -2
- package/commands/project/add.js +43 -80
- package/commands/project/create.d.ts +2 -8
- package/commands/project/create.js +84 -55
- package/commands/project/dev/unifiedFlow.js +1 -0
- package/commands/remove.js +6 -12
- package/commands/theme/generate-selectors.js +7 -10
- package/commands/theme/marketplace-validate.js +6 -8
- package/commands/theme/preview.js +17 -18
- package/commands/theme.js +2 -2
- package/commands/upload.js +26 -63
- package/commands/watch.js +20 -32
- package/lang/en.d.ts +140 -92
- package/lang/en.js +143 -98
- package/lang/en.lyaml +3 -186
- package/lib/configMigrate.d.ts +2 -2
- package/lib/configMigrate.js +34 -69
- package/lib/constants.d.ts +23 -5
- package/lib/constants.js +24 -6
- package/lib/generateSelectors.js +3 -5
- package/lib/marketplaceValidate.d.ts +12 -2
- package/lib/marketplaceValidate.js +22 -29
- package/lib/middleware/configMiddleware.js +1 -0
- package/lib/projects/add/legacyAddComponent.d.ts +5 -0
- package/lib/projects/add/legacyAddComponent.js +48 -0
- package/lib/projects/add/v3AddComponent.d.ts +8 -0
- package/lib/projects/add/v3AddComponent.js +85 -0
- package/lib/projects/components.d.ts +2 -0
- package/lib/projects/components.js +82 -0
- package/lib/projects/create/index.d.ts +23 -0
- package/lib/projects/create/index.js +33 -0
- package/lib/projects/create/legacy.d.ts +6 -0
- package/lib/projects/{create.js → create/legacy.js} +20 -11
- package/lib/projects/create/v3.d.ts +27 -0
- package/lib/projects/create/v3.js +158 -0
- package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -2
- package/lib/projects/localDev/AppDevModeInterface.js +38 -2
- package/lib/projects/localDev/LocalDevProcess.d.ts +12 -5
- package/lib/projects/localDev/LocalDevProcess.js +47 -17
- package/lib/projects/localDev/LocalDevState.d.ts +16 -3
- package/lib/projects/localDev/LocalDevState.js +43 -2
- package/lib/projects/localDev/LocalDevWatcher.js +3 -6
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +3 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.js +48 -9
- package/lib/prompts/createProjectPrompt.d.ts +14 -5
- package/lib/prompts/createProjectPrompt.js +36 -13
- package/lib/prompts/projectAddPrompt.d.ts +5 -1
- package/lib/prompts/projectAddPrompt.js +35 -7
- package/lib/prompts/setAsDefaultAccountPrompt.js +10 -0
- package/package.json +6 -5
- package/types/LocalDev.d.ts +11 -1
- package/types/Projects.d.ts +19 -2
- package/lib/projects/create.d.ts +0 -5
|
@@ -0,0 +1,48 @@
|
|
|
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.legacyAddComponent = legacyAddComponent;
|
|
7
|
+
const Projects_1 = require("../../../types/Projects");
|
|
8
|
+
const structure_1 = require("../structure");
|
|
9
|
+
const errorHandlers_1 = require("../../errorHandlers");
|
|
10
|
+
const en_1 = require("../../../lang/en");
|
|
11
|
+
const legacy_1 = require("../create/legacy");
|
|
12
|
+
const projectAddPrompt_1 = require("../../prompts/projectAddPrompt");
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const constants_1 = require("../../constants");
|
|
15
|
+
const github_1 = require("@hubspot/local-dev-lib/github");
|
|
16
|
+
const logger_1 = require("../../ui/logger");
|
|
17
|
+
async function legacyAddComponent(args, projectDir, projectConfig) {
|
|
18
|
+
// We currently only support adding private apps to projects
|
|
19
|
+
let projectContainsPublicApp = false;
|
|
20
|
+
try {
|
|
21
|
+
const components = await (0, structure_1.findProjectComponents)(projectDir);
|
|
22
|
+
projectContainsPublicApp = components.some(c => c.type === Projects_1.ComponentTypes.PublicApp);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
(0, errorHandlers_1.debugError)(err);
|
|
26
|
+
}
|
|
27
|
+
if (projectContainsPublicApp) {
|
|
28
|
+
throw new Error(en_1.commands.project.add.error.projectContainsPublicApp);
|
|
29
|
+
}
|
|
30
|
+
logger_1.uiLogger.log(en_1.commands.project.add.creatingComponent(projectConfig.name));
|
|
31
|
+
const components = await (0, legacy_1.getProjectComponentListFromRepo)(projectConfig.platformVersion);
|
|
32
|
+
if (!components || !components.length) {
|
|
33
|
+
throw new Error(en_1.commands.project.add.error.failedToFetchComponentList);
|
|
34
|
+
}
|
|
35
|
+
const projectAddPromptResponse = await (0, projectAddPrompt_1.projectAddPrompt)(components, args);
|
|
36
|
+
try {
|
|
37
|
+
const componentPath = path_1.default.join(projectDir, projectConfig.srcDir, projectAddPromptResponse.name);
|
|
38
|
+
await (0, github_1.cloneGithubRepo)(constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, componentPath, {
|
|
39
|
+
sourceDir: projectAddPromptResponse.componentTemplate.path,
|
|
40
|
+
branch: 'main',
|
|
41
|
+
hideLogs: true,
|
|
42
|
+
});
|
|
43
|
+
logger_1.uiLogger.success(en_1.commands.project.add.success(projectAddPromptResponse.name));
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw new Error(en_1.commands.project.add.error.failedToDownloadComponent);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ProjectConfig } from '../../../types/Projects';
|
|
2
|
+
export declare function v3AddComponent(args: {
|
|
3
|
+
name?: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
features?: string[];
|
|
6
|
+
auth?: string;
|
|
7
|
+
distribution?: string;
|
|
8
|
+
}, projectDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
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.v3AddComponent = v3AddComponent;
|
|
7
|
+
const en_1 = require("../../../lang/en");
|
|
8
|
+
const legacy_1 = require("../create/legacy");
|
|
9
|
+
const v3_1 = require("../create/v3");
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const projectAddPrompt_1 = require("../../prompts/projectAddPrompt");
|
|
13
|
+
const constants_1 = require("../../constants");
|
|
14
|
+
const components_1 = require("../components");
|
|
15
|
+
const project_1 = require("@hubspot/project-parsing-lib/src/lib/project");
|
|
16
|
+
const constants_2 = require("@hubspot/project-parsing-lib/src/lib/constants");
|
|
17
|
+
const github_1 = require("@hubspot/local-dev-lib/github");
|
|
18
|
+
const errorHandlers_1 = require("../../errorHandlers");
|
|
19
|
+
const logger_1 = require("../../ui/logger");
|
|
20
|
+
async function v3AddComponent(args, projectDir, projectConfig) {
|
|
21
|
+
logger_1.uiLogger.log(en_1.commands.project.add.creatingComponent(projectConfig.name));
|
|
22
|
+
const config = await (0, legacy_1.getConfigForPlatformVersion)(projectConfig.platformVersion);
|
|
23
|
+
const { components, parentComponents } = config;
|
|
24
|
+
if (!components || !components.length) {
|
|
25
|
+
throw new Error(en_1.commands.project.add.error.failedToFetchComponentList);
|
|
26
|
+
}
|
|
27
|
+
const projectSrcDirectory = path_1.default.join(projectDir, projectConfig.srcDir);
|
|
28
|
+
const projectMetadata = await (0, project_1.getProjectMetadata)(projectSrcDirectory);
|
|
29
|
+
let derivedAuthType;
|
|
30
|
+
let derivedDistribution;
|
|
31
|
+
const appsMetadata = projectMetadata.components[constants_2.AppKey];
|
|
32
|
+
const shouldCreateApp = appsMetadata.count === 0;
|
|
33
|
+
if (shouldCreateApp) {
|
|
34
|
+
const { authType, distribution } = await (0, v3_1.createV3App)(args.auth, args.distribution);
|
|
35
|
+
derivedDistribution = distribution;
|
|
36
|
+
derivedAuthType = authType;
|
|
37
|
+
}
|
|
38
|
+
else if (appsMetadata.count > appsMetadata.maxCount) {
|
|
39
|
+
throw new Error(en_1.lib.projects.create.errors.exceededMaxNumberOfApps(appsMetadata.maxCount));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const apps = appsMetadata.hsMetaFiles.map(appLoc => {
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(fs_1.default.readFileSync(appLoc, 'utf8'));
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throw new Error(en_1.lib.projects.create.errors.unableToParseAppConfig(appLoc));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
derivedDistribution = apps[0].config?.distribution;
|
|
51
|
+
derivedAuthType = apps[0].config?.auth?.type;
|
|
52
|
+
}
|
|
53
|
+
const componentTemplateChoices = (0, v3_1.calculateComponentTemplateChoices)(components, derivedAuthType, derivedDistribution, projectMetadata);
|
|
54
|
+
const projectAddPromptResponse = await (0, projectAddPrompt_1.projectAddPromptV3)(componentTemplateChoices, args.features);
|
|
55
|
+
try {
|
|
56
|
+
const components = projectAddPromptResponse.componentTemplate?.map((componentTemplate) => {
|
|
57
|
+
return path_1.default.join(projectConfig.platformVersion, componentTemplate.path);
|
|
58
|
+
}) || [];
|
|
59
|
+
if (shouldCreateApp) {
|
|
60
|
+
const parentComponent = parentComponents?.find(possibleParent => {
|
|
61
|
+
return (possibleParent.type === v3_1.PROJECT_WITH_APP &&
|
|
62
|
+
possibleParent.authType === derivedAuthType &&
|
|
63
|
+
possibleParent.distribution === derivedDistribution);
|
|
64
|
+
});
|
|
65
|
+
if (parentComponent) {
|
|
66
|
+
components.push(path_1.default.join(projectConfig.platformVersion, parentComponent.path));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
await (0, github_1.cloneGithubRepo)(constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, projectDir, {
|
|
70
|
+
sourceDir: components,
|
|
71
|
+
hideLogs: true,
|
|
72
|
+
branch: 'main',
|
|
73
|
+
handleCollision: components_1.handleComponentCollision,
|
|
74
|
+
});
|
|
75
|
+
logger_1.uiLogger.success(en_1.commands.project.add.success(projectAddPromptResponse.componentTemplate
|
|
76
|
+
.map(template => `'${template.label}'`)
|
|
77
|
+
.join(', '), projectAddPromptResponse.componentTemplate.length > 1));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
(0, errorHandlers_1.debugError)(error);
|
|
81
|
+
throw new Error(en_1.commands.project.add.error.failedToDownloadComponent, {
|
|
82
|
+
cause: error,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
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.handleComponentCollision = handleComponentCollision;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const project_parsing_lib_1 = require("@hubspot/project-parsing-lib");
|
|
10
|
+
// Handles a collision between component source files
|
|
11
|
+
function handleComponentCollision({ dest, src, collisions }) {
|
|
12
|
+
const hsMetaFiles = [];
|
|
13
|
+
const packageJsonFiles = [];
|
|
14
|
+
const sourceFiles = [];
|
|
15
|
+
collisions.forEach(collision => {
|
|
16
|
+
if (collision.endsWith(project_parsing_lib_1.metafileExtension)) {
|
|
17
|
+
hsMetaFiles.push(collision);
|
|
18
|
+
}
|
|
19
|
+
else if (path_1.default.parse(collision).base === 'package.json') {
|
|
20
|
+
packageJsonFiles.push(collision);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
sourceFiles.push(collision);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const sourceFilenameMapping = sourceFiles.reduce((acc, filename) => {
|
|
27
|
+
const { name, ext, dir } = path_1.default.parse(filename);
|
|
28
|
+
return {
|
|
29
|
+
...acc,
|
|
30
|
+
[filename]: path_1.default.join(dir, `${name}-${Date.now()}${ext}`),
|
|
31
|
+
};
|
|
32
|
+
}, {});
|
|
33
|
+
const metafileExtensionPrefix = path_1.default.parse(project_parsing_lib_1.metafileExtension).name;
|
|
34
|
+
const metaFilenameMapping = hsMetaFiles.reduce((acc, filename) => {
|
|
35
|
+
const { name, dir } = path_1.default.parse(filename);
|
|
36
|
+
return {
|
|
37
|
+
...acc,
|
|
38
|
+
[filename]: path_1.default.join(dir, `${name.replace(metafileExtensionPrefix, '')}-${Date.now()}${project_parsing_lib_1.metafileExtension}`),
|
|
39
|
+
};
|
|
40
|
+
}, {});
|
|
41
|
+
// Update the metafiles that might contain references to the old filenames
|
|
42
|
+
hsMetaFiles.forEach(file => {
|
|
43
|
+
updateMetaFile({
|
|
44
|
+
dest,
|
|
45
|
+
src,
|
|
46
|
+
file,
|
|
47
|
+
sourceFilenameMapping,
|
|
48
|
+
metaFilenameMapping,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
// Copy the renamed files into their new destination location
|
|
52
|
+
Object.entries(sourceFilenameMapping).forEach(([key, value]) => {
|
|
53
|
+
fs_1.default.copyFileSync(path_1.default.join(src, key), path_1.default.join(dest, value));
|
|
54
|
+
});
|
|
55
|
+
if (packageJsonFiles.length) {
|
|
56
|
+
handlePackageJsonCollisions(dest, src, packageJsonFiles);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function updateMetaFile({ dest, src, file, sourceFilenameMapping, metaFilenameMapping, }) {
|
|
60
|
+
let text = fs_1.default.readFileSync(path_1.default.join(src, file), 'utf-8');
|
|
61
|
+
Object.entries(sourceFilenameMapping).forEach(([key, value]) => {
|
|
62
|
+
const { base: oldFileName } = path_1.default.parse(key);
|
|
63
|
+
const { base: newFileName } = path_1.default.parse(value);
|
|
64
|
+
text = text.replace(oldFileName, newFileName);
|
|
65
|
+
});
|
|
66
|
+
fs_1.default.writeFileSync(path_1.default.join(dest, metaFilenameMapping[file]), text);
|
|
67
|
+
}
|
|
68
|
+
function handlePackageJsonCollisions(dest, src, packageJsonFiles) {
|
|
69
|
+
packageJsonFiles.forEach(file => {
|
|
70
|
+
const existingPackageJsonContents = JSON.parse(fs_1.default.readFileSync(path_1.default.join(dest, file), 'utf-8'));
|
|
71
|
+
const newPackageJsonContents = JSON.parse(fs_1.default.readFileSync(path_1.default.join(src, file), 'utf-8'));
|
|
72
|
+
existingPackageJsonContents.dependencies = {
|
|
73
|
+
...newPackageJsonContents.dependencies,
|
|
74
|
+
...existingPackageJsonContents.dependencies,
|
|
75
|
+
};
|
|
76
|
+
existingPackageJsonContents.devDependencies = {
|
|
77
|
+
...newPackageJsonContents.devDependencies,
|
|
78
|
+
...existingPackageJsonContents.devDependencies,
|
|
79
|
+
};
|
|
80
|
+
fs_1.default.writeFileSync(path_1.default.join(dest, file), JSON.stringify(existingPackageJsonContents, null, 2));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ArgumentsCamelCase } from 'yargs';
|
|
2
|
+
import { ProjectTemplateRepoConfig } from '../../../types/Projects';
|
|
3
|
+
import { CreateProjectPromptResponse } from '../../prompts/createProjectPrompt';
|
|
4
|
+
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs } from '../../../types/Yargs';
|
|
5
|
+
import { RepoPath } from '@hubspot/local-dev-lib/types/Github';
|
|
6
|
+
export type ProjectCreateArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
|
|
7
|
+
name?: string;
|
|
8
|
+
dest?: string;
|
|
9
|
+
templateSource?: RepoPath;
|
|
10
|
+
template?: string;
|
|
11
|
+
features?: string[];
|
|
12
|
+
platformVersion: string;
|
|
13
|
+
projectBase?: string;
|
|
14
|
+
auth?: string;
|
|
15
|
+
distribution?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function handleProjectCreationFlow(args: ArgumentsCamelCase<ProjectCreateArgs>): Promise<{
|
|
18
|
+
authType?: string;
|
|
19
|
+
distribution?: string;
|
|
20
|
+
repoConfig?: ProjectTemplateRepoConfig;
|
|
21
|
+
projectContents?: string;
|
|
22
|
+
createProjectPromptResponse: CreateProjectPromptResponse;
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleProjectCreationFlow = handleProjectCreationFlow;
|
|
4
|
+
const createProjectPrompt_1 = require("../../prompts/createProjectPrompt");
|
|
5
|
+
const constants_1 = require("../../constants");
|
|
6
|
+
const buildAndDeploy_1 = require("../buildAndDeploy");
|
|
7
|
+
const v3_1 = require("./v3");
|
|
8
|
+
const legacy_1 = require("./legacy");
|
|
9
|
+
const logger_1 = require("../../ui/logger");
|
|
10
|
+
const en_1 = require("../../../lang/en");
|
|
11
|
+
const exitCodes_1 = require("../../enums/exitCodes");
|
|
12
|
+
async function handleProjectCreationFlow(args) {
|
|
13
|
+
const { platformVersion, templateSource, projectBase, auth: providedAuth, distribution: providedDistribution, } = args;
|
|
14
|
+
const repo = templateSource || constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH;
|
|
15
|
+
if ((0, buildAndDeploy_1.useV3Api)(platformVersion)) {
|
|
16
|
+
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);
|
|
18
|
+
return {
|
|
19
|
+
authType,
|
|
20
|
+
distribution,
|
|
21
|
+
repoConfig,
|
|
22
|
+
projectContents,
|
|
23
|
+
createProjectPromptResponse,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const projectTemplates = await (0, legacy_1.getProjectTemplateListFromRepo)(repo, 'main');
|
|
27
|
+
if (!projectTemplates.length) {
|
|
28
|
+
logger_1.uiLogger.error(en_1.commands.project.create.errors.failedToFetchProjectList);
|
|
29
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
30
|
+
}
|
|
31
|
+
const createProjectPromptResponse = await (0, createProjectPrompt_1.createProjectPrompt)(args, projectTemplates);
|
|
32
|
+
return { createProjectPromptResponse };
|
|
33
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RepoPath } from '@hubspot/local-dev-lib/types/Github';
|
|
2
|
+
import { ProjectTemplate, ComponentTemplate, ProjectTemplateRepoConfig } from '../../../types/Projects';
|
|
3
|
+
export declare const EMPTY_PROJECT_TEMPLATE_NAME = "no-template";
|
|
4
|
+
export declare function getConfigForPlatformVersion(platformVersion: string): Promise<ProjectTemplateRepoConfig> | never;
|
|
5
|
+
export declare function getProjectComponentListFromRepo(platformVersion: string): Promise<ComponentTemplate[]>;
|
|
6
|
+
export declare function getProjectTemplateListFromRepo(templateSource: RepoPath, githubRef: string): Promise<ProjectTemplate[]>;
|
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EMPTY_PROJECT_TEMPLATE_NAME = void 0;
|
|
4
|
+
exports.getConfigForPlatformVersion = getConfigForPlatformVersion;
|
|
4
5
|
exports.getProjectComponentListFromRepo = getProjectComponentListFromRepo;
|
|
5
6
|
exports.getProjectTemplateListFromRepo = getProjectTemplateListFromRepo;
|
|
6
7
|
const github_1 = require("@hubspot/local-dev-lib/api/github");
|
|
7
|
-
const constants_1 = require("
|
|
8
|
-
const exitCodes_1 = require("
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
8
|
+
const constants_1 = require("../../constants");
|
|
9
|
+
const exitCodes_1 = require("../../enums/exitCodes");
|
|
10
|
+
const errorHandlers_1 = require("../../errorHandlers");
|
|
11
|
+
const logger_1 = require("../../ui/logger");
|
|
12
|
+
const buildAndDeploy_1 = require("../buildAndDeploy");
|
|
13
|
+
const en_1 = require("../../../lang/en");
|
|
14
|
+
const PROJECT_TEMPLATE_PROPERTIES = ['name', 'label', 'path'];
|
|
12
15
|
exports.EMPTY_PROJECT_TEMPLATE_NAME = 'no-template';
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
async function getConfigForPlatformVersion(platformVersion) {
|
|
17
|
+
let path = '';
|
|
18
|
+
if ((0, buildAndDeploy_1.useV3Api)(platformVersion)) {
|
|
19
|
+
path = `${platformVersion}/`;
|
|
20
|
+
}
|
|
21
|
+
const { data } = await (0, github_1.fetchRepoFile)(constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, `${path}config.json`, 'main');
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
async function getProjectComponentListFromRepo(platformVersion) {
|
|
15
25
|
let config;
|
|
16
26
|
try {
|
|
17
|
-
|
|
18
|
-
config = data;
|
|
27
|
+
config = await getConfigForPlatformVersion(platformVersion);
|
|
19
28
|
}
|
|
20
29
|
catch (err) {
|
|
21
|
-
(0,
|
|
30
|
+
(0, errorHandlers_1.debugError)(err);
|
|
22
31
|
}
|
|
23
32
|
if (config) {
|
|
24
33
|
return config[constants_1.PROJECT_COMPONENT_TYPES.COMPONENTS] || [];
|
|
@@ -32,7 +41,7 @@ async function getProjectTemplateListFromRepo(templateSource, githubRef) {
|
|
|
32
41
|
config = data;
|
|
33
42
|
}
|
|
34
43
|
catch (e) {
|
|
35
|
-
(0,
|
|
44
|
+
(0, errorHandlers_1.debugError)(e);
|
|
36
45
|
logger_1.uiLogger.error(en_1.lib.projects.create.errors.missingConfigFileTemplateSource);
|
|
37
46
|
return process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
38
47
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ComponentTemplate, ComponentTemplateChoice, ProjectTemplateRepoConfig } from '../../../types/Projects';
|
|
2
|
+
import { ProjectMetadata } from '@hubspot/project-parsing-lib/src/lib/project';
|
|
3
|
+
import { CreateProjectPromptResponse } from '../../prompts/createProjectPrompt';
|
|
4
|
+
export declare const EMPTY_PROJECT = "empty";
|
|
5
|
+
export declare const PROJECT_WITH_APP = "app";
|
|
6
|
+
export declare function createV3App(providedAuth: string | undefined, providedDistribution: string | undefined): Promise<{
|
|
7
|
+
authType: string;
|
|
8
|
+
distribution: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function calculateComponentTemplateChoices(components: ComponentTemplate[], authType: string | undefined, distribution: string | undefined, projectMetadata?: ProjectMetadata): ComponentTemplateChoice[];
|
|
11
|
+
type V3ComponentInfo = {
|
|
12
|
+
authType?: string;
|
|
13
|
+
distribution?: string;
|
|
14
|
+
repoConfig?: ProjectTemplateRepoConfig;
|
|
15
|
+
projectContents?: string;
|
|
16
|
+
componentTemplateChoices?: ComponentTemplateChoice[];
|
|
17
|
+
};
|
|
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;
|
|
21
|
+
platformVersion: string;
|
|
22
|
+
repoConfig?: ProjectTemplateRepoConfig;
|
|
23
|
+
projectContents?: string;
|
|
24
|
+
authType?: string;
|
|
25
|
+
distribution?: string;
|
|
26
|
+
}): string[];
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
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.PROJECT_WITH_APP = exports.EMPTY_PROJECT = void 0;
|
|
7
|
+
exports.createV3App = createV3App;
|
|
8
|
+
exports.calculateComponentTemplateChoices = calculateComponentTemplateChoices;
|
|
9
|
+
exports.v3ComponentFlow = v3ComponentFlow;
|
|
10
|
+
exports.generateComponentPaths = generateComponentPaths;
|
|
11
|
+
const constants_1 = require("../../constants");
|
|
12
|
+
const en_1 = require("../../../lang/en");
|
|
13
|
+
const promptUtils_1 = require("../../prompts/promptUtils");
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
15
|
+
const buildAndDeploy_1 = require("../buildAndDeploy");
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const legacy_1 = require("./legacy");
|
|
18
|
+
const errorHandlers_1 = require("../../errorHandlers");
|
|
19
|
+
const exitCodes_1 = require("../../enums/exitCodes");
|
|
20
|
+
const inquirer = require('inquirer');
|
|
21
|
+
exports.EMPTY_PROJECT = 'empty';
|
|
22
|
+
exports.PROJECT_WITH_APP = 'app';
|
|
23
|
+
async function createV3App(providedAuth, providedDistribution) {
|
|
24
|
+
let authType;
|
|
25
|
+
if (providedAuth &&
|
|
26
|
+
providedDistribution === constants_1.marketplaceDistribution &&
|
|
27
|
+
providedAuth !== constants_1.oAuth) {
|
|
28
|
+
throw new Error(en_1.lib.projects.create.errors.invalidAuthDistCombo(providedAuth, providedDistribution));
|
|
29
|
+
}
|
|
30
|
+
const distribution = providedDistribution ||
|
|
31
|
+
(await (0, promptUtils_1.listPrompt)(en_1.lib.projects.create.prompt.distribution, {
|
|
32
|
+
choices: [
|
|
33
|
+
{
|
|
34
|
+
name: en_1.lib.projects.create.prompt.marketPlaceDistribution,
|
|
35
|
+
value: constants_1.marketplaceDistribution,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: en_1.lib.projects.create.prompt.privateDistribution,
|
|
39
|
+
value: constants_1.privateDistribution,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
}));
|
|
43
|
+
if (distribution === constants_1.marketplaceDistribution) {
|
|
44
|
+
// This is the only valid auth type for marketplace
|
|
45
|
+
authType = constants_1.oAuth;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
authType =
|
|
49
|
+
providedAuth ||
|
|
50
|
+
(await (0, promptUtils_1.listPrompt)(en_1.lib.projects.create.prompt.auth, {
|
|
51
|
+
choices: [
|
|
52
|
+
{ name: en_1.lib.projects.create.prompt.staticAuth, value: constants_1.staticAuth },
|
|
53
|
+
{ name: en_1.lib.projects.create.prompt.oauth, value: constants_1.oAuth },
|
|
54
|
+
],
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
distribution,
|
|
59
|
+
authType,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function calculateComponentTemplateChoices(components, authType, distribution, projectMetadata) {
|
|
63
|
+
const enabledComponents = [];
|
|
64
|
+
const disabledComponents = [];
|
|
65
|
+
components.forEach(template => {
|
|
66
|
+
const { supportedAuthTypes, supportedDistributions } = template;
|
|
67
|
+
const disabledReasons = [];
|
|
68
|
+
if (projectMetadata) {
|
|
69
|
+
const { count, maxCount } = projectMetadata.components[template.type];
|
|
70
|
+
if (count >= maxCount) {
|
|
71
|
+
disabledReasons.push(en_1.commands.project.add.error.maxExceeded(maxCount));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (Array.isArray(supportedAuthTypes) &&
|
|
75
|
+
authType &&
|
|
76
|
+
!supportedAuthTypes.includes(authType)) {
|
|
77
|
+
disabledReasons.push(en_1.commands.project.add.error.authTypeNotAllowed(authType));
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(supportedDistributions) &&
|
|
80
|
+
distribution &&
|
|
81
|
+
!supportedDistributions.includes(distribution)) {
|
|
82
|
+
disabledReasons.push(en_1.commands.project.add.error.distributionNotAllowed(distribution));
|
|
83
|
+
}
|
|
84
|
+
if (disabledReasons.length > 0) {
|
|
85
|
+
disabledComponents.push({
|
|
86
|
+
name: `[${chalk_1.default.yellow('DISABLED')}] ${template.label}`,
|
|
87
|
+
value: template,
|
|
88
|
+
disabled: disabledReasons.join(' '),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
enabledComponents.push({
|
|
93
|
+
name: template.label,
|
|
94
|
+
value: template,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return disabledComponents.length
|
|
99
|
+
? [...enabledComponents, new inquirer.Separator(), ...disabledComponents]
|
|
100
|
+
: [...enabledComponents];
|
|
101
|
+
}
|
|
102
|
+
async function v3ComponentFlow(platformVersion, projectBase, providedAuth, providedDistribution) {
|
|
103
|
+
let repoConfig = undefined;
|
|
104
|
+
let authType;
|
|
105
|
+
let distribution;
|
|
106
|
+
try {
|
|
107
|
+
repoConfig = await (0, legacy_1.getConfigForPlatformVersion)(platformVersion);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
(0, errorHandlers_1.logError)(error);
|
|
111
|
+
return process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
112
|
+
}
|
|
113
|
+
const projectContentsChoice = projectBase ||
|
|
114
|
+
(await (0, promptUtils_1.listPrompt)(en_1.commands.project.create.prompts.parentComponents, {
|
|
115
|
+
choices: [
|
|
116
|
+
{
|
|
117
|
+
name: en_1.commands.project.create.prompts.emptyProject,
|
|
118
|
+
value: exports.EMPTY_PROJECT,
|
|
119
|
+
},
|
|
120
|
+
{ name: en_1.commands.project.create.prompts.app, value: exports.PROJECT_WITH_APP },
|
|
121
|
+
],
|
|
122
|
+
}));
|
|
123
|
+
if (projectContentsChoice === exports.PROJECT_WITH_APP) {
|
|
124
|
+
const { authType: selectedAuthType, distribution: selectedDistribution } = await createV3App(providedAuth, providedDistribution);
|
|
125
|
+
authType = selectedAuthType;
|
|
126
|
+
distribution = selectedDistribution;
|
|
127
|
+
}
|
|
128
|
+
const componentTemplateChoices = calculateComponentTemplateChoices(repoConfig?.components || [], authType, distribution);
|
|
129
|
+
return {
|
|
130
|
+
componentTemplateChoices,
|
|
131
|
+
authType,
|
|
132
|
+
distribution,
|
|
133
|
+
projectContents: projectContentsChoice,
|
|
134
|
+
repoConfig,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function generateComponentPaths({ createProjectPromptResponse, platformVersion, repoConfig, projectContents, authType, distribution, }) {
|
|
138
|
+
if (!(0, buildAndDeploy_1.useV3Api)(platformVersion)) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
const components = createProjectPromptResponse.componentTemplates?.map((componentTemplate) => {
|
|
142
|
+
return path_1.default.join(platformVersion, componentTemplate.path);
|
|
143
|
+
}) || [];
|
|
144
|
+
if (projectContents && projectContents !== exports.EMPTY_PROJECT) {
|
|
145
|
+
const parentComponent = repoConfig?.parentComponents?.find(possibleParent => {
|
|
146
|
+
return (possibleParent.type === projectContents &&
|
|
147
|
+
possibleParent.authType === authType &&
|
|
148
|
+
possibleParent.distribution === distribution);
|
|
149
|
+
});
|
|
150
|
+
if (parentComponent) {
|
|
151
|
+
components.push(path_1.default.join(platformVersion, parentComponent.path));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (repoConfig?.defaultFiles) {
|
|
155
|
+
components.push(path_1.default.join(platformVersion, repoConfig?.defaultFiles));
|
|
156
|
+
}
|
|
157
|
+
return components;
|
|
158
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PublicApp } from '@hubspot/local-dev-lib/types/Apps';
|
|
2
1
|
import { AppIRNode } from '../../../types/ProjectComponents';
|
|
3
2
|
import LocalDevState from './LocalDevState';
|
|
4
3
|
import LocalDevLogger from './LocalDevLogger';
|
|
@@ -10,14 +9,16 @@ declare class AppDevModeInterface {
|
|
|
10
9
|
localDevState: LocalDevState;
|
|
11
10
|
localDevLogger: LocalDevLogger;
|
|
12
11
|
_appNode?: AppIRNode | null;
|
|
13
|
-
appData?: PublicApp;
|
|
14
12
|
marketplaceAppInstalls?: number;
|
|
15
13
|
constructor(options: AppDevModeInterfaceConstructorOptions);
|
|
16
14
|
private get appNode();
|
|
15
|
+
private get appData();
|
|
16
|
+
private set appData(value);
|
|
17
17
|
private getAppInstallUrl;
|
|
18
18
|
private fetchAppData;
|
|
19
19
|
private checkMarketplaceAppInstalls;
|
|
20
20
|
private checkTestAccountAppInstallation;
|
|
21
|
+
private setUpLocalDevServerMessageListeners;
|
|
21
22
|
setup(args: any): Promise<void>;
|
|
22
23
|
start(): Promise<void>;
|
|
23
24
|
fileChange(filePath: string, event: string): Promise<void>;
|
|
@@ -18,7 +18,6 @@ class AppDevModeInterface {
|
|
|
18
18
|
localDevState;
|
|
19
19
|
localDevLogger;
|
|
20
20
|
_appNode;
|
|
21
|
-
appData;
|
|
22
21
|
marketplaceAppInstalls;
|
|
23
22
|
constructor(options) {
|
|
24
23
|
this.localDevState = options.localDevState;
|
|
@@ -48,6 +47,18 @@ class AppDevModeInterface {
|
|
|
48
47
|
}
|
|
49
48
|
return this._appNode;
|
|
50
49
|
}
|
|
50
|
+
get appData() {
|
|
51
|
+
if (!this.appNode) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
return this.localDevState.getAppDataByUid(this.appNode.uid);
|
|
55
|
+
}
|
|
56
|
+
set appData(appData) {
|
|
57
|
+
if (!this.appNode) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
this.localDevState.setAppDataForUid(this.appNode.uid, appData);
|
|
61
|
+
}
|
|
51
62
|
async getAppInstallUrl() {
|
|
52
63
|
if (this.appNode?.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH) {
|
|
53
64
|
return (0, urls_1.getOauthAppInstallUrl)({
|
|
@@ -77,7 +88,12 @@ class AppDevModeInterface {
|
|
|
77
88
|
return;
|
|
78
89
|
}
|
|
79
90
|
const { data: { uniquePortalInstallCount }, } = await (0, appsDev_1.fetchPublicAppProductionInstallCounts)(appData.id, this.localDevState.targetProjectAccountId);
|
|
80
|
-
this.appData =
|
|
91
|
+
this.appData = {
|
|
92
|
+
id: appData.id,
|
|
93
|
+
clientId: appData.clientId,
|
|
94
|
+
name: appData.name,
|
|
95
|
+
installationState: constants_1.APP_INSTALLATION_STATES.NOT_INSTALLED,
|
|
96
|
+
};
|
|
81
97
|
this.marketplaceAppInstalls = uniquePortalInstallCount;
|
|
82
98
|
}
|
|
83
99
|
async checkMarketplaceAppInstalls() {
|
|
@@ -100,11 +116,30 @@ class AppDevModeInterface {
|
|
|
100
116
|
}
|
|
101
117
|
const { data: { isInstalledWithScopeGroups, previouslyAuthorizedScopeGroups }, } = await (0, localDevAuth_1.fetchAppInstallationData)(this.localDevState.targetTestingAccountId, this.localDevState.projectId, this.appNode.uid, this.appNode.config.auth.requiredScopes, this.appNode.config.auth.optionalScopes);
|
|
102
118
|
const isReinstall = previouslyAuthorizedScopeGroups.length > 0;
|
|
119
|
+
if (isInstalledWithScopeGroups) {
|
|
120
|
+
this.appData = {
|
|
121
|
+
...this.appData,
|
|
122
|
+
installationState: constants_1.APP_INSTALLATION_STATES.INSTALLED,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
else if (isReinstall) {
|
|
126
|
+
this.appData = {
|
|
127
|
+
...this.appData,
|
|
128
|
+
installationState: constants_1.APP_INSTALLATION_STATES.INSTALLED_WITH_OUTDATED_SCOPES,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
103
131
|
if (!isInstalledWithScopeGroups) {
|
|
104
132
|
const installUrl = await this.getAppInstallUrl();
|
|
105
133
|
await (0, installAppPrompt_1.installAppPrompt)(installUrl, isReinstall);
|
|
106
134
|
}
|
|
107
135
|
}
|
|
136
|
+
setUpLocalDevServerMessageListeners() {
|
|
137
|
+
this.localDevState.addListener('devServerMessage', message => {
|
|
138
|
+
if (message === constants_1.LOCAL_DEV_SERVER_MESSAGE_TYPES.WEBSOCKET_SERVER_CONNECTED) {
|
|
139
|
+
this.checkTestAccountAppInstallation();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
108
143
|
// @ts-expect-error TODO: reconcile types between CLI and UIE Dev Server
|
|
109
144
|
// In the future, update UIE Dev Server to use LocalDevState
|
|
110
145
|
async setup(args) {
|
|
@@ -121,6 +156,7 @@ class AppDevModeInterface {
|
|
|
121
156
|
catch (e) {
|
|
122
157
|
(0, index_1.logError)(e);
|
|
123
158
|
}
|
|
159
|
+
this.setUpLocalDevServerMessageListeners();
|
|
124
160
|
return ui_extensions_dev_server_1.DevModeUnifiedInterface.setup(args);
|
|
125
161
|
}
|
|
126
162
|
async start() {
|