@hubspot/cli 5.2.1-beta.0 → 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/bin/cli.js +6 -1
- package/commands/accounts/clean.js +3 -3
- package/commands/accounts/list.js +17 -5
- package/commands/init.js +1 -1
- package/commands/project/dev.js +108 -259
- package/commands/project/upload.js +3 -0
- package/commands/sandbox/sync.js +5 -3
- package/commands/theme/preview.js +48 -14
- package/lang/en.lyaml +55 -17
- package/lib/LocalDevManager.js +31 -33
- package/lib/accountTypes.js +34 -0
- package/lib/developerTestAccountCreate.js +187 -0
- package/lib/developerTestAccounts.js +50 -4
- package/lib/localDev.js +444 -0
- package/lib/projectStructure.js +12 -2
- package/lib/projects.js +36 -0
- package/lib/prompts/developerTestAccountNamePrompt.js +29 -0
- package/lib/prompts/previewPrompt.js +18 -0
- package/lib/prompts/projectDevTargetAccountPrompt.js +126 -13
- package/lib/prompts/sandboxesPrompt.js +1 -1
- package/lib/sandboxSync.js +1 -1
- package/lib/sandboxes.js +1 -16
- package/lib/ui/index.js +10 -2
- package/package.json +4 -4
package/bin/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ const updateNotifier = require('update-notifier');
|
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
|
|
7
7
|
const { logger } = require('@hubspot/local-dev-lib/logger');
|
|
8
|
+
const { addUserAgentHeader } = require('@hubspot/local-dev-lib/http');
|
|
8
9
|
const { logErrorInstance } = require('../lib/errorHandlers/standardErrors');
|
|
9
10
|
const { setLogLevel, getCommandName } = require('../lib/commonOpts');
|
|
10
11
|
const {
|
|
@@ -110,9 +111,13 @@ const performChecks = argv => {
|
|
|
110
111
|
}
|
|
111
112
|
};
|
|
112
113
|
|
|
114
|
+
const setRequestHeaders = () => {
|
|
115
|
+
addUserAgentHeader('HubSpot CLI', pkg.version);
|
|
116
|
+
};
|
|
117
|
+
|
|
113
118
|
const argv = yargs
|
|
114
119
|
.usage('The command line interface to interact with HubSpot.')
|
|
115
|
-
.middleware([setLogLevel])
|
|
120
|
+
.middleware([setLogLevel, setRequestHeaders])
|
|
116
121
|
.exitProcess(false)
|
|
117
122
|
.fail(handleFailure)
|
|
118
123
|
.option('debug', {
|
|
@@ -13,7 +13,6 @@ const {
|
|
|
13
13
|
addUseEnvironmentOptions,
|
|
14
14
|
addTestingOptions,
|
|
15
15
|
} = require('../../lib/commonOpts');
|
|
16
|
-
const { getAccountName } = require('../../lib/sandboxes');
|
|
17
16
|
const { promptUser } = require('../../lib/prompts/promptUtils');
|
|
18
17
|
const { getTableContents } = require('../../lib/ui/table');
|
|
19
18
|
const SpinniesManager = require('../../lib/ui/SpinniesManager');
|
|
@@ -21,6 +20,7 @@ const { getConfig, deleteAccount } = require('@hubspot/local-dev-lib/config');
|
|
|
21
20
|
const {
|
|
22
21
|
isSpecifiedHubSpotAuthError,
|
|
23
22
|
} = require('@hubspot/local-dev-lib/errors/apiErrors');
|
|
23
|
+
const { uiAccountDescription } = require('../../lib/ui');
|
|
24
24
|
|
|
25
25
|
const i18nKey = 'cli.commands.accounts.subcommands.clean';
|
|
26
26
|
|
|
@@ -87,7 +87,7 @@ exports.handler = async options => {
|
|
|
87
87
|
});
|
|
88
88
|
logger.log(
|
|
89
89
|
getTableContents(
|
|
90
|
-
accountsToRemove.map(p => [
|
|
90
|
+
accountsToRemove.map(p => [uiAccountDescription(p)]),
|
|
91
91
|
{ border: { bodyLeft: ' ' } }
|
|
92
92
|
)
|
|
93
93
|
);
|
|
@@ -111,7 +111,7 @@ exports.handler = async options => {
|
|
|
111
111
|
await deleteAccount(accountToRemove.name);
|
|
112
112
|
logger.log(
|
|
113
113
|
i18n(`${i18nKey}.removeSuccess`, {
|
|
114
|
-
accountName:
|
|
114
|
+
accountName: uiAccountDescription(accountToRemove),
|
|
115
115
|
})
|
|
116
116
|
);
|
|
117
117
|
}
|
|
@@ -9,8 +9,13 @@ const {
|
|
|
9
9
|
} = require('../../lib/commonOpts');
|
|
10
10
|
const { trackCommandUsage } = require('../../lib/usageTracking');
|
|
11
11
|
const { loadAndValidateOptions } = require('../../lib/validation');
|
|
12
|
-
const {
|
|
13
|
-
const {
|
|
12
|
+
const { getSandboxName } = require('../../lib/sandboxes');
|
|
13
|
+
const {
|
|
14
|
+
isSandbox,
|
|
15
|
+
isDeveloperTestAccount,
|
|
16
|
+
isAppDeveloperAccount,
|
|
17
|
+
} = require('../../lib/accountTypes');
|
|
18
|
+
|
|
14
19
|
const { i18n } = require('../../lib/lang');
|
|
15
20
|
const {
|
|
16
21
|
HUBSPOT_ACCOUNT_TYPES,
|
|
@@ -53,21 +58,28 @@ const sortAndMapPortals = portals => {
|
|
|
53
58
|
|
|
54
59
|
const getPortalData = mappedPortalData => {
|
|
55
60
|
const portalData = [];
|
|
56
|
-
Object.
|
|
61
|
+
Object.entries(mappedPortalData).forEach(([key, set]) => {
|
|
62
|
+
const hasParentPortal = set.filter(
|
|
63
|
+
p => p.portalId === parseInt(key, 10)
|
|
64
|
+
)[0];
|
|
57
65
|
set.forEach(portal => {
|
|
58
66
|
let name = portal.name;
|
|
59
67
|
if (isSandbox(portal)) {
|
|
60
68
|
name = `${portal.name} ${getSandboxName(portal)}`;
|
|
61
|
-
if (set.length > 1) {
|
|
69
|
+
if (hasParentPortal && set.length > 1) {
|
|
62
70
|
name = `↳ ${name}`;
|
|
63
71
|
}
|
|
64
72
|
} else if (isDeveloperTestAccount(portal)) {
|
|
65
73
|
name = `${portal.name} [${
|
|
66
74
|
HUBSPOT_ACCOUNT_TYPE_STRINGS[HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST]
|
|
67
75
|
}]`;
|
|
68
|
-
if (set.length > 1) {
|
|
76
|
+
if (hasParentPortal && set.length > 1) {
|
|
69
77
|
name = `↳ ${name}`;
|
|
70
78
|
}
|
|
79
|
+
} else if (isAppDeveloperAccount(portal)) {
|
|
80
|
+
name = `${portal.name} [${
|
|
81
|
+
HUBSPOT_ACCOUNT_TYPE_STRINGS[HUBSPOT_ACCOUNT_TYPES.APP_DEVELOPER]
|
|
82
|
+
}]`;
|
|
71
83
|
}
|
|
72
84
|
portalData.push([name, portal.portalId, portal.authType]);
|
|
73
85
|
});
|
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
|
@@ -5,10 +5,7 @@ const {
|
|
|
5
5
|
addUseEnvironmentOptions,
|
|
6
6
|
addTestingOptions,
|
|
7
7
|
} = require('../../lib/commonOpts');
|
|
8
|
-
const {
|
|
9
|
-
trackCommandUsage,
|
|
10
|
-
trackCommandMetadataUsage,
|
|
11
|
-
} = require('../../lib/usageTracking');
|
|
8
|
+
const { trackCommandUsage } = require('../../lib/usageTracking');
|
|
12
9
|
const { loadAndValidateOptions } = require('../../lib/validation');
|
|
13
10
|
const { handleExit } = require('../../lib/process');
|
|
14
11
|
const { i18n } = require('../../lib/lang');
|
|
@@ -18,61 +15,40 @@ const {
|
|
|
18
15
|
getAccountConfig,
|
|
19
16
|
getEnv,
|
|
20
17
|
} = require('@hubspot/local-dev-lib/config');
|
|
21
|
-
const {
|
|
22
|
-
createProject,
|
|
23
|
-
fetchProject,
|
|
24
|
-
} = require('@hubspot/local-dev-lib/api/projects');
|
|
18
|
+
const { fetchProject } = require('@hubspot/local-dev-lib/api/projects');
|
|
25
19
|
const {
|
|
26
20
|
getProjectConfig,
|
|
27
21
|
ensureProjectExists,
|
|
28
|
-
handleProjectUpload,
|
|
29
|
-
pollProjectBuildAndDeploy,
|
|
30
22
|
validateProjectConfig,
|
|
31
23
|
} = require('../../lib/projects');
|
|
32
24
|
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
|
|
33
|
-
const {
|
|
34
|
-
uiAccountDescription,
|
|
35
|
-
uiBetaTag,
|
|
36
|
-
uiCommandReference,
|
|
37
|
-
uiLine,
|
|
38
|
-
} = require('../../lib/ui');
|
|
39
|
-
const { confirmPrompt } = require('../../lib/prompts/promptUtils');
|
|
40
|
-
const {
|
|
41
|
-
selectTargetAccountPrompt,
|
|
42
|
-
confirmDefaultAccountPrompt,
|
|
43
|
-
} = require('../../lib/prompts/projectDevTargetAccountPrompt');
|
|
25
|
+
const { uiBetaTag } = require('../../lib/ui');
|
|
44
26
|
const SpinniesManager = require('../../lib/ui/SpinniesManager');
|
|
45
27
|
const LocalDevManager = require('../../lib/LocalDevManager');
|
|
46
|
-
const { isSandbox, getSandboxTypeAsString } = require('../../lib/sandboxes');
|
|
47
|
-
const { sandboxNamePrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
48
28
|
const {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
29
|
+
isSandbox,
|
|
30
|
+
isDeveloperTestAccount,
|
|
31
|
+
isStandardAccount,
|
|
32
|
+
isAppDeveloperAccount,
|
|
33
|
+
} = require('../../lib/accountTypes');
|
|
52
34
|
const { getValidEnv } = require('@hubspot/local-dev-lib/environment');
|
|
35
|
+
|
|
53
36
|
const {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
} = require('../../lib/
|
|
58
|
-
|
|
59
|
-
const { buildSandbox } = require('../../lib/sandboxCreate');
|
|
60
|
-
const { syncSandbox } = require('../../lib/sandboxSync');
|
|
61
|
-
const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
|
|
62
|
-
const {
|
|
63
|
-
logApiErrorInstance,
|
|
64
|
-
ApiErrorContext,
|
|
65
|
-
} = require('../../lib/errorHandlers/apiErrors');
|
|
66
|
-
const {
|
|
67
|
-
isMissingScopeError,
|
|
68
|
-
isSpecifiedError,
|
|
69
|
-
} = require('@hubspot/local-dev-lib/errors/apiErrors');
|
|
70
|
-
const { logErrorInstance } = require('../../lib/errorHandlers/standardErrors');
|
|
71
|
-
const { isDeveloperTestAccount } = require('../../lib/developerTestAccounts');
|
|
37
|
+
findProjectComponents,
|
|
38
|
+
getProjectComponentTypes,
|
|
39
|
+
COMPONENT_TYPES,
|
|
40
|
+
} = require('../../lib/projectStructure');
|
|
72
41
|
const {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
42
|
+
confirmDefaultAccountIsTarget,
|
|
43
|
+
suggestRecommendedNestedAccount,
|
|
44
|
+
checkIfAppDeveloperAccount,
|
|
45
|
+
checkIfDeveloperTestAccount,
|
|
46
|
+
createSandboxForLocalDev,
|
|
47
|
+
createDeveloperTestAccountForLocalDev,
|
|
48
|
+
createNewProjectForLocalDev,
|
|
49
|
+
createInitialBuildForNewProject,
|
|
50
|
+
useExistingDevTestAccount,
|
|
51
|
+
} = require('../../lib/localDev');
|
|
76
52
|
|
|
77
53
|
const i18nKey = 'cli.commands.project.subcommands.dev';
|
|
78
54
|
|
|
@@ -98,126 +74,91 @@ exports.handler = async options => {
|
|
|
98
74
|
|
|
99
75
|
validateProjectConfig(projectConfig, projectDir);
|
|
100
76
|
|
|
77
|
+
const components = await findProjectComponents(projectDir);
|
|
78
|
+
const componentTypes = getProjectComponentTypes(components);
|
|
79
|
+
const hasPrivateApps = componentTypes[COMPONENT_TYPES.privateApp];
|
|
80
|
+
const hasPublicApps = componentTypes[COMPONENT_TYPES.publicApp];
|
|
81
|
+
|
|
82
|
+
if (hasPrivateApps && hasPublicApps) {
|
|
83
|
+
logger.error(i18n(`${i18nKey}.errors.invalidProjectComponents`));
|
|
84
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
85
|
+
}
|
|
86
|
+
|
|
101
87
|
const accounts = getConfigAccounts();
|
|
102
|
-
let targetAccountId = options.account ? accountId : null;
|
|
103
|
-
let createNewSandbox = false;
|
|
104
|
-
const defaultAccountIsSandbox = isSandbox(accountConfig);
|
|
105
|
-
const defaultAccountIsDeveloperTestAccount = isDeveloperTestAccount(
|
|
106
|
-
accountConfig
|
|
107
|
-
);
|
|
108
88
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(
|
|
112
|
-
) {
|
|
113
|
-
logger.log();
|
|
114
|
-
const useDefaultAccount = await confirmDefaultAccountPrompt(
|
|
115
|
-
accountConfig.name,
|
|
116
|
-
defaultAccountIsSandbox
|
|
117
|
-
? `${getSandboxTypeAsString(accountConfig.accountType)} sandbox`
|
|
118
|
-
: HUBSPOT_ACCOUNT_TYPE_STRINGS[HUBSPOT_ACCOUNT_TYPES.DEVELOPER_TEST]
|
|
119
|
-
);
|
|
89
|
+
const defaultAccountIsRecommendedType =
|
|
90
|
+
isDeveloperTestAccount(accountConfig) ||
|
|
91
|
+
(!hasPublicApps && isSandbox(accountConfig));
|
|
120
92
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
131
|
-
}
|
|
93
|
+
// The account that the project must exist in
|
|
94
|
+
let targetProjectAccountId = options.account ? accountId : null;
|
|
95
|
+
// The account that we are locally testing against
|
|
96
|
+
let targetTestingAccountId = options.account ? accountId : null;
|
|
97
|
+
|
|
98
|
+
if (options.account && hasPublicApps) {
|
|
99
|
+
checkIfDeveloperTestAccount(accountConfig);
|
|
100
|
+
targetProjectAccountId = accountConfig.parentAccountId;
|
|
101
|
+
targetTestingAccountId = accountId;
|
|
132
102
|
}
|
|
133
103
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
104
|
+
let createNewSandbox = false;
|
|
105
|
+
let createNewDeveloperTestAccount = false;
|
|
106
|
+
|
|
107
|
+
if (!targetProjectAccountId && defaultAccountIsRecommendedType) {
|
|
108
|
+
await confirmDefaultAccountIsTarget(accountConfig, hasPublicApps);
|
|
109
|
+
targetProjectAccountId = hasPublicApps
|
|
110
|
+
? accountConfig.parentAccountId
|
|
111
|
+
: accountId;
|
|
112
|
+
targetTestingAccountId = accountId;
|
|
113
|
+
} else if (!targetProjectAccountId && hasPublicApps) {
|
|
114
|
+
checkIfAppDeveloperAccount(accountConfig);
|
|
115
|
+
}
|
|
140
116
|
|
|
117
|
+
if (!targetProjectAccountId) {
|
|
141
118
|
const {
|
|
142
|
-
targetAccountId
|
|
143
|
-
|
|
144
|
-
|
|
119
|
+
targetAccountId,
|
|
120
|
+
parentAccountId,
|
|
121
|
+
createNestedAccount,
|
|
122
|
+
notInConfigAccount,
|
|
123
|
+
} = await suggestRecommendedNestedAccount(
|
|
124
|
+
accounts,
|
|
125
|
+
accountConfig,
|
|
126
|
+
hasPublicApps
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
targetProjectAccountId = hasPublicApps ? parentAccountId : targetAccountId;
|
|
130
|
+
targetTestingAccountId = targetAccountId;
|
|
145
131
|
|
|
146
|
-
|
|
147
|
-
|
|
132
|
+
// Only used for developer test accounts that are not yet in the config
|
|
133
|
+
if (notInConfigAccount) {
|
|
134
|
+
await useExistingDevTestAccount(env, notInConfigAccount);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
createNewSandbox = isStandardAccount(accountConfig) && createNestedAccount;
|
|
138
|
+
createNewDeveloperTestAccount =
|
|
139
|
+
isAppDeveloperAccount(accountConfig) && createNestedAccount;
|
|
148
140
|
}
|
|
149
141
|
|
|
150
142
|
if (createNewSandbox) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
logger.info(
|
|
167
|
-
i18n('cli.lib.sandbox.create.failure.scopes.instructions', {
|
|
168
|
-
accountName: accountConfig.name || accountId,
|
|
169
|
-
url,
|
|
170
|
-
})
|
|
171
|
-
);
|
|
172
|
-
} else {
|
|
173
|
-
logErrorInstance(err);
|
|
174
|
-
}
|
|
175
|
-
process.exit(EXIT_CODES.ERROR);
|
|
176
|
-
}
|
|
177
|
-
try {
|
|
178
|
-
const { name } = await sandboxNamePrompt(
|
|
179
|
-
HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
trackCommandMetadataUsage(
|
|
183
|
-
'sandbox-create',
|
|
184
|
-
{ step: 'project-dev' },
|
|
185
|
-
accountId
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
const { result } = await buildSandbox({
|
|
189
|
-
name,
|
|
190
|
-
type: HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX,
|
|
191
|
-
accountConfig,
|
|
192
|
-
env,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
targetAccountId = result.sandbox.sandboxHubId;
|
|
196
|
-
|
|
197
|
-
const sandboxAccountConfig = getAccountConfig(
|
|
198
|
-
result.sandbox.sandboxHubId
|
|
199
|
-
);
|
|
200
|
-
const syncTasks = await getAvailableSyncTypes(
|
|
201
|
-
accountConfig,
|
|
202
|
-
sandboxAccountConfig
|
|
203
|
-
);
|
|
204
|
-
await syncSandbox({
|
|
205
|
-
accountConfig: sandboxAccountConfig,
|
|
206
|
-
parentAccountConfig: accountConfig,
|
|
207
|
-
env,
|
|
208
|
-
syncTasks,
|
|
209
|
-
allowEarlyTermination: false, // Don't let user terminate early in this flow
|
|
210
|
-
skipPolling: true, // Skip polling, sync will run and complete in the background
|
|
211
|
-
});
|
|
212
|
-
} catch (err) {
|
|
213
|
-
logErrorInstance(err);
|
|
214
|
-
process.exit(EXIT_CODES.ERROR);
|
|
215
|
-
}
|
|
143
|
+
targetProjectAccountId = await createSandboxForLocalDev(
|
|
144
|
+
accountId,
|
|
145
|
+
accountConfig,
|
|
146
|
+
env
|
|
147
|
+
);
|
|
148
|
+
// We will be running our tests against this new sandbox account
|
|
149
|
+
targetTestingAccountId = targetProjectAccountId;
|
|
150
|
+
}
|
|
151
|
+
if (createNewDeveloperTestAccount) {
|
|
152
|
+
targetTestingAccountId = await createDeveloperTestAccountForLocalDev(
|
|
153
|
+
accountId,
|
|
154
|
+
accountConfig,
|
|
155
|
+
env
|
|
156
|
+
);
|
|
157
|
+
targetProjectAccountId = accountId;
|
|
216
158
|
}
|
|
217
159
|
|
|
218
|
-
logger.log();
|
|
219
160
|
const projectExists = await ensureProjectExists(
|
|
220
|
-
|
|
161
|
+
targetProjectAccountId,
|
|
221
162
|
projectConfig.name,
|
|
222
163
|
{
|
|
223
164
|
allowCreate: false,
|
|
@@ -230,7 +171,10 @@ exports.handler = async options => {
|
|
|
230
171
|
let isGithubLinked;
|
|
231
172
|
|
|
232
173
|
if (projectExists) {
|
|
233
|
-
const project = await fetchProject(
|
|
174
|
+
const project = await fetchProject(
|
|
175
|
+
targetProjectAccountId,
|
|
176
|
+
projectConfig.name
|
|
177
|
+
);
|
|
234
178
|
deployedBuild = project.deployedBuild;
|
|
235
179
|
isGithubLinked =
|
|
236
180
|
project.sourceIntegration &&
|
|
@@ -240,114 +184,18 @@ exports.handler = async options => {
|
|
|
240
184
|
SpinniesManager.init();
|
|
241
185
|
|
|
242
186
|
if (!projectExists) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
logger.warn(
|
|
250
|
-
i18n(`${i18nKey}.logs.projectMustExistExplanation`, {
|
|
251
|
-
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
252
|
-
projectName: projectConfig.name,
|
|
253
|
-
})
|
|
254
|
-
);
|
|
255
|
-
uiLine();
|
|
256
|
-
|
|
257
|
-
shouldCreateProject = await confirmPrompt(
|
|
258
|
-
i18n(`${i18nKey}.prompt.createProject`, {
|
|
259
|
-
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
260
|
-
projectName: projectConfig.name,
|
|
261
|
-
})
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (shouldCreateProject) {
|
|
266
|
-
SpinniesManager.add('createProject', {
|
|
267
|
-
text: i18n(`${i18nKey}.status.creatingProject`, {
|
|
268
|
-
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
269
|
-
projectName: projectConfig.name,
|
|
270
|
-
}),
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
try {
|
|
274
|
-
await createProject(targetAccountId, projectConfig.name);
|
|
275
|
-
SpinniesManager.succeed('createProject', {
|
|
276
|
-
text: i18n(`${i18nKey}.status.createdProject`, {
|
|
277
|
-
accountIdentifier: uiAccountDescription(targetAccountId),
|
|
278
|
-
projectName: projectConfig.name,
|
|
279
|
-
}),
|
|
280
|
-
succeedColor: 'white',
|
|
281
|
-
});
|
|
282
|
-
} catch (err) {
|
|
283
|
-
SpinniesManager.fail('createProject');
|
|
284
|
-
logger.log(i18n(`${i18nKey}.status.failedToCreateProject`));
|
|
285
|
-
process.exit(EXIT_CODES.ERROR);
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
// We cannot continue if the project does not exist in the target account
|
|
289
|
-
logger.log();
|
|
290
|
-
logger.log(i18n(`${i18nKey}.logs.choseNotToCreateProject`));
|
|
291
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
let initialUploadResult;
|
|
187
|
+
await createNewProjectForLocalDev(
|
|
188
|
+
projectConfig,
|
|
189
|
+
targetProjectAccountId,
|
|
190
|
+
createNewSandbox,
|
|
191
|
+
hasPublicApps
|
|
192
|
+
);
|
|
296
193
|
|
|
297
|
-
|
|
298
|
-
if (!projectExists) {
|
|
299
|
-
initialUploadResult = await handleProjectUpload(
|
|
300
|
-
targetAccountId,
|
|
194
|
+
deployedBuild = await createInitialBuildForNewProject(
|
|
301
195
|
projectConfig,
|
|
302
196
|
projectDir,
|
|
303
|
-
|
|
304
|
-
i18n(`${i18nKey}.logs.initialUploadMessage`)
|
|
197
|
+
targetProjectAccountId
|
|
305
198
|
);
|
|
306
|
-
|
|
307
|
-
if (initialUploadResult.uploadError) {
|
|
308
|
-
if (
|
|
309
|
-
isSpecifiedError(initialUploadResult.uploadError, {
|
|
310
|
-
subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
311
|
-
})
|
|
312
|
-
) {
|
|
313
|
-
logger.log();
|
|
314
|
-
logger.error(i18n(`${i18nKey}.errors.projectLockedError`));
|
|
315
|
-
logger.log();
|
|
316
|
-
} else {
|
|
317
|
-
logApiErrorInstance(
|
|
318
|
-
initialUploadResult.uploadError,
|
|
319
|
-
new ApiErrorContext({
|
|
320
|
-
accountId,
|
|
321
|
-
projectName: projectConfig.name,
|
|
322
|
-
})
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
process.exit(EXIT_CODES.ERROR);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (!initialUploadResult.succeeded) {
|
|
329
|
-
let subTasks = [];
|
|
330
|
-
|
|
331
|
-
if (initialUploadResult.buildResult.status === 'FAILURE') {
|
|
332
|
-
subTasks =
|
|
333
|
-
initialUploadResult.buildResult[PROJECT_BUILD_TEXT.SUBTASK_KEY];
|
|
334
|
-
} else if (initialUploadResult.deployResult.status === 'FAILURE') {
|
|
335
|
-
subTasks =
|
|
336
|
-
initialUploadResult.deployResult[PROJECT_DEPLOY_TEXT.SUBTASK_KEY];
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const failedSubTasks = subTasks.filter(task => task.status === 'FAILURE');
|
|
340
|
-
|
|
341
|
-
logger.log();
|
|
342
|
-
failedSubTasks.forEach(failedSubTask => {
|
|
343
|
-
console.error(failedSubTask.errorMessage);
|
|
344
|
-
});
|
|
345
|
-
logger.log();
|
|
346
|
-
|
|
347
|
-
process.exit(EXIT_CODES.ERROR);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
deployedBuild = initialUploadResult.buildResult;
|
|
351
199
|
}
|
|
352
200
|
|
|
353
201
|
const LocalDev = new LocalDevManager({
|
|
@@ -355,8 +203,9 @@ exports.handler = async options => {
|
|
|
355
203
|
deployedBuild,
|
|
356
204
|
projectConfig,
|
|
357
205
|
projectDir,
|
|
358
|
-
targetAccountId,
|
|
206
|
+
targetAccountId: targetTestingAccountId,
|
|
359
207
|
isGithubLinked,
|
|
208
|
+
components,
|
|
360
209
|
});
|
|
361
210
|
|
|
362
211
|
await LocalDev.start();
|
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
logFeedbackMessage,
|
|
17
17
|
validateProjectConfig,
|
|
18
18
|
pollProjectBuildAndDeploy,
|
|
19
|
+
displayWarnLogs,
|
|
19
20
|
} = require('../../lib/projects');
|
|
20
21
|
const { i18n } = require('../../lib/lang');
|
|
21
22
|
const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
|
|
@@ -91,6 +92,8 @@ exports.handler = async options => {
|
|
|
91
92
|
);
|
|
92
93
|
uiLine();
|
|
93
94
|
logFeedbackMessage(result.buildId);
|
|
95
|
+
|
|
96
|
+
displayWarnLogs(accountId, projectConfig.name, result.buildId);
|
|
94
97
|
process.exit(EXIT_CODES.SUCCESS);
|
|
95
98
|
}
|
|
96
99
|
} catch (e) {
|
package/commands/sandbox/sync.js
CHANGED
|
@@ -14,12 +14,14 @@ const { getAccountConfig, getEnv } = require('@hubspot/local-dev-lib/config');
|
|
|
14
14
|
const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
|
|
15
15
|
const { promptUser } = require('../../lib/prompts/promptUtils');
|
|
16
16
|
const { uiLine, uiAccountDescription } = require('../../lib/ui');
|
|
17
|
+
const {
|
|
18
|
+
isSandbox,
|
|
19
|
+
isStandardSandbox,
|
|
20
|
+
isDevelopmentSandbox,
|
|
21
|
+
} = require('../../lib/accountTypes');
|
|
17
22
|
const {
|
|
18
23
|
getAvailableSyncTypes,
|
|
19
24
|
getSyncTypesWithContactRecordsPrompt,
|
|
20
|
-
isDevelopmentSandbox,
|
|
21
|
-
isStandardSandbox,
|
|
22
|
-
isSandbox,
|
|
23
25
|
} = require('../../lib/sandboxes');
|
|
24
26
|
const { syncSandbox } = require('../../lib/sandboxSync');
|
|
25
27
|
const { getValidEnv } = require('@hubspot/local-dev-lib/environment');
|
|
@@ -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
|
|