@hubspot/cli 4.0.1-beta.4 → 4.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +2 -0
- package/commands/cms/lighthouseScore.js +4 -1
- package/commands/init.js +3 -0
- package/commands/process.js +85 -0
- package/commands/sandbox/create.js +17 -6
- package/commands/sandbox/delete.js +16 -3
- package/commands/upload.js +72 -16
- package/commands/watch.js +20 -1
- package/lib/projects.js +33 -18
- package/lib/prompts/cmsFieldPrompt.js +50 -0
- package/package.json +4 -4
package/bin/cli.js
CHANGED
|
@@ -35,6 +35,7 @@ const moduleCommand = require('../commands/module');
|
|
|
35
35
|
const configCommand = require('../commands/config');
|
|
36
36
|
const accountsCommand = require('../commands/accounts');
|
|
37
37
|
const sandboxesCommand = require('../commands/sandbox');
|
|
38
|
+
const processCommand = require('../commands/process');
|
|
38
39
|
const cmsCommand = require('../commands/cms');
|
|
39
40
|
const { EXIT_CODES } = require('../lib/enums/exitCodes');
|
|
40
41
|
|
|
@@ -154,6 +155,7 @@ const argv = yargs
|
|
|
154
155
|
.command(configCommand)
|
|
155
156
|
.command(accountsCommand)
|
|
156
157
|
.command(sandboxesCommand)
|
|
158
|
+
.command(processCommand, false)
|
|
157
159
|
.help()
|
|
158
160
|
.recommendCommands()
|
|
159
161
|
.demandCommand(1, '')
|
|
@@ -49,7 +49,10 @@ const selectTheme = async accountId => {
|
|
|
49
49
|
message: i18n(`${i18nKey}.info.promptMessage`),
|
|
50
50
|
choices: async () => {
|
|
51
51
|
try {
|
|
52
|
-
const result = await fetchThemes(accountId
|
|
52
|
+
const result = await fetchThemes(accountId, {
|
|
53
|
+
limit: 500,
|
|
54
|
+
sorting: 'MOST_USED',
|
|
55
|
+
});
|
|
53
56
|
if (result && result.objects) {
|
|
54
57
|
return result.objects
|
|
55
58
|
.map(({ theme }) => theme.path)
|
package/commands/init.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
} = require('@hubspot/cli-lib/lib/config');
|
|
9
9
|
const { addConfigOptions } = require('../lib/commonOpts');
|
|
10
10
|
const { handleExit } = require('@hubspot/cli-lib/lib/process');
|
|
11
|
+
const { checkAndUpdateGitignore } = require('@hubspot/cli-lib/lib/git');
|
|
11
12
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
12
13
|
const {
|
|
13
14
|
DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME,
|
|
@@ -116,6 +117,8 @@ exports.handler = async options => {
|
|
|
116
117
|
);
|
|
117
118
|
const configPath = getConfigPath();
|
|
118
119
|
|
|
120
|
+
checkAndUpdateGitignore(configPath);
|
|
121
|
+
|
|
119
122
|
logger.log('');
|
|
120
123
|
logger.success(
|
|
121
124
|
i18n(`${i18nKey}.success.configFileCreated`, {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { createIgnoreFilter } = require('@hubspot/cli-lib/ignoreRules');
|
|
4
|
+
const { isAllowedExtension } = require('@hubspot/cli-lib//path');
|
|
5
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
6
|
+
const { walk } = require('@hubspot/cli-lib/lib/walk');
|
|
7
|
+
const { getThemeJSONPath } = require('@hubspot/cli-lib/lib/files');
|
|
8
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
9
|
+
const {
|
|
10
|
+
FieldsJs,
|
|
11
|
+
isProcessableFieldsJs,
|
|
12
|
+
} = require('@hubspot/cli-lib/lib/handleFieldsJs');
|
|
13
|
+
const i18nKey = 'cli.commands.process';
|
|
14
|
+
|
|
15
|
+
exports.command = 'process';
|
|
16
|
+
exports.describe = false;
|
|
17
|
+
|
|
18
|
+
const invalidPath = src => {
|
|
19
|
+
logger.error(
|
|
20
|
+
i18n(`${i18nKey}.errors.invalidPath`, {
|
|
21
|
+
path: src,
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.handler = async options => {
|
|
27
|
+
const src = options.src;
|
|
28
|
+
const projectRoot = path.dirname(getThemeJSONPath(src));
|
|
29
|
+
let stats;
|
|
30
|
+
try {
|
|
31
|
+
stats = fs.statSync(src);
|
|
32
|
+
if (!stats.isFile() && !stats.isDirectory()) {
|
|
33
|
+
invalidPath(src);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
} catch (e) {
|
|
37
|
+
invalidPath(src);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (stats.isFile()) {
|
|
41
|
+
const fieldsJs = await new FieldsJs(
|
|
42
|
+
projectRoot,
|
|
43
|
+
src,
|
|
44
|
+
undefined,
|
|
45
|
+
options.fieldOptions
|
|
46
|
+
).init();
|
|
47
|
+
if (fieldsJs.rejected) return;
|
|
48
|
+
fieldsJs.saveOutput();
|
|
49
|
+
} else if (stats.isDirectory()) {
|
|
50
|
+
const filePaths = await walk(src);
|
|
51
|
+
const allowedFilePaths = filePaths
|
|
52
|
+
.filter(file => {
|
|
53
|
+
if (!isAllowedExtension(file)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
})
|
|
58
|
+
.filter(createIgnoreFilter());
|
|
59
|
+
for (const filePath of allowedFilePaths) {
|
|
60
|
+
if (isProcessableFieldsJs(projectRoot, filePath, true)) {
|
|
61
|
+
const fieldsJs = await new FieldsJs(
|
|
62
|
+
projectRoot,
|
|
63
|
+
filePath,
|
|
64
|
+
undefined,
|
|
65
|
+
options.fieldOptions
|
|
66
|
+
).init();
|
|
67
|
+
if (fieldsJs.rejected) return;
|
|
68
|
+
fieldsJs.saveOutput();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
exports.builder = yargs => {
|
|
75
|
+
yargs.positional('src', {
|
|
76
|
+
describe: i18n(`${i18nKey}.positionals.src.describe`),
|
|
77
|
+
type: 'string',
|
|
78
|
+
});
|
|
79
|
+
yargs.option('fieldOptions', {
|
|
80
|
+
describe: i18n(`${i18nKey}.options.options.describe`),
|
|
81
|
+
type: 'array',
|
|
82
|
+
default: [''],
|
|
83
|
+
});
|
|
84
|
+
return yargs;
|
|
85
|
+
};
|
|
@@ -13,6 +13,9 @@ const { loadAndValidateOptions } = require('../../lib/validation');
|
|
|
13
13
|
const { createSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
14
14
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
15
15
|
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
16
|
+
const {
|
|
17
|
+
debugErrorAndContext,
|
|
18
|
+
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
16
19
|
const {
|
|
17
20
|
ENVIRONMENTS,
|
|
18
21
|
PERSONAL_ACCESS_KEY_AUTH_METHOD,
|
|
@@ -103,7 +106,7 @@ const personalAccessKeyFlow = async (env, account, name) => {
|
|
|
103
106
|
]);
|
|
104
107
|
};
|
|
105
108
|
|
|
106
|
-
exports.command = 'create [name]';
|
|
109
|
+
exports.command = 'create [--name]';
|
|
107
110
|
exports.describe = i18n(`${i18nKey}.describe`);
|
|
108
111
|
|
|
109
112
|
exports.handler = async options => {
|
|
@@ -117,10 +120,10 @@ exports.handler = async options => {
|
|
|
117
120
|
succeedColor: 'white',
|
|
118
121
|
});
|
|
119
122
|
|
|
120
|
-
let namePrompt;
|
|
121
|
-
|
|
122
123
|
trackCommandUsage('sandbox-create', {}, accountId);
|
|
123
124
|
|
|
125
|
+
let namePrompt;
|
|
126
|
+
|
|
124
127
|
if (!name) {
|
|
125
128
|
namePrompt = await createSandboxPrompt();
|
|
126
129
|
}
|
|
@@ -146,11 +149,16 @@ exports.handler = async options => {
|
|
|
146
149
|
}),
|
|
147
150
|
});
|
|
148
151
|
} catch (err) {
|
|
152
|
+
debugErrorAndContext(err);
|
|
153
|
+
|
|
154
|
+
trackCommandUsage('sandbox-create', { success: false }, accountId);
|
|
155
|
+
|
|
149
156
|
spinnies.fail('sandboxCreate', {
|
|
150
157
|
text: i18n(`${i18nKey}.loading.fail`, {
|
|
151
158
|
sandboxName,
|
|
152
159
|
}),
|
|
153
160
|
});
|
|
161
|
+
|
|
154
162
|
if (isMissingScopeError(err)) {
|
|
155
163
|
logger.error(
|
|
156
164
|
i18n(`${i18nKey}.failure.scopes.message`, {
|
|
@@ -180,13 +188,16 @@ exports.handler = async options => {
|
|
|
180
188
|
};
|
|
181
189
|
|
|
182
190
|
exports.builder = yargs => {
|
|
183
|
-
yargs.
|
|
184
|
-
describe: i18n(`${i18nKey}.
|
|
191
|
+
yargs.option('name', {
|
|
192
|
+
describe: i18n(`${i18nKey}.options.name.describe`),
|
|
185
193
|
type: 'string',
|
|
186
194
|
});
|
|
187
195
|
|
|
188
196
|
yargs.example([
|
|
189
|
-
[
|
|
197
|
+
[
|
|
198
|
+
'$0 sandbox create --name=MySandboxAccount',
|
|
199
|
+
i18n(`${i18nKey}.examples.default`),
|
|
200
|
+
],
|
|
190
201
|
]);
|
|
191
202
|
|
|
192
203
|
addConfigOptions(yargs, true);
|
|
@@ -8,12 +8,17 @@ const {
|
|
|
8
8
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
9
9
|
const { trackCommandUsage } = require('../../lib/usageTracking');
|
|
10
10
|
const { loadAndValidateOptions } = require('../../lib/validation');
|
|
11
|
+
const {
|
|
12
|
+
debugErrorAndContext,
|
|
13
|
+
} = require('@hubspot/cli-lib/errorHandlers/standardErrors');
|
|
11
14
|
|
|
12
15
|
const { deleteSandbox } = require('@hubspot/cli-lib/sandboxes');
|
|
13
16
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
14
17
|
const { getConfig, getEnv } = require('@hubspot/cli-lib');
|
|
15
18
|
const { deleteSandboxPrompt } = require('../../lib/prompts/sandboxesPrompt');
|
|
16
|
-
const {
|
|
19
|
+
const {
|
|
20
|
+
removeSandboxAccountFromConfig,
|
|
21
|
+
} = require('@hubspot/cli-lib/lib/config');
|
|
17
22
|
const {
|
|
18
23
|
selectAndSetAsDefaultAccountPrompt,
|
|
19
24
|
} = require('../../lib/prompts/accountsPrompt');
|
|
@@ -111,12 +116,18 @@ exports.handler = async options => {
|
|
|
111
116
|
);
|
|
112
117
|
logger.log('');
|
|
113
118
|
|
|
114
|
-
const promptDefaultAccount =
|
|
119
|
+
const promptDefaultAccount = removeSandboxAccountFromConfig(
|
|
120
|
+
sandboxAccountId
|
|
121
|
+
);
|
|
115
122
|
if (promptDefaultAccount) {
|
|
116
123
|
await selectAndSetAsDefaultAccountPrompt(config);
|
|
117
124
|
}
|
|
118
125
|
process.exit(EXIT_CODES.SUCCESS);
|
|
119
126
|
} catch (err) {
|
|
127
|
+
debugErrorAndContext(err);
|
|
128
|
+
|
|
129
|
+
trackCommandUsage('sandbox-delete', { success: false }, sandboxAccountId);
|
|
130
|
+
|
|
120
131
|
if (
|
|
121
132
|
err.error &&
|
|
122
133
|
err.error.category === OBJECT_NOT_FOUND &&
|
|
@@ -130,7 +141,9 @@ exports.handler = async options => {
|
|
|
130
141
|
);
|
|
131
142
|
logger.log('');
|
|
132
143
|
|
|
133
|
-
const promptDefaultAccount =
|
|
144
|
+
const promptDefaultAccount = removeSandboxAccountFromConfig(
|
|
145
|
+
sandboxAccountId
|
|
146
|
+
);
|
|
134
147
|
if (promptDefaultAccount) {
|
|
135
148
|
await selectAndSetAsDefaultAccountPrompt(config);
|
|
136
149
|
}
|
package/commands/upload.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
|
|
4
3
|
const { uploadFolder, hasUploadErrors } = require('@hubspot/cli-lib');
|
|
5
4
|
const { getFileMapperQueryValues } = require('@hubspot/cli-lib/fileMapper');
|
|
6
5
|
const { upload } = require('@hubspot/cli-lib/api/fileMapper');
|
|
@@ -29,11 +28,18 @@ const {
|
|
|
29
28
|
const { uploadPrompt } = require('../lib/prompts/uploadPrompt');
|
|
30
29
|
const { validateMode, loadAndValidateOptions } = require('../lib/validation');
|
|
31
30
|
const { trackCommandUsage } = require('../lib/usageTracking');
|
|
32
|
-
const {
|
|
31
|
+
const {
|
|
32
|
+
getThemePreviewUrl,
|
|
33
|
+
getThemeJSONPath,
|
|
34
|
+
} = require('@hubspot/cli-lib/lib/files');
|
|
33
35
|
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
34
|
-
|
|
35
36
|
const i18nKey = 'cli.commands.upload';
|
|
36
37
|
const { EXIT_CODES } = require('../lib/enums/exitCodes');
|
|
38
|
+
const {
|
|
39
|
+
FieldsJs,
|
|
40
|
+
isProcessableFieldsJs,
|
|
41
|
+
cleanupTmpDirSync,
|
|
42
|
+
} = require('@hubspot/cli-lib/lib/handleFieldsJs');
|
|
37
43
|
|
|
38
44
|
exports.command = 'upload [--src] [--dest]';
|
|
39
45
|
exports.describe = i18n(`${i18nKey}.describe`);
|
|
@@ -61,11 +67,34 @@ exports.handler = async options => {
|
|
|
61
67
|
const mode = getMode(options);
|
|
62
68
|
|
|
63
69
|
const uploadPromptAnswers = await uploadPrompt(options);
|
|
64
|
-
|
|
65
70
|
const src = options.src || uploadPromptAnswers.src;
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
const saveOutput = options.saveOutput;
|
|
72
|
+
let dest = options.dest || uploadPromptAnswers.dest;
|
|
73
|
+
let absoluteSrcPath = path.resolve(getCwd(), src);
|
|
74
|
+
if (!dest) {
|
|
75
|
+
logger.error(i18n(`${i18nKey}.errors.destinationRequired`));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// The theme.json file must always be at the root of the project - so we look for that and determine the root path based on it.
|
|
79
|
+
const projectRoot = path.dirname(getThemeJSONPath(absoluteSrcPath));
|
|
80
|
+
const processFieldsJs = isProcessableFieldsJs(
|
|
81
|
+
projectRoot,
|
|
82
|
+
absoluteSrcPath,
|
|
83
|
+
options.processFieldsJs
|
|
84
|
+
);
|
|
85
|
+
let fieldsJs;
|
|
86
|
+
if (processFieldsJs) {
|
|
87
|
+
fieldsJs = await new FieldsJs(
|
|
88
|
+
projectRoot,
|
|
89
|
+
absoluteSrcPath,
|
|
90
|
+
undefined,
|
|
91
|
+
options.fieldOptions
|
|
92
|
+
).init();
|
|
93
|
+
if (fieldsJs.rejected) return;
|
|
94
|
+
// Ensures that the dest path is a .json. The user might pass '.js' accidentally - this ensures it just works.
|
|
95
|
+
absoluteSrcPath = fieldsJs.outputPath;
|
|
96
|
+
dest = path.join(path.dirname(dest), 'fields.json');
|
|
97
|
+
}
|
|
69
98
|
let stats;
|
|
70
99
|
try {
|
|
71
100
|
stats = fs.statSync(absoluteSrcPath);
|
|
@@ -86,10 +115,6 @@ exports.handler = async options => {
|
|
|
86
115
|
return;
|
|
87
116
|
}
|
|
88
117
|
|
|
89
|
-
if (!dest) {
|
|
90
|
-
logger.error(i18n(`${i18nKey}.errors.destinationRequired`));
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
118
|
const normalizedDest = convertToUnixPath(dest);
|
|
94
119
|
trackCommandUsage(
|
|
95
120
|
'upload',
|
|
@@ -106,7 +131,7 @@ exports.handler = async options => {
|
|
|
106
131
|
process.exit(EXIT_CODES.WARNING);
|
|
107
132
|
}
|
|
108
133
|
if (stats.isFile()) {
|
|
109
|
-
if (!isAllowedExtension(src)) {
|
|
134
|
+
if (!isAllowedExtension(src) && !processFieldsJs) {
|
|
110
135
|
logger.error(
|
|
111
136
|
i18n(`${i18nKey}.errors.invalidPath`, {
|
|
112
137
|
path: src,
|
|
@@ -123,7 +148,6 @@ exports.handler = async options => {
|
|
|
123
148
|
);
|
|
124
149
|
return;
|
|
125
150
|
}
|
|
126
|
-
|
|
127
151
|
upload(
|
|
128
152
|
accountId,
|
|
129
153
|
absoluteSrcPath,
|
|
@@ -156,6 +180,13 @@ exports.handler = async options => {
|
|
|
156
180
|
})
|
|
157
181
|
);
|
|
158
182
|
process.exit(EXIT_CODES.WARNING);
|
|
183
|
+
})
|
|
184
|
+
.finally(() => {
|
|
185
|
+
if (!processFieldsJs) return;
|
|
186
|
+
if (saveOutput) {
|
|
187
|
+
fieldsJs.saveOutput();
|
|
188
|
+
}
|
|
189
|
+
cleanupTmpDirSync(fieldsJs.rootWriteDir);
|
|
159
190
|
});
|
|
160
191
|
} else {
|
|
161
192
|
logger.log(
|
|
@@ -165,9 +196,15 @@ exports.handler = async options => {
|
|
|
165
196
|
src,
|
|
166
197
|
})
|
|
167
198
|
);
|
|
168
|
-
uploadFolder(
|
|
169
|
-
|
|
170
|
-
|
|
199
|
+
uploadFolder(
|
|
200
|
+
accountId,
|
|
201
|
+
absoluteSrcPath,
|
|
202
|
+
dest,
|
|
203
|
+
{
|
|
204
|
+
mode,
|
|
205
|
+
},
|
|
206
|
+
options
|
|
207
|
+
)
|
|
171
208
|
.then(results => {
|
|
172
209
|
if (!hasUploadErrors(results)) {
|
|
173
210
|
logger.success(
|
|
@@ -214,5 +251,24 @@ exports.builder = yargs => {
|
|
|
214
251
|
describe: i18n(`${i18nKey}.positionals.dest.describe`),
|
|
215
252
|
type: 'string',
|
|
216
253
|
});
|
|
254
|
+
yargs.option('fieldOptions', {
|
|
255
|
+
describe: i18n(`${i18nKey}.options.options.describe`),
|
|
256
|
+
type: 'array',
|
|
257
|
+
default: [''],
|
|
258
|
+
hidden: true,
|
|
259
|
+
});
|
|
260
|
+
yargs.option('saveOutput', {
|
|
261
|
+
describe: i18n(`${i18nKey}.options.saveOutput.describe`),
|
|
262
|
+
type: 'boolean',
|
|
263
|
+
default: false,
|
|
264
|
+
hidden: true,
|
|
265
|
+
});
|
|
266
|
+
yargs.option('processFieldsJs', {
|
|
267
|
+
describe: i18n(`${i18nKey}.options.processFields.describe`),
|
|
268
|
+
alias: ['processFields'],
|
|
269
|
+
type: 'boolean',
|
|
270
|
+
default: false,
|
|
271
|
+
hidden: true,
|
|
272
|
+
});
|
|
217
273
|
return yargs;
|
|
218
274
|
};
|
package/commands/watch.js
CHANGED
|
@@ -82,6 +82,7 @@ exports.handler = async options => {
|
|
|
82
82
|
remove,
|
|
83
83
|
disableInitial: initialUpload ? false : true,
|
|
84
84
|
notify,
|
|
85
|
+
commandOptions: options,
|
|
85
86
|
});
|
|
86
87
|
};
|
|
87
88
|
|
|
@@ -99,6 +100,12 @@ exports.builder = yargs => {
|
|
|
99
100
|
describe: i18n(`${i18nKey}.positionals.dest.describe`),
|
|
100
101
|
type: 'string',
|
|
101
102
|
});
|
|
103
|
+
yargs.option('fieldOptions', {
|
|
104
|
+
describe: i18n(`${i18nKey}.options.options.describe`),
|
|
105
|
+
type: 'array',
|
|
106
|
+
default: [''],
|
|
107
|
+
hidden: true,
|
|
108
|
+
});
|
|
102
109
|
yargs.option('remove', {
|
|
103
110
|
alias: 'r',
|
|
104
111
|
describe: i18n(`${i18nKey}.options.remove.describe`),
|
|
@@ -121,6 +128,18 @@ exports.builder = yargs => {
|
|
|
121
128
|
type: 'string',
|
|
122
129
|
requiresArg: true,
|
|
123
130
|
});
|
|
124
|
-
|
|
131
|
+
yargs.option('processFieldsJs', {
|
|
132
|
+
describe: i18n(`${i18nKey}.options.processFields.describe`),
|
|
133
|
+
alias: ['processFields'],
|
|
134
|
+
type: 'boolean',
|
|
135
|
+
default: false,
|
|
136
|
+
hidden: true,
|
|
137
|
+
});
|
|
138
|
+
yargs.option('saveOutput', {
|
|
139
|
+
describe: i18n(`${i18nKey}.options.saveOutput.describe`),
|
|
140
|
+
type: 'boolean',
|
|
141
|
+
default: false,
|
|
142
|
+
hidden: true,
|
|
143
|
+
});
|
|
125
144
|
return yargs;
|
|
126
145
|
};
|
package/lib/projects.js
CHANGED
|
@@ -224,6 +224,13 @@ const getProjectBuildDetailUrl = (projectName, buildId, accountId) => {
|
|
|
224
224
|
return `${getProjectDetailUrl(projectName, accountId)}/build/${buildId}`;
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
+
const getProjectDeployDetailUrl = (projectName, deployId, accountId) => {
|
|
228
|
+
if (!projectName || !deployId || !accountId) return;
|
|
229
|
+
return `${getProjectDetailUrl(
|
|
230
|
+
projectName,
|
|
231
|
+
accountId
|
|
232
|
+
)}/activity/deploy/${deployId}`;
|
|
233
|
+
};
|
|
227
234
|
const uploadProjectFiles = async (accountId, projectName, filePath) => {
|
|
228
235
|
const i18nKey = 'cli.commands.project.subcommands.upload';
|
|
229
236
|
const spinnies = new Spinnies({
|
|
@@ -343,10 +350,13 @@ const makePollTaskStatusFunc = ({
|
|
|
343
350
|
}
|
|
344
351
|
};
|
|
345
352
|
|
|
346
|
-
return async (accountId, taskName, taskId) => {
|
|
347
|
-
|
|
353
|
+
return async (accountId, taskName, taskId, deployedBuildId = null) => {
|
|
354
|
+
const displayId = deployedBuildId || taskId;
|
|
355
|
+
|
|
348
356
|
if (linkToHubSpot) {
|
|
349
|
-
logger.log(
|
|
357
|
+
logger.log(
|
|
358
|
+
`\n${linkToHubSpot(accountId, taskName, taskId, deployedBuildId)}\n`
|
|
359
|
+
);
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
const spinnies = new Spinnies({
|
|
@@ -372,7 +382,7 @@ const makePollTaskStatusFunc = ({
|
|
|
372
382
|
const subTaskName = subTask[statusText.SUBTASK_NAME_KEY];
|
|
373
383
|
|
|
374
384
|
spinnies.add(subTaskName, {
|
|
375
|
-
text: `${chalk.bold(subTaskName)} #${
|
|
385
|
+
text: `${chalk.bold(subTaskName)} #${displayId} ${
|
|
376
386
|
statusText.STATUS_TEXT[statusText.STATES.ENQUEUED]
|
|
377
387
|
}\n`,
|
|
378
388
|
indent: 2,
|
|
@@ -395,7 +405,7 @@ const makePollTaskStatusFunc = ({
|
|
|
395
405
|
return;
|
|
396
406
|
}
|
|
397
407
|
|
|
398
|
-
const updatedText = `${chalk.bold(subTaskName)} #${
|
|
408
|
+
const updatedText = `${chalk.bold(subTaskName)} #${displayId} ${
|
|
399
409
|
statusText.STATUS_TEXT[subTask.status]
|
|
400
410
|
}\n`;
|
|
401
411
|
|
|
@@ -413,17 +423,17 @@ const makePollTaskStatusFunc = ({
|
|
|
413
423
|
});
|
|
414
424
|
|
|
415
425
|
if (isTaskComplete(taskStatus)) {
|
|
416
|
-
subTaskStatus.forEach(subTask => {
|
|
417
|
-
|
|
418
|
-
});
|
|
426
|
+
// subTaskStatus.forEach(subTask => {
|
|
427
|
+
// spinnies.remove(subTask[statusText.SUBTASK_NAME_KEY]);
|
|
428
|
+
// });
|
|
419
429
|
|
|
420
430
|
if (status === statusText.STATES.SUCCESS) {
|
|
421
431
|
spinnies.succeed('overallTaskStatus', {
|
|
422
|
-
text:
|
|
432
|
+
text: statusStrings.SUCCESS(taskName),
|
|
423
433
|
});
|
|
424
434
|
} else if (status === statusText.STATES.FAILURE) {
|
|
425
435
|
spinnies.fail('overallTaskStatus', {
|
|
426
|
-
text:
|
|
436
|
+
text: statusStrings.FAIL(taskName),
|
|
427
437
|
});
|
|
428
438
|
|
|
429
439
|
const failedSubtask = subTaskStatus.filter(
|
|
@@ -433,7 +443,7 @@ const makePollTaskStatusFunc = ({
|
|
|
433
443
|
uiLine();
|
|
434
444
|
logger.log(
|
|
435
445
|
`${statusStrings.SUBTASK_FAIL(
|
|
436
|
-
|
|
446
|
+
displayId,
|
|
437
447
|
failedSubtask.length === 1
|
|
438
448
|
? failedSubtask[0][statusText.SUBTASK_NAME_KEY]
|
|
439
449
|
: failedSubtask.length + ' components'
|
|
@@ -470,10 +480,10 @@ const makePollTaskStatusFunc = ({
|
|
|
470
480
|
};
|
|
471
481
|
|
|
472
482
|
const pollBuildStatus = makePollTaskStatusFunc({
|
|
473
|
-
linkToHubSpot: (
|
|
483
|
+
linkToHubSpot: (accountId, taskName, taskId) =>
|
|
474
484
|
uiLink(
|
|
475
|
-
`View build #${
|
|
476
|
-
getProjectBuildDetailUrl(
|
|
485
|
+
`View build #${taskId} in HubSpot`,
|
|
486
|
+
getProjectBuildDetailUrl(taskName, taskId, accountId)
|
|
477
487
|
),
|
|
478
488
|
statusFn: getBuildStatus,
|
|
479
489
|
statusText: PROJECT_BUILD_TEXT,
|
|
@@ -481,22 +491,27 @@ const pollBuildStatus = makePollTaskStatusFunc({
|
|
|
481
491
|
INITIALIZE: name => `Building ${chalk.bold(name)}`,
|
|
482
492
|
SUCCESS: name => `Built ${chalk.bold(name)}`,
|
|
483
493
|
FAIL: name => `Failed to build ${chalk.bold(name)}`,
|
|
484
|
-
SUBTASK_FAIL: (
|
|
485
|
-
`Build #${
|
|
494
|
+
SUBTASK_FAIL: (buildId, name) =>
|
|
495
|
+
`Build #${buildId} failed because there was a problem\nbuilding ${chalk.bold(
|
|
486
496
|
name
|
|
487
497
|
)}`,
|
|
488
498
|
},
|
|
489
499
|
});
|
|
490
500
|
|
|
491
501
|
const pollDeployStatus = makePollTaskStatusFunc({
|
|
502
|
+
linkToHubSpot: (accountId, taskName, taskId, deployedBuildId) =>
|
|
503
|
+
uiLink(
|
|
504
|
+
`View deploy of build #${deployedBuildId} in HubSpot`,
|
|
505
|
+
getProjectDeployDetailUrl(taskName, taskId, accountId)
|
|
506
|
+
),
|
|
492
507
|
statusFn: getDeployStatus,
|
|
493
508
|
statusText: PROJECT_DEPLOY_TEXT,
|
|
494
509
|
statusStrings: {
|
|
495
510
|
INITIALIZE: name => `Deploying ${chalk.bold(name)}`,
|
|
496
511
|
SUCCESS: name => `Deployed ${chalk.bold(name)}`,
|
|
497
512
|
FAIL: name => `Failed to deploy ${chalk.bold(name)}`,
|
|
498
|
-
SUBTASK_FAIL: (
|
|
499
|
-
`Deploy for build #${
|
|
513
|
+
SUBTASK_FAIL: (deployedBuildId, name) =>
|
|
514
|
+
`Deploy for build #${deployedBuildId} failed because there was a\nproblem deploying ${chalk.bold(
|
|
500
515
|
name
|
|
501
516
|
)}`,
|
|
502
517
|
},
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { promptUser } = require('./promptUtils');
|
|
4
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
5
|
+
const escapeRegExp = require('@hubspot/cli-lib/lib/escapeRegExp');
|
|
6
|
+
const i18nKey = 'cli.lib.prompts.uploadPrompt';
|
|
7
|
+
const FIELDS_FILES = ['fields.json', 'fields.js', 'fields.cjs', 'fields.mjs'];
|
|
8
|
+
|
|
9
|
+
const fieldsJsPrompt = async (filePath, projectDir, skipFiles = []) => {
|
|
10
|
+
const dirName = path.dirname(filePath);
|
|
11
|
+
|
|
12
|
+
// Get a list of all field files in the directory, resolve their absolute path, and remove the ones that we already skipped.
|
|
13
|
+
const fileChoices = fs
|
|
14
|
+
.readdirSync(dirName)
|
|
15
|
+
.filter(file => FIELDS_FILES.includes(file))
|
|
16
|
+
.map(file => path.resolve(dirName, file))
|
|
17
|
+
.filter(file => !skipFiles.includes(file));
|
|
18
|
+
|
|
19
|
+
if (!fileChoices.length) return [filePath, []];
|
|
20
|
+
if (fileChoices.length == 1) return [fileChoices[0], []];
|
|
21
|
+
|
|
22
|
+
// We get the directory above the project one so that relative paths are printed with the root of the project dir attached.
|
|
23
|
+
projectDir = projectDir.substring(0, projectDir.lastIndexOf('/'));
|
|
24
|
+
const projectDirRegex = new RegExp(`^${escapeRegExp(projectDir)}`);
|
|
25
|
+
const fileDir = path.dirname(fileChoices[0]).replace(projectDirRegex, '');
|
|
26
|
+
|
|
27
|
+
const selection = [];
|
|
28
|
+
fileChoices.forEach(fileChoice => {
|
|
29
|
+
selection.push({
|
|
30
|
+
name: fileChoice.replace(projectDirRegex, ''),
|
|
31
|
+
value: fileChoice,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
const promptVal = await promptUser([
|
|
35
|
+
{
|
|
36
|
+
message: i18n(`${i18nKey}.fieldsPrompt`, { dir: fileDir }),
|
|
37
|
+
type: 'list',
|
|
38
|
+
name: 'filePathChoice',
|
|
39
|
+
choices: selection,
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
const choice = promptVal.filePathChoice;
|
|
43
|
+
|
|
44
|
+
// Add the ones that were not picked to skip files array.
|
|
45
|
+
const notPicked = fileChoices.filter(item => item !== choice);
|
|
46
|
+
skipFiles.push(...notPicked);
|
|
47
|
+
return [choice, skipFiles];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
module.exports = { fieldsJsPrompt };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2-beta.0",
|
|
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/cli-lib": "4.0.
|
|
12
|
-
"@hubspot/serverless-dev-runtime": "4.0.
|
|
11
|
+
"@hubspot/cli-lib": "4.0.2-beta.0",
|
|
12
|
+
"@hubspot/serverless-dev-runtime": "4.0.2-beta.0",
|
|
13
13
|
"archiver": "^5.3.0",
|
|
14
14
|
"chalk": "^4.1.2",
|
|
15
15
|
"express": "^4.17.1",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "861cd70866ca2e8f803d5b61c73fccd04f3d6c75"
|
|
41
41
|
}
|