@hubspot/cli 5.2.1-beta.1 → 5.2.1-beta.2
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/init.js +1 -1
- package/commands/project/dev.js +19 -2
- package/commands/theme/preview.js +48 -14
- package/lang/en.lyaml +7 -5
- package/lib/developerTestAccountCreate.js +1 -0
- package/lib/localDev.js +59 -16
- package/lib/projectStructure.js +5 -2
- package/lib/prompts/previewPrompt.js +18 -0
- package/lib/prompts/projectDevTargetAccountPrompt.js +47 -5
- package/package.json +4 -4
package/commands/init.js
CHANGED
|
@@ -62,7 +62,7 @@ const personalAccessKeyConfigCreationFlow = async (env, account) => {
|
|
|
62
62
|
|
|
63
63
|
try {
|
|
64
64
|
const token = await getAccessToken(personalAccessKey, env);
|
|
65
|
-
const defaultName = toKebabCase(token.hubName);
|
|
65
|
+
const defaultName = token.hubName ? toKebabCase(token.hubName) : null;
|
|
66
66
|
const { name } = await enterAccountNamePrompt(defaultName);
|
|
67
67
|
|
|
68
68
|
updatedConfig = updateConfigWithAccessToken(
|
package/commands/project/dev.js
CHANGED
|
@@ -42,10 +42,12 @@ const {
|
|
|
42
42
|
confirmDefaultAccountIsTarget,
|
|
43
43
|
suggestRecommendedNestedAccount,
|
|
44
44
|
checkIfAppDeveloperAccount,
|
|
45
|
+
checkIfDeveloperTestAccount,
|
|
45
46
|
createSandboxForLocalDev,
|
|
46
47
|
createDeveloperTestAccountForLocalDev,
|
|
47
48
|
createNewProjectForLocalDev,
|
|
48
49
|
createInitialBuildForNewProject,
|
|
50
|
+
useExistingDevTestAccount,
|
|
49
51
|
} = require('../../lib/localDev');
|
|
50
52
|
|
|
51
53
|
const i18nKey = 'cli.commands.project.subcommands.dev';
|
|
@@ -91,7 +93,13 @@ exports.handler = async options => {
|
|
|
91
93
|
// The account that the project must exist in
|
|
92
94
|
let targetProjectAccountId = options.account ? accountId : null;
|
|
93
95
|
// The account that we are locally testing against
|
|
94
|
-
let targetTestingAccountId =
|
|
96
|
+
let targetTestingAccountId = options.account ? accountId : null;
|
|
97
|
+
|
|
98
|
+
if (options.account && hasPublicApps) {
|
|
99
|
+
checkIfDeveloperTestAccount(accountConfig);
|
|
100
|
+
targetProjectAccountId = accountConfig.parentAccountId;
|
|
101
|
+
targetTestingAccountId = accountId;
|
|
102
|
+
}
|
|
95
103
|
|
|
96
104
|
let createNewSandbox = false;
|
|
97
105
|
let createNewDeveloperTestAccount = false;
|
|
@@ -101,6 +109,7 @@ exports.handler = async options => {
|
|
|
101
109
|
targetProjectAccountId = hasPublicApps
|
|
102
110
|
? accountConfig.parentAccountId
|
|
103
111
|
: accountId;
|
|
112
|
+
targetTestingAccountId = accountId;
|
|
104
113
|
} else if (!targetProjectAccountId && hasPublicApps) {
|
|
105
114
|
checkIfAppDeveloperAccount(accountConfig);
|
|
106
115
|
}
|
|
@@ -110,6 +119,7 @@ exports.handler = async options => {
|
|
|
110
119
|
targetAccountId,
|
|
111
120
|
parentAccountId,
|
|
112
121
|
createNestedAccount,
|
|
122
|
+
notInConfigAccount,
|
|
113
123
|
} = await suggestRecommendedNestedAccount(
|
|
114
124
|
accounts,
|
|
115
125
|
accountConfig,
|
|
@@ -119,6 +129,11 @@ exports.handler = async options => {
|
|
|
119
129
|
targetProjectAccountId = hasPublicApps ? parentAccountId : targetAccountId;
|
|
120
130
|
targetTestingAccountId = targetAccountId;
|
|
121
131
|
|
|
132
|
+
// Only used for developer test accounts that are not yet in the config
|
|
133
|
+
if (notInConfigAccount) {
|
|
134
|
+
await useExistingDevTestAccount(env, notInConfigAccount);
|
|
135
|
+
}
|
|
136
|
+
|
|
122
137
|
createNewSandbox = isStandardAccount(accountConfig) && createNestedAccount;
|
|
123
138
|
createNewDeveloperTestAccount =
|
|
124
139
|
isAppDeveloperAccount(accountConfig) && createNestedAccount;
|
|
@@ -139,6 +154,7 @@ exports.handler = async options => {
|
|
|
139
154
|
accountConfig,
|
|
140
155
|
env
|
|
141
156
|
);
|
|
157
|
+
targetProjectAccountId = accountId;
|
|
142
158
|
}
|
|
143
159
|
|
|
144
160
|
const projectExists = await ensureProjectExists(
|
|
@@ -171,7 +187,8 @@ exports.handler = async options => {
|
|
|
171
187
|
await createNewProjectForLocalDev(
|
|
172
188
|
projectConfig,
|
|
173
189
|
targetProjectAccountId,
|
|
174
|
-
createNewSandbox
|
|
190
|
+
createNewSandbox,
|
|
191
|
+
hasPublicApps
|
|
175
192
|
);
|
|
176
193
|
|
|
177
194
|
deployedBuild = await createInitialBuildForNewProject(
|
|
@@ -12,19 +12,28 @@ const { preview } = require('@hubspot/theme-preview-dev-server');
|
|
|
12
12
|
const { getUploadableFileList } = require('../../lib/upload');
|
|
13
13
|
const { trackCommandUsage } = require('../../lib/usageTracking');
|
|
14
14
|
const { loadAndValidateOptions } = require('../../lib/validation');
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
previewPrompt,
|
|
17
|
+
previewProjectPrompt,
|
|
18
|
+
} = require('../../lib/prompts/previewPrompt');
|
|
16
19
|
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
|
|
17
20
|
const {
|
|
18
21
|
FILE_UPLOAD_RESULT_TYPES,
|
|
19
22
|
} = require('@hubspot/local-dev-lib/constants/files');
|
|
20
|
-
const i18nKey = 'cli.commands.preview';
|
|
21
23
|
const cliProgress = require('cli-progress');
|
|
22
24
|
const {
|
|
23
25
|
ApiErrorContext,
|
|
24
26
|
logApiUploadErrorInstance,
|
|
25
27
|
} = require('../../lib/errorHandlers/apiErrors');
|
|
26
28
|
const { handleExit, handleKeypress } = require('../../lib/process');
|
|
29
|
+
const { getThemeJSONPath } = require('@hubspot/local-dev-lib/cms/themes');
|
|
30
|
+
const { getProjectConfig } = require('../../lib/projects');
|
|
31
|
+
const {
|
|
32
|
+
findProjectComponents,
|
|
33
|
+
COMPONENT_TYPES,
|
|
34
|
+
} = require('../../lib/projectStructure');
|
|
27
35
|
|
|
36
|
+
const i18nKey = 'cli.commands.preview';
|
|
28
37
|
exports.command = 'preview [--src] [--dest]';
|
|
29
38
|
exports.describe = false; // i18n(`${i18nKey}.describe`) - Hiding command
|
|
30
39
|
|
|
@@ -63,6 +72,42 @@ const handleUserInput = () => {
|
|
|
63
72
|
});
|
|
64
73
|
};
|
|
65
74
|
|
|
75
|
+
const determineSrcAndDest = async options => {
|
|
76
|
+
let absoluteSrc;
|
|
77
|
+
let dest;
|
|
78
|
+
const { projectDir, projectConfig } = await getProjectConfig();
|
|
79
|
+
if (!(projectDir && projectConfig)) {
|
|
80
|
+
// Not in a project, prompt for src and dest of traditional theme
|
|
81
|
+
const previewPromptAnswers = await previewPrompt(options);
|
|
82
|
+
const src = options.src || previewPromptAnswers.src;
|
|
83
|
+
dest = options.dest || previewPromptAnswers.dest;
|
|
84
|
+
absoluteSrc = path.resolve(getCwd(), src);
|
|
85
|
+
if (!dest || !validateSrcPath(absoluteSrc)) {
|
|
86
|
+
process.exit(EXIT_CODES.ERROR);
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
// In a project
|
|
90
|
+
let themeJsonPath = getThemeJSONPath();
|
|
91
|
+
if (!themeJsonPath) {
|
|
92
|
+
const projectComponents = await findProjectComponents(projectDir);
|
|
93
|
+
const themeComponents = projectComponents.filter(
|
|
94
|
+
c => c.type === COMPONENT_TYPES.hublTheme
|
|
95
|
+
);
|
|
96
|
+
if (themeComponents.length === 0) {
|
|
97
|
+
logger.error(i18n(`${i18nKey}.errors.noThemeComponents`));
|
|
98
|
+
process.exit(EXIT_CODES.ERROR);
|
|
99
|
+
}
|
|
100
|
+
const answer = await previewProjectPrompt(themeComponents);
|
|
101
|
+
themeJsonPath = `${answer.themeComponentPath}/theme.json`;
|
|
102
|
+
}
|
|
103
|
+
const { dir: themeDir } = path.parse(themeJsonPath);
|
|
104
|
+
absoluteSrc = themeDir;
|
|
105
|
+
const { base: themeName } = path.parse(themeDir);
|
|
106
|
+
dest = `@projects/${projectConfig.name}/${themeName}`;
|
|
107
|
+
}
|
|
108
|
+
return { absoluteSrc, dest };
|
|
109
|
+
};
|
|
110
|
+
|
|
66
111
|
exports.handler = async options => {
|
|
67
112
|
const { notify, skipUpload, noSsl, port, debug } = options;
|
|
68
113
|
|
|
@@ -70,18 +115,7 @@ exports.handler = async options => {
|
|
|
70
115
|
|
|
71
116
|
const accountId = getAccountId(options);
|
|
72
117
|
|
|
73
|
-
const
|
|
74
|
-
const src = options.src || previewPromptAnswers.src;
|
|
75
|
-
let dest = options.dest || previewPromptAnswers.dest;
|
|
76
|
-
if (!dest) {
|
|
77
|
-
logger.error(i18n(`${i18nKey}.errors.destinationRequired`));
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const absoluteSrc = path.resolve(getCwd(), src);
|
|
82
|
-
if (!validateSrcPath(absoluteSrc)) {
|
|
83
|
-
process.exit(EXIT_CODES.ERROR);
|
|
84
|
-
}
|
|
118
|
+
const { absoluteSrc, dest } = await determineSrcAndDest(options);
|
|
85
119
|
|
|
86
120
|
const filePaths = await getUploadableFileList(absoluteSrc, false);
|
|
87
121
|
|
package/lang/en.lyaml
CHANGED
|
@@ -882,6 +882,7 @@ en:
|
|
|
882
882
|
describe: "Upload and watch a theme directory on your computer for changes and start a local development server to preview theme changes on a site"
|
|
883
883
|
errors:
|
|
884
884
|
invalidPath: "The path \"{{ path }}\" is not a path to a directory"
|
|
885
|
+
noThemeComponents: "Your project has no theme components available to preview."
|
|
885
886
|
options:
|
|
886
887
|
src:
|
|
887
888
|
describe: "Path to the local directory your theme is in, relative to your current working directory"
|
|
@@ -944,14 +945,15 @@ en:
|
|
|
944
945
|
localDev:
|
|
945
946
|
confirmDefaultAccountIsTarget:
|
|
946
947
|
declineDefaultAccountExplanation: "To develop on a different account, run {{ useCommand }} to change your default account, then re-run {{ devCommand }}."
|
|
947
|
-
|
|
948
|
-
|
|
948
|
+
checkIfAppDevloperAccount: "This project contains a public app. Local development of public apps is only supported on developer accounts and developer test accounts. Change your default account using {{#bold}}`hs accounts use`{{/bold}}, or link a new account with {{#bold}}`hs auth`{{/bold}}."
|
|
949
|
+
checkIfDeveloperTestAccount: "This project contains a public app. The \"--account\" flag must point to a developer test account to develop this project locally. Alternatively, change your default account to an App Developer Account using {{#bold}}`hs accounts use`{{/bold}} and run {{#bold}}`hs project dev`{{/bold}} to set up a new Developer Test Account."
|
|
949
950
|
suggestRecommendedNestedAccount:
|
|
950
951
|
nonSandboxWarning: "Testing in a sandbox is strongly recommended. To switch the target account, select an option below or run {{#bold}}`hs accounts use`{{/bold}} before running the command again."
|
|
951
952
|
publicAppNonDeveloperTestAccountWarning: "Local development of public apps is only supported in {{#bold}}developer test accounts{{/bold}}."
|
|
952
953
|
privateAppNonDeveloperTestAccountWarning: "Local development of private apps is only supported in {{#bold}}developer test accounts{{/bold}}"
|
|
953
954
|
createNewProjectForLocalDev:
|
|
954
955
|
projectMustExistExplanation: "The project {{ projectName }} does not exist in the target account {{ accountIdentifier}}. This command requires the project to exist in the target account."
|
|
956
|
+
publicAppProjectMustExistExplanation: "The project {{ projectName }} does not exist in {{ accountIdentifier}}, the app developer account associated with your target account. This command requires the project to exist in this app developer account."
|
|
955
957
|
createProject: "Create new project {{ projectName}} in {{#bold}}[{{ accountIdentifier }}]{{/bold}}?"
|
|
956
958
|
choseNotToCreateProject: "Exiting because this command requires the project to exist in the target account."
|
|
957
959
|
creatingProject: "Creating project {{ projectName }} in {{ accountIdentifier }}"
|
|
@@ -1080,6 +1082,7 @@ en:
|
|
|
1080
1082
|
sandboxLimitWithSuggestion: "Your account reached the limit of {{ limit }} development sandboxes. Run {{ authCommand }} to add an existing one to the config."
|
|
1081
1083
|
developerTestAccountLimit: "Your account reached the limit of {{ limit }} developer test accounts."
|
|
1082
1084
|
confirmDefaultAccount: "Continue testing on {{#bold}}{{ accountName }} ({{ accountType }}){{/bold}}? (Y/n)"
|
|
1085
|
+
confirmUseExistingDeveloperTestAccount: "Continue with {{ accountName }}? This account isn't currently connected to the HubSpot CLI. By continuing, you'll be prompted to generate a personal access key and connect it."
|
|
1083
1086
|
projectLogsPrompt:
|
|
1084
1087
|
projectName:
|
|
1085
1088
|
message: "[--project] Enter the project name:"
|
|
@@ -1222,6 +1225,7 @@ en:
|
|
|
1222
1225
|
previewPrompt:
|
|
1223
1226
|
enterSrc: "[--src] Enter a local theme directory to preview."
|
|
1224
1227
|
enterDest: "[--dest] Enter the destination path for the src theme in HubSpot Design Tools."
|
|
1228
|
+
themeProjectSelect: "[--theme] Select which theme to preview."
|
|
1225
1229
|
errors:
|
|
1226
1230
|
srcRequired: "You must specify a source directory."
|
|
1227
1231
|
destRequired: "You must specify a destination directory."
|
|
@@ -1241,7 +1245,7 @@ en:
|
|
|
1241
1245
|
fail: "Failed to create a developer test account {{#bold}}{{ accountName }}{{/bold}}."
|
|
1242
1246
|
succeed: "Successfully created a developer test account {{#bold}}{{ name }}{{/bold}} with portalId {{#bold}}{{ accountId }}{{/bold}}."
|
|
1243
1247
|
success:
|
|
1244
|
-
configFileUpdated: "{{
|
|
1248
|
+
configFileUpdated: "Account \"{{ accountName }}\" updated using \"{{ authType }}\""
|
|
1245
1249
|
failure:
|
|
1246
1250
|
invalidUser: "Couldn't create {{#bold}}{{ accountName }}{{/bold}} because your account has been removed from {{#bold}}{{ parentAccountName }}{{/bold}} or your permission set doesn't allow you to create the sandbox. To update your permissions, contact a super admin in {{#bold}}{{ parentAccountName }}{{/bold}}."
|
|
1247
1251
|
limit: "{{#bold}}{{ accountName }}{{/bold}} reached the limit of {{ limit }} developer test accounts.
|
|
@@ -1264,8 +1268,6 @@ en:
|
|
|
1264
1268
|
add: "Creating standard sandbox {{#bold}}{{ sandboxName }}{{/bold}}"
|
|
1265
1269
|
fail: "Failed to create a standard sandbox {{#bold}}{{ sandboxName }}{{/bold}}."
|
|
1266
1270
|
succeed: "Successfully created a standard sandbox {{#bold}}{{ name }}{{/bold}} with portalId {{#bold}}{{ sandboxHubId }}{{/bold}}."
|
|
1267
|
-
success:
|
|
1268
|
-
configFileUpdated: "{{ configFilename }} updated with {{ authMethod }} for account {{ account }}."
|
|
1269
1271
|
failure:
|
|
1270
1272
|
invalidUser: "Couldn't create {{#bold}}{{ accountName }}{{/bold}} because your account has been removed from {{#bold}}{{ parentAccountName }}{{/bold}} or your permission set doesn't allow you to create the sandbox. To update your permissions, contact a super admin in {{#bold}}{{ parentAccountName }}{{/bold}}."
|
|
1271
1273
|
403Gating: "Couldn't create {{#bold}}{{ accountName }}{{/bold}} because {{#bold}}{{ parentAccountName }}{{/bold}} does not have access to development sandboxes. To opt in to the CRM Development Beta and use development sandboxes, visit https://app.hubspot.com/l/product-updates/in-beta?update=13899236."
|
package/lib/localDev.js
CHANGED
|
@@ -15,6 +15,7 @@ const {
|
|
|
15
15
|
confirmDefaultAccountPrompt,
|
|
16
16
|
selectSandboxTargetAccountPrompt,
|
|
17
17
|
selectDeveloperTestTargetAccountPrompt,
|
|
18
|
+
confirmUseExistingDeveloperTestAccountPrompt,
|
|
18
19
|
} = require('./prompts/projectDevTargetAccountPrompt');
|
|
19
20
|
const { sandboxNamePrompt } = require('./prompts/sandboxesPrompt');
|
|
20
21
|
const {
|
|
@@ -31,7 +32,10 @@ const { syncSandbox } = require('./sandboxSync');
|
|
|
31
32
|
const {
|
|
32
33
|
validateDevTestAccountUsageLimits,
|
|
33
34
|
} = require('./developerTestAccounts');
|
|
34
|
-
const {
|
|
35
|
+
const {
|
|
36
|
+
buildDeveloperTestAccount,
|
|
37
|
+
saveDevTestAccountToConfig,
|
|
38
|
+
} = require('./developerTestAccountCreate');
|
|
35
39
|
const { logErrorInstance } = require('./errorHandlers/standardErrors');
|
|
36
40
|
const { uiCommandReference, uiLine, uiAccountDescription } = require('./ui');
|
|
37
41
|
const SpinniesManager = require('./ui/SpinniesManager');
|
|
@@ -55,6 +59,9 @@ const {
|
|
|
55
59
|
logApiErrorInstance,
|
|
56
60
|
ApiErrorContext,
|
|
57
61
|
} = require('./errorHandlers/apiErrors');
|
|
62
|
+
const {
|
|
63
|
+
PERSONAL_ACCESS_KEY_AUTH_METHOD,
|
|
64
|
+
} = require('@hubspot/local-dev-lib/constants/auth');
|
|
58
65
|
|
|
59
66
|
const i18nKey = 'cli.lib.localDev';
|
|
60
67
|
|
|
@@ -86,11 +93,15 @@ const confirmDefaultAccountIsTarget = async accountConfig => {
|
|
|
86
93
|
// Confirm the default account is a developer account if developing public apps
|
|
87
94
|
const checkIfAppDeveloperAccount = accountConfig => {
|
|
88
95
|
if (!isAppDeveloperAccount(accountConfig)) {
|
|
89
|
-
logger.error(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
logger.error(i18n(`${i18nKey}.checkIfAppDevloperAccount`));
|
|
97
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Confirm the default account is a developer account if developing public apps
|
|
102
|
+
const checkIfDeveloperTestAccount = accountConfig => {
|
|
103
|
+
if (!isDeveloperTestAccount(accountConfig)) {
|
|
104
|
+
logger.error(i18n(`${i18nKey}.checkIfDeveloperTestAccount`));
|
|
94
105
|
process.exit(EXIT_CODES.SUCCESS);
|
|
95
106
|
}
|
|
96
107
|
};
|
|
@@ -262,27 +273,57 @@ const createDeveloperTestAccountForLocalDev = async (
|
|
|
262
273
|
}
|
|
263
274
|
};
|
|
264
275
|
|
|
276
|
+
// Prompt user to confirm usage of an existing developer test account that is not currently in the config
|
|
277
|
+
const useExistingDevTestAccount = async (env, account) => {
|
|
278
|
+
const useExistingDevTestAcct = await confirmUseExistingDeveloperTestAccountPrompt(
|
|
279
|
+
account
|
|
280
|
+
);
|
|
281
|
+
if (!useExistingDevTestAcct) {
|
|
282
|
+
logger.log('');
|
|
283
|
+
logger.log(
|
|
284
|
+
i18n(
|
|
285
|
+
`${i18nKey}.confirmDefaultAccountIsTarget.declineDefaultAccountExplanation`,
|
|
286
|
+
{
|
|
287
|
+
useCommand: uiCommandReference('hs accounts use'),
|
|
288
|
+
devCommand: uiCommandReference('hs project dev'),
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
);
|
|
292
|
+
logger.log('');
|
|
293
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
294
|
+
}
|
|
295
|
+
const devTestAcctConfigName = await saveDevTestAccountToConfig(env, account);
|
|
296
|
+
logger.success(
|
|
297
|
+
i18n(`cli.lib.developerTestAccount.create.success.configFileUpdated`, {
|
|
298
|
+
accountName: devTestAcctConfigName,
|
|
299
|
+
authType: PERSONAL_ACCESS_KEY_AUTH_METHOD.name,
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
};
|
|
303
|
+
|
|
265
304
|
// Prompt the user to create a new project if one doesn't exist on their target account
|
|
266
305
|
const createNewProjectForLocalDev = async (
|
|
267
306
|
projectConfig,
|
|
268
307
|
targetAccountId,
|
|
269
|
-
shouldCreateWithoutConfirmation
|
|
308
|
+
shouldCreateWithoutConfirmation,
|
|
309
|
+
hasPublicApps
|
|
270
310
|
) => {
|
|
271
311
|
// Create the project without prompting if this is a newly created sandbox
|
|
272
312
|
let shouldCreateProject = shouldCreateWithoutConfirmation;
|
|
273
313
|
|
|
274
314
|
if (!shouldCreateProject) {
|
|
315
|
+
const explanationString = i18n(
|
|
316
|
+
hasPublicApps
|
|
317
|
+
? `${i18nKey}.createNewProjectForLocalDev.publicAppProjectMustExistExplanation`
|
|
318
|
+
: `${i18nKey}.createNewProjectForLocalDev.projectMustExistExplanation`,
|
|
319
|
+
{
|
|
320
|
+
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
321
|
+
projectName: projectConfig.name,
|
|
322
|
+
}
|
|
323
|
+
);
|
|
275
324
|
logger.log();
|
|
276
325
|
uiLine();
|
|
277
|
-
logger.warn(
|
|
278
|
-
i18n(
|
|
279
|
-
`${i18nKey}.createNewProjectForLocalDev.projectMustExistExplanation`,
|
|
280
|
-
{
|
|
281
|
-
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
282
|
-
projectName: projectConfig.name,
|
|
283
|
-
}
|
|
284
|
-
)
|
|
285
|
-
);
|
|
326
|
+
logger.warn(explanationString);
|
|
286
327
|
uiLine();
|
|
287
328
|
|
|
288
329
|
shouldCreateProject = await confirmPrompt(
|
|
@@ -393,9 +434,11 @@ const createInitialBuildForNewProject = async (
|
|
|
393
434
|
module.exports = {
|
|
394
435
|
confirmDefaultAccountIsTarget,
|
|
395
436
|
checkIfAppDeveloperAccount,
|
|
437
|
+
checkIfDeveloperTestAccount,
|
|
396
438
|
suggestRecommendedNestedAccount,
|
|
397
439
|
createSandboxForLocalDev,
|
|
398
440
|
createDeveloperTestAccountForLocalDev,
|
|
441
|
+
useExistingDevTestAccount,
|
|
399
442
|
createNewProjectForLocalDev,
|
|
400
443
|
createInitialBuildForNewProject,
|
|
401
444
|
};
|
package/lib/projectStructure.js
CHANGED
|
@@ -7,11 +7,13 @@ const { logErrorInstance } = require('./errorHandlers/standardErrors');
|
|
|
7
7
|
const COMPONENT_TYPES = Object.freeze({
|
|
8
8
|
privateApp: 'private-app',
|
|
9
9
|
publicApp: 'public-app',
|
|
10
|
+
hublTheme: 'hubl-theme',
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
const CONFIG_FILES = {
|
|
13
14
|
[COMPONENT_TYPES.privateApp]: 'app.json',
|
|
14
15
|
[COMPONENT_TYPES.publicApp]: 'public-app.json',
|
|
16
|
+
[COMPONENT_TYPES.hublTheme]: 'theme.json',
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
function getTypeFromConfigFile(configFile) {
|
|
@@ -102,13 +104,14 @@ async function findProjectComponents(projectSourceDir) {
|
|
|
102
104
|
if (Object.values(CONFIG_FILES).includes(base)) {
|
|
103
105
|
const parsedAppConfig = loadConfigFile(projectFile);
|
|
104
106
|
|
|
105
|
-
if (parsedAppConfig
|
|
107
|
+
if (parsedAppConfig) {
|
|
106
108
|
const isLegacy = getIsLegacyApp(parsedAppConfig, dir);
|
|
109
|
+
const isHublTheme = base === CONFIG_FILES[COMPONENT_TYPES.hublTheme];
|
|
107
110
|
|
|
108
111
|
components.push({
|
|
109
112
|
type: getTypeFromConfigFile(base),
|
|
110
113
|
config: parsedAppConfig,
|
|
111
|
-
runnable: !isLegacy,
|
|
114
|
+
runnable: !isLegacy && !isHublTheme,
|
|
112
115
|
path: dir,
|
|
113
116
|
});
|
|
114
117
|
}
|
|
@@ -34,6 +34,24 @@ const previewPrompt = (promptOptions = {}) => {
|
|
|
34
34
|
]);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
const previewProjectPrompt = async themeComponents => {
|
|
38
|
+
return promptUser([
|
|
39
|
+
{
|
|
40
|
+
name: 'themeComponentPath',
|
|
41
|
+
message: i18n(`${i18nKey}.themeProjectSelect`),
|
|
42
|
+
type: 'list',
|
|
43
|
+
choices: themeComponents.map(t => {
|
|
44
|
+
const themeName = path.basename(t.path);
|
|
45
|
+
return {
|
|
46
|
+
name: themeName,
|
|
47
|
+
value: t.path,
|
|
48
|
+
};
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
};
|
|
53
|
+
|
|
37
54
|
module.exports = {
|
|
38
55
|
previewPrompt,
|
|
56
|
+
previewProjectPrompt,
|
|
39
57
|
};
|
|
@@ -24,6 +24,12 @@ const mapNestedAccount = accountConfig => ({
|
|
|
24
24
|
},
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
const getNonConfigDeveloperTestAccountName = account => {
|
|
28
|
+
return `${account.accountName} [${
|
|
29
|
+
HUBSPOT_ACCOUNT_TYPE_STRINGS[HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST]
|
|
30
|
+
}] (${account.id})`;
|
|
31
|
+
};
|
|
32
|
+
|
|
27
33
|
const selectSandboxTargetAccountPrompt = async (
|
|
28
34
|
accounts,
|
|
29
35
|
defaultAccountConfig
|
|
@@ -94,9 +100,11 @@ const selectDeveloperTestTargetAccountPrompt = async (
|
|
|
94
100
|
) => {
|
|
95
101
|
const defaultAccountId = getAccountId(defaultAccountConfig.name);
|
|
96
102
|
let choices = [];
|
|
97
|
-
let
|
|
103
|
+
let devTestAccountsResponse = undefined;
|
|
98
104
|
try {
|
|
99
|
-
|
|
105
|
+
devTestAccountsResponse = await fetchDeveloperTestAccounts(
|
|
106
|
+
defaultAccountId
|
|
107
|
+
);
|
|
100
108
|
} catch (err) {
|
|
101
109
|
logger.debug('Unable to fetch developer test account usage limits: ', err);
|
|
102
110
|
}
|
|
@@ -110,17 +118,37 @@ const selectDeveloperTestTargetAccountPrompt = async (
|
|
|
110
118
|
);
|
|
111
119
|
let disabledMessage = false;
|
|
112
120
|
if (
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
devTestAccountsResponse &&
|
|
122
|
+
devTestAccountsResponse.results.length >=
|
|
123
|
+
devTestAccountsResponse.maxTestPortals
|
|
115
124
|
) {
|
|
116
125
|
disabledMessage = i18n(`${i18nKey}.developerTestAccountLimit`, {
|
|
117
126
|
authCommand: uiCommandReference('hs auth'),
|
|
118
|
-
limit:
|
|
127
|
+
limit: devTestAccountsResponse.maxTestPortals,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let devTestAccountsNotInConfig = [];
|
|
132
|
+
if (devTestAccountsResponse && devTestAccountsResponse.results) {
|
|
133
|
+
const inConfigIds = devTestAccounts.map(d => d.portalId);
|
|
134
|
+
devTestAccountsResponse.results.forEach(acct => {
|
|
135
|
+
if (inConfigIds.indexOf(acct.id) < 0) {
|
|
136
|
+
devTestAccountsNotInConfig.push({
|
|
137
|
+
name: getNonConfigDeveloperTestAccountName(acct),
|
|
138
|
+
value: {
|
|
139
|
+
targetAccountId: acct.id,
|
|
140
|
+
createdNestedAccount: false,
|
|
141
|
+
parentAccountId: defaultAccountId,
|
|
142
|
+
notInConfigAccount: acct,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
119
146
|
});
|
|
120
147
|
}
|
|
121
148
|
|
|
122
149
|
choices = [
|
|
123
150
|
...devTestAccounts.map(mapNestedAccount),
|
|
151
|
+
...devTestAccountsNotInConfig,
|
|
124
152
|
{
|
|
125
153
|
name: i18n(`${i18nKey}.createNewDeveloperTestAccountOption`),
|
|
126
154
|
value: {
|
|
@@ -172,8 +200,22 @@ const confirmDefaultAccountPrompt = async (accountName, accountType) => {
|
|
|
172
200
|
return useDefaultAccount;
|
|
173
201
|
};
|
|
174
202
|
|
|
203
|
+
const confirmUseExistingDeveloperTestAccountPrompt = async account => {
|
|
204
|
+
const { confirmUseExistingDeveloperTestAccount } = await promptUser([
|
|
205
|
+
{
|
|
206
|
+
name: 'confirmUseExistingDeveloperTestAccount',
|
|
207
|
+
type: 'confirm',
|
|
208
|
+
message: i18n(`${i18nKey}.confirmUseExistingDeveloperTestAccount`, {
|
|
209
|
+
accountName: getNonConfigDeveloperTestAccountName(account),
|
|
210
|
+
}),
|
|
211
|
+
},
|
|
212
|
+
]);
|
|
213
|
+
return confirmUseExistingDeveloperTestAccount;
|
|
214
|
+
};
|
|
215
|
+
|
|
175
216
|
module.exports = {
|
|
176
217
|
selectSandboxTargetAccountPrompt,
|
|
177
218
|
selectDeveloperTestTargetAccountPrompt,
|
|
178
219
|
confirmDefaultAccountPrompt,
|
|
220
|
+
confirmUseExistingDeveloperTestAccountPrompt,
|
|
179
221
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "5.2.1-beta.
|
|
3
|
+
"version": "5.2.1-beta.2",
|
|
4
4
|
"description": "CLI for working with HubSpot",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"url": "https://github.com/HubSpot/hubspot-cms-tools"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@hubspot/local-dev-lib": "
|
|
12
|
-
"@hubspot/serverless-dev-runtime": "5.2.1-beta.
|
|
11
|
+
"@hubspot/local-dev-lib": "1.0.1",
|
|
12
|
+
"@hubspot/serverless-dev-runtime": "5.2.1-beta.2",
|
|
13
13
|
"@hubspot/theme-preview-dev-server": "0.0.4",
|
|
14
14
|
"@hubspot/ui-extensions-dev-server": "0.8.12",
|
|
15
15
|
"archiver": "^5.3.0",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "eeed6c79043020a0be2552fd0b5271866f8d73f9"
|
|
49
49
|
}
|