@hubspot/cli 4.0.2-beta.0 → 4.0.2-beta.3

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 CHANGED
@@ -7,7 +7,10 @@ const chalk = require('chalk');
7
7
  const { logger } = require('@hubspot/cli-lib/logger');
8
8
  const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
9
9
  const { setLogLevel, getCommandName } = require('../lib/commonOpts');
10
- const { trackHelpUsage } = require('../lib/usageTracking');
10
+ const {
11
+ trackHelpUsage,
12
+ trackProcessFieldsUsage,
13
+ } = require('../lib/usageTracking');
11
14
  const { getIsInProject } = require('../lib/projects');
12
15
  const pkg = require('../package.json');
13
16
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
@@ -166,3 +169,7 @@ const argv = yargs
166
169
  if (argv.help) {
167
170
  trackHelpUsage(getCommandName(argv));
168
171
  }
172
+
173
+ if (argv.processFieldsJs) {
174
+ trackProcessFieldsUsage(getCommandName(argv));
175
+ }
@@ -1,7 +1,7 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
3
  const { createIgnoreFilter } = require('@hubspot/cli-lib/ignoreRules');
4
- const { isAllowedExtension } = require('@hubspot/cli-lib//path');
4
+ const { isAllowedExtension, getCwd } = require('@hubspot/cli-lib/path');
5
5
  const { logger } = require('@hubspot/cli-lib/logger');
6
6
  const { walk } = require('@hubspot/cli-lib/lib/walk');
7
7
  const { getThemeJSONPath } = require('@hubspot/cli-lib/lib/files');
@@ -10,6 +10,8 @@ const {
10
10
  FieldsJs,
11
11
  isProcessableFieldsJs,
12
12
  } = require('@hubspot/cli-lib/lib/handleFieldsJs');
13
+
14
+ const { trackProcessFieldsUsage } = require('../lib/usageTracking');
13
15
  const i18nKey = 'cli.commands.process';
14
16
 
15
17
  exports.command = 'process';
@@ -24,7 +26,7 @@ const invalidPath = src => {
24
26
  };
25
27
 
26
28
  exports.handler = async options => {
27
- const src = options.src;
29
+ const src = path.resolve(getCwd(), options.src);
28
30
  const projectRoot = path.dirname(getThemeJSONPath(src));
29
31
  let stats;
30
32
  try {
@@ -37,6 +39,8 @@ exports.handler = async options => {
37
39
  invalidPath(src);
38
40
  }
39
41
 
42
+ trackProcessFieldsUsage('process');
43
+
40
44
  if (stats.isFile()) {
41
45
  const fieldsJs = await new FieldsJs(
42
46
  projectRoot,
@@ -14,6 +14,7 @@ const {
14
14
  } = require('../../lib/prompts/createProjectPrompt');
15
15
  const { createProjectConfig } = require('../../lib/projects');
16
16
  const { i18n } = require('@hubspot/cli-lib/lib/lang');
17
+ const { PROJECT_TEMPLATES } = require('@hubspot/cli-lib/lib/constants');
17
18
  const { uiFeatureHighlight } = require('../../lib/ui');
18
19
  const { logger } = require('@hubspot/cli-lib/logger');
19
20
 
@@ -60,6 +61,7 @@ exports.builder = yargs => {
60
61
  template: {
61
62
  describe: i18n(`${i18nKey}.options.template.describe`),
62
63
  type: 'string',
64
+ choices: PROJECT_TEMPLATES.map(template => template.name),
63
65
  },
64
66
  });
65
67
 
@@ -1,4 +1,5 @@
1
1
  const path = require('path');
2
+ const chalk = require('chalk');
2
3
 
3
4
  const {
4
5
  getAccountId,
@@ -37,7 +38,20 @@ exports.handler = async options => {
37
38
 
38
39
  trackCommandUsage('project-download', { projectName }, accountId);
39
40
 
40
- await ensureProjectExists(accountId, projectName, { allowCreate: false });
41
+ const projectExists = await ensureProjectExists(accountId, projectName, {
42
+ allowCreate: false,
43
+ noLogs: true,
44
+ });
45
+
46
+ if (!projectExists) {
47
+ logger.error(
48
+ i18n(`${i18nKey}.errors.projectNotFound`, {
49
+ projectName: chalk.bold(projectName),
50
+ accountId: chalk.bold(accountId),
51
+ })
52
+ );
53
+ process.exit(EXIT_CODES.ERROR);
54
+ }
41
55
 
42
56
  const absoluteDestPath = dest ? path.resolve(getCwd(), dest) : getCwd();
43
57
 
@@ -276,18 +276,18 @@ exports.builder = yargs => {
276
276
  describe: i18n(`${i18nKey}.options.compact.describe`),
277
277
  type: 'boolean',
278
278
  },
279
- follow: {
280
- alias: ['t', 'tail', 'f'],
281
- describe: i18n(`${i18nKey}.options.follow.describe`),
279
+ tail: {
280
+ alias: ['t', 'follow'],
281
+ describe: i18n(`${i18nKey}.options.tail.describe`),
282
282
  type: 'boolean',
283
283
  },
284
284
  limit: {
285
- alias: ['limit', 'n', 'max-count'],
286
285
  describe: i18n(`${i18nKey}.options.limit.describe`),
287
286
  type: 'number',
287
+ default: 10,
288
288
  },
289
289
  })
290
- .conflicts('follow', 'limit');
290
+ .conflicts('tail', 'limit');
291
291
 
292
292
  yargs.example([['$0 project logs', i18n(`${i18nKey}.examples.default`)]]);
293
293
  yargs.example([
@@ -1,5 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { walk } = require('@hubspot/cli-lib/lib/walk');
4
+ const { createIgnoreFilter } = require('@hubspot/cli-lib/ignoreRules');
3
5
  const { uploadFolder, hasUploadErrors } = require('@hubspot/cli-lib');
4
6
  const { getFileMapperQueryValues } = require('@hubspot/cli-lib/fileMapper');
5
7
  const { upload } = require('@hubspot/cli-lib/api/fileMapper');
@@ -26,6 +28,7 @@ const {
26
28
  getMode,
27
29
  } = require('../lib/commonOpts');
28
30
  const { uploadPrompt } = require('../lib/prompts/uploadPrompt');
31
+ const { fieldsJsPrompt } = require('../lib/prompts/cmsFieldPrompt');
29
32
  const { validateMode, loadAndValidateOptions } = require('../lib/validation');
30
33
  const { trackCommandUsage } = require('../lib/usageTracking');
31
34
  const {
@@ -196,6 +199,12 @@ exports.handler = async options => {
196
199
  src,
197
200
  })
198
201
  );
202
+
203
+ // Generate the first-pass file list in here, and pass to uploadFolder.
204
+ const filePaths = await getUploadableFileList(
205
+ absoluteSrcPath,
206
+ options.processFieldsJs
207
+ );
199
208
  uploadFolder(
200
209
  accountId,
201
210
  absoluteSrcPath,
@@ -203,7 +212,8 @@ exports.handler = async options => {
203
212
  {
204
213
  mode,
205
214
  },
206
- options
215
+ options,
216
+ filePaths
207
217
  )
208
218
  .then(results => {
209
219
  if (!hasUploadErrors(results)) {
@@ -237,6 +247,46 @@ exports.handler = async options => {
237
247
  }
238
248
  };
239
249
 
250
+ /*
251
+ * Walks the src folder for files, filters them based on ignore filter.
252
+ * If processFieldsJs is true then will check for any JS fields conflicts (i.e., JS fields file and fields.json file) and prompt to resolve
253
+ */
254
+ const getUploadableFileList = async (src, processFieldsJs) => {
255
+ const filePaths = await walk(src);
256
+ const allowedFiles = filePaths
257
+ .filter(file => {
258
+ if (!isAllowedExtension(file)) {
259
+ return false;
260
+ }
261
+ return true;
262
+ })
263
+ .filter(createIgnoreFilter());
264
+ if (!processFieldsJs) {
265
+ return allowedFiles;
266
+ }
267
+
268
+ let uploadableFiles = [];
269
+ let skipFiles = [];
270
+ for (const filePath of allowedFiles) {
271
+ const fileName = path.basename(filePath);
272
+ if (skipFiles.includes(filePath)) continue;
273
+ const isProcessable = isProcessableFieldsJs(src, filePath, processFieldsJs);
274
+ if (isProcessable || fileName == 'fields.json') {
275
+ // This prompt checks if there are multiple field files in the folder and gets user to choose.
276
+ const [choice, updatedSkipFiles] = await fieldsJsPrompt(
277
+ filePath,
278
+ src,
279
+ skipFiles
280
+ );
281
+ skipFiles = updatedSkipFiles;
282
+ // If they chose something other than the current file, move on.
283
+ if (choice !== filePath) continue;
284
+ }
285
+ uploadableFiles.push(filePath);
286
+ }
287
+ return uploadableFiles;
288
+ };
289
+
240
290
  exports.builder = yargs => {
241
291
  addConfigOptions(yargs, true);
242
292
  addAccountOptions(yargs, true);
package/lib/projects.js CHANGED
@@ -115,7 +115,7 @@ const createProjectConfig = async (projectPath, projectName, template) => {
115
115
  }`
116
116
  );
117
117
 
118
- if (template === 'none') {
118
+ if (template === 'no-template') {
119
119
  fs.ensureDirSync(path.join(projectPath, 'src'));
120
120
 
121
121
  writeProjectConfig(projectConfigPath, {
@@ -47,18 +47,12 @@ const createProjectPrompt = (promptOptions = {}) => {
47
47
  !promptOptions.template ||
48
48
  !PROJECT_TEMPLATES.find(t => t.name === promptOptions.template),
49
49
  type: 'list',
50
- choices: [
51
- {
52
- name: i18n(`${i18nKey}.templateOptions.noTemplate`),
53
- value: 'none',
54
- },
55
- ...PROJECT_TEMPLATES.map(template => {
56
- return {
57
- name: template.label,
58
- value: template.name,
59
- };
60
- }),
61
- ],
50
+ choices: PROJECT_TEMPLATES.map(template => {
51
+ return {
52
+ name: template.label,
53
+ value: template.name,
54
+ };
55
+ }),
62
56
  },
63
57
  ]);
64
58
  };
package/lib/ui.js CHANGED
@@ -37,10 +37,11 @@ const getTerminalUISupport = () => {
37
37
  */
38
38
  const uiLink = (linkText, url) => {
39
39
  const terminalUISupport = getTerminalUISupport();
40
+ const encodedUrl = encodeURI(url);
40
41
  if (terminalUISupport.hyperlinks) {
41
42
  const result = [
42
43
  '\u001B]8;;',
43
- url,
44
+ encodedUrl,
44
45
  '\u0007',
45
46
  linkText,
46
47
  '\u001B]8;;\u0007',
@@ -48,8 +49,8 @@ const uiLink = (linkText, url) => {
48
49
  return terminalUISupport.color ? chalk.cyan(result) : result;
49
50
  } else {
50
51
  return terminalUISupport.color
51
- ? `${linkText}: ${chalk.cyan(url)}`
52
- : `${linkText}: ${url}`;
52
+ ? `${linkText}: ${chalk.cyan(encodedUrl)}`
53
+ : `${linkText}: ${encodedUrl}`;
53
54
  }
54
55
  };
55
56
 
@@ -78,6 +78,24 @@ async function trackHelpUsage(command) {
78
78
  }
79
79
  }
80
80
 
81
+ async function trackProcessFieldsUsage(command) {
82
+ if (!isTrackingAllowed()) {
83
+ return;
84
+ }
85
+ try {
86
+ logger.debug('Attempting to track usage of "%s" command', command);
87
+ await trackUsage('cli-interaction', EventClass.INTERACTION, {
88
+ action: 'cli-process-fields',
89
+ os: getPlatform(),
90
+ ...getNodeVersionData(),
91
+ version,
92
+ command,
93
+ });
94
+ } catch (e) {
95
+ logger.debug('Usage tracking failed: %s', e.message);
96
+ }
97
+ }
98
+
81
99
  const addHelpUsageTracking = (program, command) => {
82
100
  program.on('--help', () => {
83
101
  setLogLevel(program);
@@ -118,5 +136,6 @@ module.exports = {
118
136
  trackCommandUsage,
119
137
  trackHelpUsage,
120
138
  addHelpUsageTracking,
139
+ trackProcessFieldsUsage,
121
140
  trackAuthAction,
122
141
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "4.0.2-beta.0",
3
+ "version": "4.0.2-beta.3",
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.2-beta.0",
12
- "@hubspot/serverless-dev-runtime": "4.0.2-beta.0",
11
+ "@hubspot/cli-lib": "4.0.2-beta.3",
12
+ "@hubspot/serverless-dev-runtime": "4.0.2-beta.3",
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": "861cd70866ca2e8f803d5b61c73fccd04f3d6c75"
40
+ "gitHead": "8d7d59214871eb34d2e9061e253c8d5d39ae0d9a"
41
41
  }