@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.
Files changed (59) hide show
  1. package/commands/account/auth.js +51 -82
  2. package/commands/auth.js +2 -15
  3. package/commands/config/migrate.js +17 -36
  4. package/commands/init.js +1 -2
  5. package/commands/module/marketplace-validate.js +6 -8
  6. package/commands/module.js +2 -1
  7. package/commands/project/add.d.ts +5 -2
  8. package/commands/project/add.js +43 -80
  9. package/commands/project/create.d.ts +2 -8
  10. package/commands/project/create.js +84 -55
  11. package/commands/project/dev/unifiedFlow.js +1 -0
  12. package/commands/remove.js +6 -12
  13. package/commands/theme/generate-selectors.js +7 -10
  14. package/commands/theme/marketplace-validate.js +6 -8
  15. package/commands/theme/preview.js +17 -18
  16. package/commands/theme.js +2 -2
  17. package/commands/upload.js +26 -63
  18. package/commands/watch.js +20 -32
  19. package/lang/en.d.ts +140 -92
  20. package/lang/en.js +143 -98
  21. package/lang/en.lyaml +3 -186
  22. package/lib/configMigrate.d.ts +2 -2
  23. package/lib/configMigrate.js +34 -69
  24. package/lib/constants.d.ts +23 -5
  25. package/lib/constants.js +24 -6
  26. package/lib/generateSelectors.js +3 -5
  27. package/lib/marketplaceValidate.d.ts +12 -2
  28. package/lib/marketplaceValidate.js +22 -29
  29. package/lib/middleware/configMiddleware.js +1 -0
  30. package/lib/projects/add/legacyAddComponent.d.ts +5 -0
  31. package/lib/projects/add/legacyAddComponent.js +48 -0
  32. package/lib/projects/add/v3AddComponent.d.ts +8 -0
  33. package/lib/projects/add/v3AddComponent.js +85 -0
  34. package/lib/projects/components.d.ts +2 -0
  35. package/lib/projects/components.js +82 -0
  36. package/lib/projects/create/index.d.ts +23 -0
  37. package/lib/projects/create/index.js +33 -0
  38. package/lib/projects/create/legacy.d.ts +6 -0
  39. package/lib/projects/{create.js → create/legacy.js} +20 -11
  40. package/lib/projects/create/v3.d.ts +27 -0
  41. package/lib/projects/create/v3.js +158 -0
  42. package/lib/projects/localDev/AppDevModeInterface.d.ts +3 -2
  43. package/lib/projects/localDev/AppDevModeInterface.js +38 -2
  44. package/lib/projects/localDev/LocalDevProcess.d.ts +12 -5
  45. package/lib/projects/localDev/LocalDevProcess.js +47 -17
  46. package/lib/projects/localDev/LocalDevState.d.ts +16 -3
  47. package/lib/projects/localDev/LocalDevState.js +43 -2
  48. package/lib/projects/localDev/LocalDevWatcher.js +3 -6
  49. package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +3 -0
  50. package/lib/projects/localDev/LocalDevWebsocketServer.js +48 -9
  51. package/lib/prompts/createProjectPrompt.d.ts +14 -5
  52. package/lib/prompts/createProjectPrompt.js +36 -13
  53. package/lib/prompts/projectAddPrompt.d.ts +5 -1
  54. package/lib/prompts/projectAddPrompt.js +35 -7
  55. package/lib/prompts/setAsDefaultAccountPrompt.js +10 -0
  56. package/package.json +6 -5
  57. package/types/LocalDev.d.ts +11 -1
  58. package/types/Projects.d.ts +19 -2
  59. package/lib/projects/create.d.ts +0 -5
@@ -87,6 +87,7 @@ const accountsSubCommands = {
87
87
  list: { target: true },
88
88
  ls: { target: true },
89
89
  remove: { target: true },
90
+ use: { target: true },
90
91
  },
91
92
  };
92
93
  const sandboxesSubCommands = {
@@ -0,0 +1,5 @@
1
+ import { ProjectConfig } from '../../../types/Projects';
2
+ export declare function legacyAddComponent(args: {
3
+ name?: string;
4
+ type?: string;
5
+ }, projectDir: string, projectConfig: ProjectConfig): Promise<void>;
@@ -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,2 @@
1
+ import { Collision } from '@hubspot/local-dev-lib/types/Archive';
2
+ export declare function handleComponentCollision({ dest, src, collisions }: Collision): void;
@@ -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("../constants");
8
- const exitCodes_1 = require("../enums/exitCodes");
9
- const index_1 = require("../errorHandlers/index");
10
- const en_1 = require("../../lang/en");
11
- const logger_1 = require("../ui/logger");
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
- const PROJECT_TEMPLATE_PROPERTIES = ['name', 'label', 'path', 'insertPath'];
14
- async function getProjectComponentListFromRepo(githubRef) {
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
- const { data } = await (0, github_1.fetchRepoFile)(constants_1.HUBSPOT_PROJECT_COMPONENTS_GITHUB_PATH, 'config.json', githubRef);
18
- config = data;
27
+ config = await getConfigForPlatformVersion(platformVersion);
19
28
  }
20
29
  catch (err) {
21
- (0, index_1.debugError)(err);
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, index_1.debugError)(e);
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 = 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() {