@hubspot/cli 4.2.0 → 4.2.1-beta.1
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/cms/lighthouseScore.js +4 -5
- package/commands/module/marketplace-validate.js +5 -5
- package/commands/project/dev.js +101 -42
- package/commands/project/logs.js +132 -129
- package/commands/project/upload.js +4 -4
- package/commands/sandbox/create.js +0 -5
- package/commands/sandbox/delete.js +2 -8
- package/commands/sandbox/sync.js +5 -8
- package/commands/theme/marketplace-validate.js +5 -5
- package/lang/en.lyaml +25 -7
- package/lib/DevServerManager.js +53 -28
- package/lib/LocalDevManager.js +256 -168
- package/lib/LocalDevManagerV2.js +129 -0
- package/lib/SpinniesManager.js +318 -59
- package/lib/projects.js +36 -33
- package/lib/sandbox-create.js +5 -5
- package/lib/sandbox-sync.js +9 -9
- package/lib/serverlessLogs.js +8 -8
- package/lib/spinniesUtils.js +174 -0
- package/lib/ui.js +7 -0
- package/package.json +6 -4
|
@@ -55,7 +55,6 @@ exports.handler = async options => {
|
|
|
55
55
|
accountConfig.sandboxAccountType &&
|
|
56
56
|
accountConfig.sandboxAccountType !== null
|
|
57
57
|
) {
|
|
58
|
-
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
59
58
|
logger.error(
|
|
60
59
|
i18n(`${i18nKey}.failure.creatingWithinSandbox`, {
|
|
61
60
|
sandboxType: getSandboxTypeAsString(accountConfig.sandboxAccountType),
|
|
@@ -73,7 +72,6 @@ exports.handler = async options => {
|
|
|
73
72
|
typePrompt = await sandboxTypePrompt();
|
|
74
73
|
} else {
|
|
75
74
|
logger.error(i18n(`${i18nKey}.failure.optionMissing.type`));
|
|
76
|
-
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
77
75
|
process.exit(EXIT_CODES.ERROR);
|
|
78
76
|
}
|
|
79
77
|
}
|
|
@@ -100,7 +98,6 @@ exports.handler = async options => {
|
|
|
100
98
|
} else {
|
|
101
99
|
logErrorInstance(err);
|
|
102
100
|
}
|
|
103
|
-
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
104
101
|
process.exit(EXIT_CODES.ERROR);
|
|
105
102
|
}
|
|
106
103
|
|
|
@@ -109,7 +106,6 @@ exports.handler = async options => {
|
|
|
109
106
|
namePrompt = await sandboxNamePrompt(sandboxType);
|
|
110
107
|
} else {
|
|
111
108
|
logger.error(i18n(`${i18nKey}.failure.optionMissing.name`));
|
|
112
|
-
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
113
109
|
process.exit(EXIT_CODES.ERROR);
|
|
114
110
|
}
|
|
115
111
|
}
|
|
@@ -196,7 +192,6 @@ exports.handler = async options => {
|
|
|
196
192
|
uiFeatureHighlight(highlightItems);
|
|
197
193
|
process.exit(EXIT_CODES.SUCCESS);
|
|
198
194
|
} catch (error) {
|
|
199
|
-
trackCommandUsage('sandbox-create', { successful: false }, accountId);
|
|
200
195
|
// Errors are logged in util functions
|
|
201
196
|
process.exit(EXIT_CODES.ERROR);
|
|
202
197
|
}
|
|
@@ -44,6 +44,8 @@ exports.handler = async options => {
|
|
|
44
44
|
const { account, force } = options;
|
|
45
45
|
const config = getConfig();
|
|
46
46
|
|
|
47
|
+
trackCommandUsage('sandbox-delete', null);
|
|
48
|
+
|
|
47
49
|
let accountPrompt;
|
|
48
50
|
if (!account) {
|
|
49
51
|
if (!force) {
|
|
@@ -68,8 +70,6 @@ exports.handler = async options => {
|
|
|
68
70
|
const isDefaultAccount =
|
|
69
71
|
sandboxAccountId === getAccountId(config.defaultPortal);
|
|
70
72
|
|
|
71
|
-
trackCommandUsage('sandbox-delete', null, sandboxAccountId);
|
|
72
|
-
|
|
73
73
|
const baseUrl = getHubSpotWebsiteOrigin(
|
|
74
74
|
getValidEnv(getEnv(sandboxAccountId))
|
|
75
75
|
);
|
|
@@ -168,12 +168,6 @@ exports.handler = async options => {
|
|
|
168
168
|
} catch (err) {
|
|
169
169
|
debugErrorAndContext(err);
|
|
170
170
|
|
|
171
|
-
trackCommandUsage(
|
|
172
|
-
'sandbox-delete',
|
|
173
|
-
{ successful: false },
|
|
174
|
-
sandboxAccountId
|
|
175
|
-
);
|
|
176
|
-
|
|
177
171
|
if (err instanceof HubSpotAuthError) {
|
|
178
172
|
// Intercept invalid key error
|
|
179
173
|
// This command uses the parent portal PAK to delete a sandbox, so we must specify which account needs a new key
|
package/commands/sandbox/sync.js
CHANGED
|
@@ -44,7 +44,11 @@ exports.handler = async options => {
|
|
|
44
44
|
const accountConfig = getAccountConfig(accountId);
|
|
45
45
|
const env = getValidEnv(getEnv(accountId));
|
|
46
46
|
|
|
47
|
-
trackCommandUsage(
|
|
47
|
+
trackCommandUsage(
|
|
48
|
+
'sandbox-sync',
|
|
49
|
+
{ type: accountConfig.sandboxAccountType },
|
|
50
|
+
accountId
|
|
51
|
+
);
|
|
48
52
|
|
|
49
53
|
if (
|
|
50
54
|
// Check if default account is a sandbox, otherwise exit
|
|
@@ -53,7 +57,6 @@ exports.handler = async options => {
|
|
|
53
57
|
accountConfig.sandboxAccountType === null
|
|
54
58
|
) {
|
|
55
59
|
logger.error(i18n(`${i18nKey}.failure.notSandbox`));
|
|
56
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
57
60
|
process.exit(EXIT_CODES.ERROR);
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -66,7 +69,6 @@ exports.handler = async options => {
|
|
|
66
69
|
sandboxName: getAccountName(accountConfig),
|
|
67
70
|
})
|
|
68
71
|
);
|
|
69
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
70
72
|
process.exit(EXIT_CODES.ERROR);
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -98,7 +100,6 @@ exports.handler = async options => {
|
|
|
98
100
|
} else {
|
|
99
101
|
logErrorInstance(error);
|
|
100
102
|
}
|
|
101
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
102
103
|
process.exit(EXIT_CODES.ERROR);
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -128,7 +129,6 @@ exports.handler = async options => {
|
|
|
128
129
|
},
|
|
129
130
|
]);
|
|
130
131
|
if (!confirmed) {
|
|
131
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
132
132
|
process.exit(EXIT_CODES.SUCCESS);
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -166,13 +166,11 @@ exports.handler = async options => {
|
|
|
166
166
|
},
|
|
167
167
|
]);
|
|
168
168
|
if (!confirmed) {
|
|
169
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
170
169
|
process.exit(EXIT_CODES.SUCCESS);
|
|
171
170
|
}
|
|
172
171
|
}
|
|
173
172
|
} else {
|
|
174
173
|
logger.error('Sync must be run in a sandbox account.');
|
|
175
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
176
174
|
process.exit(EXIT_CODES.ERROR);
|
|
177
175
|
}
|
|
178
176
|
|
|
@@ -193,7 +191,6 @@ exports.handler = async options => {
|
|
|
193
191
|
|
|
194
192
|
process.exit(EXIT_CODES.SUCCESS);
|
|
195
193
|
} catch (error) {
|
|
196
|
-
trackCommandUsage('sandbox-sync', { successful: false }, accountId);
|
|
197
194
|
process.exit(EXIT_CODES.ERROR);
|
|
198
195
|
}
|
|
199
196
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const SpinniesManager = require('../../lib/SpinniesManager');
|
|
3
2
|
const {
|
|
4
3
|
addConfigOptions,
|
|
5
4
|
addAccountOptions,
|
|
@@ -31,8 +30,9 @@ exports.handler = async options => {
|
|
|
31
30
|
|
|
32
31
|
trackCommandUsage('validate', null, accountId);
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
SpinniesManager.init();
|
|
34
|
+
|
|
35
|
+
SpinniesManager.add('marketplaceValidation', {
|
|
36
36
|
text: i18n(`${i18nKey}.logs.validatingTheme`, {
|
|
37
37
|
path: src,
|
|
38
38
|
}),
|
|
@@ -42,7 +42,7 @@ exports.handler = async options => {
|
|
|
42
42
|
const validationId = await kickOffValidation(accountId, assetType, src);
|
|
43
43
|
await pollForValidationFinish(accountId, validationId);
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
SpinniesManager.remove('marketplaceValidation');
|
|
46
46
|
|
|
47
47
|
const validationResults = await fetchValidationResults(
|
|
48
48
|
accountId,
|
package/lang/en.lyaml
CHANGED
|
@@ -448,8 +448,7 @@ en:
|
|
|
448
448
|
dev:
|
|
449
449
|
describe: "Start local dev for the current project"
|
|
450
450
|
logs:
|
|
451
|
-
betaMessage: "
|
|
452
|
-
learnMoreLink: "Learn more about the projects local dev server"
|
|
451
|
+
betaMessage: "HubSpot projects local development"
|
|
453
452
|
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."
|
|
454
453
|
placeholderAccountSelection: "Using default account as target account (for now)"
|
|
455
454
|
projectMustExistExplanation: "The project {{ projectName }} does not exist in the target account {{ accountIdentifier}}. This command requires the project to exist in the target account."
|
|
@@ -464,8 +463,8 @@ en:
|
|
|
464
463
|
createProject: "Create new project {{ projectName}} in {{#bold}}[{{ accountIdentifier }}]{{/bold}}?"
|
|
465
464
|
targetNonSandbox: "Continue testing in a non-sandbox account?"
|
|
466
465
|
options:
|
|
467
|
-
|
|
468
|
-
describe: "The
|
|
466
|
+
extension:
|
|
467
|
+
describe: "The extension that you would like to run locally"
|
|
469
468
|
errors:
|
|
470
469
|
noProjectConfig: "No project detected. Please run this command again from a project directory."
|
|
471
470
|
projectLockedError: "Your project is locked. This may mean that another user is running the {{#bold}}`hs project dev`{{/bold}} command for this project. If this is you, unlock the project in Projects UI."
|
|
@@ -849,7 +848,20 @@ en:
|
|
|
849
848
|
lib:
|
|
850
849
|
DevServerManager:
|
|
851
850
|
portConflict: "The port {{ port }} is already in use."
|
|
851
|
+
LocalDevManagerV2:
|
|
852
|
+
failedToInitialize: "Missing required arguments to initialize Local Dev"
|
|
853
|
+
betaMessage: "HubSpot projects local development"
|
|
854
|
+
running: "Running {{#bold}}{{ projectName }}{{/bold}} locally on {{ accountIdentifier }}, waiting for changes ..."
|
|
855
|
+
quitHelper: "Press {{#bold}}'q'{{/bold}} to stop the local dev server"
|
|
856
|
+
viewInHubSpotLink: "View in HubSpot"
|
|
857
|
+
exitingStart: "Stopping local dev server ..."
|
|
858
|
+
exitingSucceed: "Successfully exited"
|
|
859
|
+
exitingFail: "Failed to cleanup before exiting"
|
|
860
|
+
devServer:
|
|
861
|
+
cleanupError: "Failed to cleanup local dev server: {{ message }}"
|
|
862
|
+
startError: "Failed to start local dev server: {{ message }}"
|
|
852
863
|
LocalDevManager:
|
|
864
|
+
failedToInitialize: "Missing required arguments to initialize Local Dev Manager"
|
|
853
865
|
exitingStart: "Stopping local dev server ..."
|
|
854
866
|
exitingSucceed: "Successfully exited"
|
|
855
867
|
exitingFail: "Failed to clean up before exiting"
|
|
@@ -857,16 +869,16 @@ en:
|
|
|
857
869
|
cancelledFromUI: "The dev process has been cancelled from the UI. Any changes made since cancelling have not been uploaded. To resume dev mode, rerun {{#yellow}}`hs project dev`{{/yellow}}."
|
|
858
870
|
header:
|
|
859
871
|
betaMessage: "{{#yellow}}{{#bold}}[beta]{{/bold}}{{/yellow}} HubSpot projects local development"
|
|
860
|
-
|
|
861
|
-
running: "Running {{ projectName}} locally on {{ accountIdentifier }}, waiting for changes ..."
|
|
872
|
+
running: "Running {{#bold}}{{ projectName }}{{/bold}} locally on {{ accountIdentifier }}, waiting for changes ..."
|
|
862
873
|
quitHelper: "Press {{#bold}}'q'{{/bold}} to stop the local dev server"
|
|
863
874
|
viewInHubSpotLink: "View in HubSpot"
|
|
864
875
|
status:
|
|
865
876
|
clean: "{{#bold}}Status:{{/bold}} {{#green}}Everything up to date{{/green}}"
|
|
877
|
+
buildError: "{{#bold}}Status:{{/bold}} {{#red}}Latest build failed{{/red}}"
|
|
878
|
+
deployError: "{{#bold}}Status:{{/bold}} {{#red}}Latest deploy failed{{/red}}"
|
|
866
879
|
uploadPending: "{{#bold}}Status:{{/bold}} {{#yellow}}Upload is pending{{/yellow}}"
|
|
867
880
|
noUploadsAllowed: "{{#bold}}Status:{{/bold}} {{#red}}Change requires upload, but uploads are not allowed{{/red}}"
|
|
868
881
|
manualUploadRequired: "{{#bold}}Status:{{/bold}} {{#yellow}}Change requires manual upload{{/yellow}}"
|
|
869
|
-
supportedChange: "{{#bold}}Status:{{/bold}} {{#green}}Change handled by local dev server{{/green}}"
|
|
870
882
|
manualUpload: "{{#bold}}Status:{{/bold}} {{#green}}Manually uploading pending changes{{/green}}"
|
|
871
883
|
upload:
|
|
872
884
|
noUploadsAllowed: "The change to {{ filePath }} requires an upload, but the CLI cannot upload to a project that is using a github integration."
|
|
@@ -876,6 +888,8 @@ en:
|
|
|
876
888
|
manualUploadExplanation1: "{{#yellow}}> Dev server is running on a {{#bold}}non-sandbox account{{/bold}}.{{/yellow}}"
|
|
877
889
|
manualUploadExplanation2: "{{#yellow}}> Uploading changes may overwrite production data.{{/yellow}}"
|
|
878
890
|
manualUploadPrompt: "? Manually upload and deploy project? {{#green}}Y/n{{/green}}"
|
|
891
|
+
extensionNotAllowed: "Extension not allowed for {{ filePath }}"
|
|
892
|
+
fileIgnored: "File ignored: {{ filePath }}"
|
|
879
893
|
uploadingAddChange: "[INFO] Uploading {{ filePath }}"
|
|
880
894
|
uploadedAddChange: "[INFO] Uploaded {{ filePath }}"
|
|
881
895
|
uploadingRemoveChange: "[INFO] Removing {{ filePath }}"
|
|
@@ -883,6 +897,9 @@ en:
|
|
|
883
897
|
uploadingChanges: "{{#bold}}Building #{{ buildId }} and deploying recent changes on {{ accountIdentifier }}{{/bold}}"
|
|
884
898
|
uploadedChangesSucceeded: "{{#bold}}Built #{{ buildId }} and deployed recent changes on {{ accountIdentifier }}{{/bold}}"
|
|
885
899
|
uploadedChangesFailed: "{{#bold}}Failed to build #{{ buildId }} and deploy recent changes on {{ accountIdentifier }}{{/bold}}"
|
|
900
|
+
devServer:
|
|
901
|
+
startError: "{{#red}}[ERROR]{{/red}} Failed to start local dev server"
|
|
902
|
+
cleanupError: "{{#red}}[ERROR]{{/red}} Failed to cleanup local dev server"
|
|
886
903
|
projects:
|
|
887
904
|
uploadProjectFiles:
|
|
888
905
|
add: "Uploading {{#bold}}{{ projectName }}{{/bold}} project files to {{ accountIdentifier }}"
|
|
@@ -909,6 +926,7 @@ en:
|
|
|
909
926
|
feedbackHeader: "We'd love to hear your feedback!"
|
|
910
927
|
feedbackMessage: "How are you liking the new projects and developer tools? \n > Run `{{#yellow}}hs feedback{{/yellow}}` to let us know what you think!\n"
|
|
911
928
|
ui:
|
|
929
|
+
betaTag: "{{#bold}}[beta]{{/bold}}"
|
|
912
930
|
betaWarning:
|
|
913
931
|
header: "{{#yellow}}***************************** WARNING ****************************{{/yellow}}"
|
|
914
932
|
footer: "{{#yellow}}******************************************************************{{/yellow}}"
|
package/lib/DevServerManager.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const bodyParser = require('body-parser');
|
|
3
3
|
const cors = require('cors');
|
|
4
|
-
const {
|
|
4
|
+
const { walk } = require('@hubspot/cli-lib/lib/walk');
|
|
5
5
|
const { getProjectDetailUrl } = require('./projects');
|
|
6
|
+
const { i18n } = require('./lang');
|
|
6
7
|
const { EXIT_CODES } = require('./enums/exitCodes');
|
|
7
8
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
8
9
|
|
|
@@ -12,10 +13,21 @@ const DEFAULT_PORT = 8080;
|
|
|
12
13
|
|
|
13
14
|
class DevServerManager {
|
|
14
15
|
constructor() {
|
|
16
|
+
this.initialized = false;
|
|
15
17
|
this.server = null;
|
|
18
|
+
this.path = null;
|
|
16
19
|
this.devServers = {};
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
safeLoadServer() {
|
|
23
|
+
try {
|
|
24
|
+
const { DevModeInterface } = require('@hubspot/ui-extensions-dev-server');
|
|
25
|
+
this.devServers['uie'] = DevModeInterface;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
logger.debug('Failed to load dev server interface: ', e);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
19
31
|
async iterateDevServers(callback) {
|
|
20
32
|
const serverKeys = Object.keys(this.devServers);
|
|
21
33
|
|
|
@@ -26,7 +38,17 @@ class DevServerManager {
|
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
generateURL(path) {
|
|
42
|
+
return this.path ? `${this.path}/${path}` : null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async start({
|
|
46
|
+
accountId,
|
|
47
|
+
debug,
|
|
48
|
+
extension,
|
|
49
|
+
projectConfig,
|
|
50
|
+
projectSourceDir,
|
|
51
|
+
}) {
|
|
30
52
|
const app = express();
|
|
31
53
|
|
|
32
54
|
// Install Middleware
|
|
@@ -46,46 +68,49 @@ class DevServerManager {
|
|
|
46
68
|
app.get('/hs/project', (req, res) => {
|
|
47
69
|
res.redirect(getProjectDetailUrl(projectConfig.name, accountId));
|
|
48
70
|
});
|
|
49
|
-
app.get('/hs/learnMore', (req, res) => {
|
|
50
|
-
//TODO link to docs
|
|
51
|
-
res.redirect(getProjectDetailUrl(projectConfig.name, accountId));
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Initialize component servers
|
|
55
|
-
await this.iterateDevServers(async (serverInterface, serverKey) => {
|
|
56
|
-
if (serverInterface.start) {
|
|
57
|
-
const serverApp = await serverInterface.start(serverKey);
|
|
58
|
-
app.use(`/${serverKey}`, serverApp);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
71
|
|
|
62
72
|
// Start server
|
|
63
|
-
this.server = app.listen(
|
|
73
|
+
this.server = await app.listen(DEFAULT_PORT).on('error', err => {
|
|
64
74
|
if (err.code === 'EADDRINUSE') {
|
|
65
|
-
logger.error(
|
|
66
|
-
i18n(`${i18nKey}.portConflict`, { port: port || DEFAULT_PORT })
|
|
67
|
-
);
|
|
75
|
+
logger.error(i18n(`${i18nKey}.portConflict`, { port: DEFAULT_PORT }));
|
|
68
76
|
logger.log();
|
|
69
77
|
process.exit(EXIT_CODES.ERROR);
|
|
70
78
|
}
|
|
71
79
|
});
|
|
72
80
|
|
|
73
|
-
|
|
81
|
+
const projectFiles = await walk(projectSourceDir);
|
|
82
|
+
|
|
83
|
+
// Initialize component servers
|
|
84
|
+
await this.iterateDevServers(async serverInterface => {
|
|
85
|
+
if (serverInterface.start) {
|
|
86
|
+
await serverInterface.start({
|
|
87
|
+
accountId,
|
|
88
|
+
debug,
|
|
89
|
+
extension,
|
|
90
|
+
projectConfig,
|
|
91
|
+
projectFiles,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this.path = this.server.address()
|
|
74
97
|
? `http://localhost:${this.server.address().port}`
|
|
75
98
|
: null;
|
|
76
|
-
}
|
|
77
99
|
|
|
78
|
-
|
|
79
|
-
return { uploadRequired: true };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async execute() {
|
|
83
|
-
return;
|
|
100
|
+
this.initialized = true;
|
|
84
101
|
}
|
|
85
102
|
|
|
86
103
|
async cleanup() {
|
|
87
|
-
if (this.
|
|
88
|
-
await this.
|
|
104
|
+
if (this.initialized) {
|
|
105
|
+
await this.iterateDevServers(async serverInterface => {
|
|
106
|
+
if (serverInterface.cleanup) {
|
|
107
|
+
await serverInterface.cleanup();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (this.server) {
|
|
112
|
+
await this.server.close();
|
|
113
|
+
}
|
|
89
114
|
}
|
|
90
115
|
}
|
|
91
116
|
}
|