@hubspot/cli 5.1.3 → 5.1.4-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.
Files changed (48) hide show
  1. package/commands/accounts/list.js +43 -31
  2. package/commands/customObject/create.js +10 -6
  3. package/commands/customObject/schema/create.js +10 -9
  4. package/commands/customObject/schema/delete.js +6 -6
  5. package/commands/customObject/schema/fetch.js +1 -1
  6. package/commands/customObject/schema/update.js +10 -9
  7. package/commands/functions/deploy.js +1 -1
  8. package/commands/functions/list.js +1 -1
  9. package/commands/hubdb/clear.js +4 -4
  10. package/commands/hubdb/create.js +5 -5
  11. package/commands/hubdb/delete.js +3 -3
  12. package/commands/hubdb/fetch.js +3 -3
  13. package/commands/mv.js +3 -2
  14. package/commands/project/deploy.js +4 -1
  15. package/commands/project/dev.js +33 -14
  16. package/commands/project/download.js +1 -1
  17. package/commands/project/listBuilds.js +1 -1
  18. package/commands/project/logs.js +7 -7
  19. package/commands/project/upload.js +5 -2
  20. package/commands/project/watch.js +7 -2
  21. package/commands/sandbox/create.js +6 -7
  22. package/commands/sandbox/delete.js +8 -11
  23. package/commands/sandbox/sync.js +18 -17
  24. package/commands/secrets/addSecret.js +5 -6
  25. package/commands/secrets/deleteSecret.js +5 -6
  26. package/commands/secrets/listSecrets.js +5 -6
  27. package/commands/secrets/updateSecret.js +5 -6
  28. package/lang/en.lyaml +3 -2
  29. package/lib/DevServerManager.js +12 -6
  30. package/lib/LocalDevManager.js +1 -1
  31. package/lib/constants.js +11 -0
  32. package/lib/developerTestAccounts.js +14 -0
  33. package/lib/lang.js +3 -1
  34. package/lib/marketplace-validate.js +1 -1
  35. package/lib/projects.js +6 -5
  36. package/lib/projectsWatch.js +61 -19
  37. package/lib/prompts/accountsPrompt.js +5 -7
  38. package/lib/prompts/downloadProjectPrompt.js +1 -1
  39. package/lib/prompts/projectDevTargetAccountPrompt.js +15 -11
  40. package/lib/prompts/projectsLogsPrompt.js +1 -1
  41. package/lib/prompts/sandboxesPrompt.js +12 -13
  42. package/lib/{sandbox-create.js → sandboxCreate.js} +100 -13
  43. package/lib/{sandbox-sync.js → sandboxSync.js} +7 -7
  44. package/lib/sandboxes.js +53 -136
  45. package/lib/schema.js +4 -2
  46. package/lib/ui.js +16 -5
  47. package/lib/validation.js +8 -6
  48. package/package.json +4 -4
package/lib/sandboxes.js CHANGED
@@ -1,49 +1,39 @@
1
- const chalk = require('chalk');
2
- const { i18n } = require('./lang');
1
+ const { i18n, MISSING_LANGUAGE_DATA_PREFIX } = require('./lang');
3
2
  const { handleExit, handleKeypress } = require('./process');
4
3
  const { logger } = require('@hubspot/cli-lib/logger');
5
- const {
6
- getAccessToken,
7
- updateConfigWithAccessToken,
8
- } = require('@hubspot/local-dev-lib/personalAccessKey');
9
4
  const { EXIT_CODES } = require('./enums/exitCodes');
10
- const { enterAccountNamePrompt } = require('./prompts/enterAccountNamePrompt');
11
5
  const {
12
6
  fetchTaskStatus,
13
7
  fetchTypes,
14
8
  getSandboxUsageLimits,
15
9
  } = require('@hubspot/local-dev-lib/sandboxes');
16
- const {
17
- accountNameExistsInConfig,
18
- getConfig,
19
- writeConfig,
20
- updateAccountConfig,
21
- getAccountId,
22
- } = require('@hubspot/local-dev-lib/config');
10
+ const { getConfig, getAccountId } = require('@hubspot/local-dev-lib/config');
23
11
  const CliProgressMultibarManager = require('./CliProgressMultibarManager');
24
12
  const { promptUser } = require('./prompts/promptUtils');
25
13
  const { getHubSpotWebsiteOrigin } = require('@hubspot/local-dev-lib/urls');
26
14
  const {
27
- personalAccessKeyPrompt,
28
- } = require('./prompts/personalAccessKeyPrompt');
29
- const { logErrorInstance } = require('./errorHandlers/standardErrors');
30
-
31
- const STANDARD_SANDBOX = 'standard';
32
- const DEVELOPER_SANDBOX = 'developer';
15
+ HUBSPOT_ACCOUNT_TYPES,
16
+ } = require('@hubspot/local-dev-lib/constants/config');
17
+ const {
18
+ STANDARD_SANDBOX_TYPE,
19
+ DEVELOPER_SANDBOX_TYPE,
20
+ DEVELOPER_SANDBOX,
21
+ STANDARD_SANDBOX,
22
+ } = require('./constants');
33
23
 
34
24
  const syncTypes = {
35
25
  OBJECT_RECORDS: 'object-records',
36
26
  };
37
27
 
38
28
  const sandboxTypeMap = {
39
- DEV: DEVELOPER_SANDBOX,
40
- dev: DEVELOPER_SANDBOX,
41
- DEVELOPER: DEVELOPER_SANDBOX,
42
- developer: DEVELOPER_SANDBOX,
43
- DEVELOPMENT: DEVELOPER_SANDBOX,
44
- development: DEVELOPER_SANDBOX,
45
- STANDARD: STANDARD_SANDBOX,
46
- standard: STANDARD_SANDBOX,
29
+ DEV: DEVELOPER_SANDBOX_TYPE,
30
+ dev: DEVELOPER_SANDBOX_TYPE,
31
+ DEVELOPER: DEVELOPER_SANDBOX_TYPE,
32
+ developer: DEVELOPER_SANDBOX_TYPE,
33
+ DEVELOPMENT: DEVELOPER_SANDBOX_TYPE,
34
+ development: DEVELOPER_SANDBOX_TYPE,
35
+ STANDARD: STANDARD_SANDBOX_TYPE,
36
+ standard: STANDARD_SANDBOX_TYPE,
47
37
  };
48
38
 
49
39
  const sandboxApiTypeMap = {
@@ -51,23 +41,26 @@ const sandboxApiTypeMap = {
51
41
  developer: 2,
52
42
  };
53
43
 
54
- const getSandboxTypeAsString = type =>
55
- type === 'DEVELOPER' ? 'development' : 'standard';
56
-
57
- const isSandbox = config =>
58
- config.sandboxAccountType && config.sandboxAccountType !== null;
44
+ const getSandboxTypeAsString = accountType => {
45
+ if (
46
+ accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX ||
47
+ accountType === DEVELOPER_SANDBOX // remove line once sandboxAccountType is removed
48
+ ) {
49
+ return 'development'; // Only place we're using this specific name
50
+ }
51
+ return STANDARD_SANDBOX_TYPE;
52
+ };
59
53
 
60
- function getAccountName(config, bold = true) {
61
- const sandboxName = `[${getSandboxTypeAsString(
62
- config.sandboxAccountType
54
+ const getSandboxName = config =>
55
+ `[${getSandboxTypeAsString(
56
+ config.accountType || config.sandboxAccountType
63
57
  )} sandbox] `;
64
58
 
65
- const message = `${config.name} ${isSandbox(config) ? sandboxName : ''}(${
66
- config.portalId
67
- })`;
68
-
69
- return bold ? chalk.bold(message) : message;
70
- }
59
+ const isSandbox = config =>
60
+ config.accountType
61
+ ? config.accountType === HUBSPOT_ACCOUNT_TYPES.STANDARD_SANDBOX ||
62
+ config.accountType === HUBSPOT_ACCOUNT_TYPES.DEVELOPMENT_SANDBOX
63
+ : config.sandboxAccountType && config.sandboxAccountType !== null;
71
64
 
72
65
  function getHasSandboxesByType(parentAccountConfig, type) {
73
66
  const config = getConfig();
@@ -153,13 +146,13 @@ const validateSandboxUsageLimits = async (accountConfig, sandboxType, env) => {
153
146
  if (!usage) {
154
147
  throw new Error('Unable to fetch sandbox usage limits. Please try again.');
155
148
  }
156
- if (sandboxType === DEVELOPER_SANDBOX) {
157
- if (usage['DEVELOPER'].available === 0) {
158
- const devSandboxLimit = usage['DEVELOPER'].limit;
149
+ if (sandboxType === DEVELOPER_SANDBOX_TYPE) {
150
+ if (usage[DEVELOPER_SANDBOX].available === 0) {
151
+ const devSandboxLimit = usage[DEVELOPER_SANDBOX].limit;
159
152
  const plural = devSandboxLimit !== 1;
160
153
  const hasDevelopmentSandboxes = getHasSandboxesByType(
161
154
  accountConfig,
162
- DEVELOPER_SANDBOX
155
+ DEVELOPER_SANDBOX_TYPE
163
156
  );
164
157
  if (hasDevelopmentSandboxes) {
165
158
  throw new Error(
@@ -190,13 +183,13 @@ const validateSandboxUsageLimits = async (accountConfig, sandboxType, env) => {
190
183
  }
191
184
  }
192
185
  }
193
- if (sandboxType === STANDARD_SANDBOX) {
194
- if (usage['STANDARD'].available === 0) {
195
- const standardSandboxLimit = usage['STANDARD'].limit;
186
+ if (sandboxType === STANDARD_SANDBOX_TYPE) {
187
+ if (usage[STANDARD_SANDBOX].available === 0) {
188
+ const standardSandboxLimit = usage[STANDARD_SANDBOX].limit;
196
189
  const plural = standardSandboxLimit !== 1;
197
190
  const hasStandardSandboxes = getHasSandboxesByType(
198
191
  accountConfig,
199
- STANDARD_SANDBOX
192
+ STANDARD_SANDBOX_TYPE
200
193
  );
201
194
  if (hasStandardSandboxes) {
202
195
  throw new Error(
@@ -229,78 +222,6 @@ const validateSandboxUsageLimits = async (accountConfig, sandboxType, env) => {
229
222
  }
230
223
  };
231
224
 
232
- /**
233
- * @param {String} env - Environment (QA/Prod)
234
- * @param {Object} result - Sandbox instance returned from API
235
- * @param {Boolean} force - Force flag to skip prompt
236
- * @returns {String} validName saved into config
237
- */
238
- const saveSandboxToConfig = async (env, result, force = false) => {
239
- let personalAccessKey = result.personalAccessKey;
240
- if (!personalAccessKey) {
241
- const configData = await personalAccessKeyPrompt({
242
- env,
243
- account: result.sandbox.sandboxHubId,
244
- });
245
- personalAccessKey = configData.personalAccessKey;
246
- }
247
-
248
- let updatedConfig;
249
-
250
- try {
251
- const token = await getAccessToken(personalAccessKey, env);
252
- updatedConfig = await updateConfigWithAccessToken(
253
- token,
254
- personalAccessKey,
255
- env
256
- );
257
- } catch (e) {
258
- logErrorInstance(e);
259
- }
260
-
261
- if (!updatedConfig) {
262
- throw new Error('Failed to update config with personal access key.');
263
- }
264
-
265
- let validName = updatedConfig.name;
266
- if (!updatedConfig.name) {
267
- const nameForConfig = result.sandbox.name
268
- .toLowerCase()
269
- .split(' ')
270
- .join('-');
271
- validName = nameForConfig;
272
- const invalidAccountName = accountNameExistsInConfig(nameForConfig);
273
- if (invalidAccountName) {
274
- if (!force) {
275
- logger.log('');
276
- logger.warn(
277
- i18n(
278
- `cli.lib.prompts.enterAccountNamePrompt.errors.accountNameExists`,
279
- { name: nameForConfig }
280
- )
281
- );
282
- const { name: promptName } = await enterAccountNamePrompt(
283
- nameForConfig + `_${result.sandbox.sandboxHubId}`
284
- );
285
- validName = promptName;
286
- } else {
287
- // Basic invalid name handling when force flag is passed
288
- validName = nameForConfig + `_${result.sandbox.sandboxHubId}`;
289
- }
290
- }
291
- }
292
- updateAccountConfig({
293
- ...updatedConfig,
294
- environment: updatedConfig.env,
295
- tokenInfo: updatedConfig.auth.tokenInfo,
296
- name: validName,
297
- });
298
- writeConfig();
299
-
300
- logger.log('');
301
- return validName;
302
- };
303
-
304
225
  const ACTIVE_TASK_POLL_INTERVAL = 1000;
305
226
 
306
227
  const isTaskComplete = task => {
@@ -332,7 +253,6 @@ function pollSyncTaskStatus(
332
253
  const mergeTasks = {
333
254
  'lead-flows': 'forms', // lead-flows are a subset of forms. We combine these in the UI as a single item, so we want to merge here for consistency.
334
255
  };
335
- const ignoreTasks = ['gates'];
336
256
  let progressCounter = {};
337
257
  let pollInterval;
338
258
  // Handle manual exit for return key and ctrl+c
@@ -368,16 +288,16 @@ function pollSyncTaskStatus(
368
288
  // Array of sync tasks, eg: workflows, pipelines, object-schemas, etc. with each task containing a status of 'PENDING', 'IN_PROGRESS', 'COMPLETE', and 'FAILURE'
369
289
  for (const task of taskResult.tasks) {
370
290
  // For each sync task, show a progress bar and increment bar each time we run this interval until status is 'COMPLETE'
371
- const taskType = task.type;
372
- if (
373
- !progressBar.get(taskType) &&
374
- !mergeTasks[taskType] &&
375
- !ignoreTasks.includes(taskType)
376
- ) {
291
+ let taskType = task.type;
292
+ const taskTypeLabel = i18n(`${i18nKey}.${taskType}.label`);
293
+ if (taskTypeLabel.startsWith(MISSING_LANGUAGE_DATA_PREFIX)) {
294
+ continue;
295
+ }
296
+ if (!progressBar.get(taskType) && !mergeTasks[taskType]) {
377
297
  // skip creation of lead-flows bar because we're combining lead-flows into the forms bar, otherwise create a bar instance for the type
378
298
  progressCounter[taskType] = 0;
379
299
  progressBar.create(taskType, 100, 0, {
380
- label: i18n(`${i18nKey}.${taskType}.label`),
300
+ label: taskTypeLabel,
381
301
  });
382
302
  } else if (mergeTasks[taskType]) {
383
303
  // It's a lead-flow here, merge status into the forms progress bar
@@ -408,7 +328,7 @@ function pollSyncTaskStatus(
408
328
  }
409
329
  if (progressBar.get(taskType) && task.status === 'COMPLETE') {
410
330
  progressBar.update(taskType, 100, {
411
- label: i18n(`${i18nKey}.${taskType}.label`),
331
+ label: taskTypeLabel,
412
332
  });
413
333
  } else if (
414
334
  // Do not start incrementing for tasks still in PENDING state
@@ -421,7 +341,7 @@ function pollSyncTaskStatus(
421
341
  taskType === syncTypes.OBJECT_RECORDS ? 2 : 3 // slower progress for object-records, sync can take up to a few minutes
422
342
  );
423
343
  progressBar.update(taskType, progressCounter[taskType], {
424
- label: i18n(`${i18nKey}.${taskType}.label`),
344
+ label: taskTypeLabel,
425
345
  });
426
346
  }
427
347
  }
@@ -440,15 +360,12 @@ function pollSyncTaskStatus(
440
360
  }
441
361
 
442
362
  module.exports = {
443
- STANDARD_SANDBOX,
444
- DEVELOPER_SANDBOX,
445
363
  sandboxTypeMap,
446
364
  sandboxApiTypeMap,
447
365
  syncTypes,
448
366
  isSandbox,
367
+ getSandboxName,
449
368
  getSandboxTypeAsString,
450
- getAccountName,
451
- saveSandboxToConfig,
452
369
  getHasSandboxesByType,
453
370
  getSandboxLimit,
454
371
  validateSandboxUsageLimits,
package/lib/schema.js CHANGED
@@ -1,7 +1,9 @@
1
1
  const chalk = require('chalk');
2
2
  const { logger } = require('@hubspot/cli-lib/logger');
3
3
  const { table, getBorderCharacters } = require('table');
4
- const { fetchSchemas } = require('@hubspot/cli-lib/api/schema');
4
+ const {
5
+ fetchObjectSchemas,
6
+ } = require('@hubspot/local-dev-lib/api/customObjects');
5
7
 
6
8
  const logSchemas = schemas => {
7
9
  const data = schemas
@@ -22,7 +24,7 @@ const logSchemas = schemas => {
22
24
  };
23
25
 
24
26
  const listSchemas = async accountId => {
25
- const response = await fetchSchemas(accountId);
27
+ const response = await fetchObjectSchemas(accountId);
26
28
  logSchemas(response.results);
27
29
  };
28
30
 
package/lib/ui.js CHANGED
@@ -4,6 +4,11 @@ const supportsColor = require('../lib/supportsColor');
4
4
  const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
5
5
  const { i18n } = require('./lang');
6
6
  const { logger } = require('@hubspot/cli-lib/logger');
7
+ const { isSandbox, getSandboxName } = require('./sandboxes');
8
+ const {
9
+ isDeveloperTestAccount,
10
+ DEV_TEST_ACCOUNT_STRING,
11
+ } = require('./developerTestAccounts');
7
12
 
8
13
  const UI_COLORS = {
9
14
  SORBET: '#FF8F59',
@@ -65,16 +70,22 @@ const uiLink = (linkText, url) => {
65
70
  };
66
71
 
67
72
  /**
68
- * Returns formatted account name and ID
73
+ * Returns formatted account name, account type (if applicable), and ID
69
74
  *
70
75
  * @param {number} accountId
76
+ * @param {boolean} bold
71
77
  * @returns {string}
72
78
  */
73
- const uiAccountDescription = accountId => {
79
+ const uiAccountDescription = (accountId, bold = true) => {
74
80
  const account = getAccountConfig(accountId);
75
- return chalk.bold(
76
- account.name ? `${account.name} (${account.portalId})` : account.portalId
77
- );
81
+ let accountTypeString = '';
82
+ if (isSandbox(account)) {
83
+ accountTypeString = getSandboxName(account);
84
+ } else if (isDeveloperTestAccount(account)) {
85
+ accountTypeString = `[${DEV_TEST_ACCOUNT_STRING}] `;
86
+ }
87
+ const message = `${account.name} ${accountTypeString}(${account.portalId})`;
88
+ return bold ? chalk.bold(message) : message;
78
89
  };
79
90
 
80
91
  const uiInfoSection = (title, logContent) => {
package/lib/validation.js CHANGED
@@ -206,29 +206,31 @@ const fileExists = _path => {
206
206
  return true;
207
207
  };
208
208
 
209
- const isFileValidJSON = _path => {
209
+ const checkAndConvertToJson = _path => {
210
210
  const filePath = getAbsoluteFilePath(_path);
211
211
  if (!fileExists(filePath)) return false;
212
212
 
213
213
  if (getExt(_path) !== 'json') {
214
214
  logger.error(`The file "${_path}" must be a valid JSON file`);
215
- return false;
215
+ return null;
216
216
  }
217
217
 
218
+ let result;
219
+
218
220
  try {
219
- JSON.parse(fs.readFileSync(filePath));
221
+ result = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
220
222
  } catch (e) {
221
223
  logger.error(`The file "${_path}" contains invalid JSON`);
222
- return false;
224
+ result = null;
223
225
  }
224
226
 
225
- return true;
227
+ return result;
226
228
  };
227
229
 
228
230
  module.exports = {
229
231
  validateMode,
230
232
  validateAccount,
231
- isFileValidJSON,
233
+ checkAndConvertToJson,
232
234
  fileExists,
233
235
  loadAndValidateOptions,
234
236
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "5.1.3",
3
+ "version": "5.1.4-beta.1",
4
4
  "description": "CLI for working with HubSpot",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -9,8 +9,8 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "@hubspot/cli-lib": "^9.0.0",
12
- "@hubspot/local-dev-lib": "^0.3.0",
13
- "@hubspot/serverless-dev-runtime": "5.1.3",
12
+ "@hubspot/local-dev-lib": "^0.3.4",
13
+ "@hubspot/serverless-dev-runtime": "5.1.4-beta.1",
14
14
  "@hubspot/ui-extensions-dev-server": "0.8.9",
15
15
  "archiver": "^5.3.0",
16
16
  "chalk": "^4.1.2",
@@ -45,5 +45,5 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
- "gitHead": "a6b8f2aa5d3585913fb74932d13c3e1891582a84"
48
+ "gitHead": "8c66f7e80438c191d2e5148d9cc08e64dca7cf6e"
49
49
  }