@hubspot/cli 4.1.8-beta.0 → 4.1.8-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/README.md +2 -2
- package/commands/accounts/list.js +2 -2
- package/commands/create/api-sample.js +1 -1
- package/commands/project/add.js +56 -0
- package/commands/project/create.js +6 -3
- package/commands/project/deploy.js +32 -18
- package/commands/project/dev.js +278 -0
- package/commands/project/download.js +27 -16
- package/commands/project/upload.js +27 -75
- package/commands/project.js +4 -0
- package/commands/sandbox/create.js +133 -117
- package/commands/sandbox/delete.js +9 -9
- package/commands/sandbox/sync.js +30 -142
- package/lib/CliProgressMultibarManager.js +66 -0
- package/lib/LocalDevManager.js +526 -0
- package/lib/SpinniesManager.js +96 -0
- package/lib/projects.js +314 -126
- package/lib/prompts/accountsPrompt.js +2 -4
- package/lib/prompts/buildIdPrompt.js +35 -0
- package/lib/prompts/createProjectPrompt.js +43 -6
- package/lib/prompts/downloadProjectPrompt.js +44 -0
- package/lib/prompts/projectAddPrompt.js +57 -0
- package/lib/prompts/projectDevTargetAccountPrompt.js +105 -0
- package/lib/prompts/promptUtils.js +13 -0
- package/lib/prompts/sandboxesPrompt.js +50 -11
- package/lib/sandbox-create.js +199 -0
- package/lib/sandbox-sync.js +199 -0
- package/lib/sandboxes.js +296 -105
- package/lib/ui.js +15 -6
- package/package.json +6 -4
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
const Spinnies = require('spinnies');
|
|
2
|
+
const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
3
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
4
|
+
const { i18n } = require('@hubspot/cli-lib/lib/lang');
|
|
5
|
+
const {
|
|
6
|
+
getAvailableSyncTypes,
|
|
7
|
+
pollSyncTaskStatus,
|
|
8
|
+
getAccountName,
|
|
9
|
+
DEVELOPER_SANDBOX,
|
|
10
|
+
sandboxTypeMap,
|
|
11
|
+
syncTypes,
|
|
12
|
+
} = require('./sandboxes');
|
|
13
|
+
const { initiateSync } = require('@hubspot/cli-lib/sandboxes');
|
|
14
|
+
const { logErrorInstance } = require('@hubspot/cli-lib/errorHandlers');
|
|
15
|
+
const {
|
|
16
|
+
isSpecifiedError,
|
|
17
|
+
isMissingScopeError,
|
|
18
|
+
} = require('@hubspot/cli-lib/errorHandlers/apiErrors');
|
|
19
|
+
const { getSandboxTypeAsString } = require('./sandboxes');
|
|
20
|
+
const { getAccountId } = require('@hubspot/cli-lib');
|
|
21
|
+
const { uiAccountDescription } = require('./ui');
|
|
22
|
+
|
|
23
|
+
const i18nKey = 'cli.lib.sandbox.sync';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {Object} accountConfig - Account config of sandbox portal
|
|
27
|
+
* @param {Object} parentAccountConfig - Account config of parent portal
|
|
28
|
+
* @param {String} env - Environment (QA/Prod)
|
|
29
|
+
* @param {Array} syncTasks - Array of available sync tasks
|
|
30
|
+
* @param {Boolean} allowEarlyTermination - Option to allow a keypress to terminate early
|
|
31
|
+
* @param {Boolean} skipPolling - Option to skip progress bars for polling and let sync run in background
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
const syncSandbox = async ({
|
|
35
|
+
accountConfig,
|
|
36
|
+
parentAccountConfig,
|
|
37
|
+
env,
|
|
38
|
+
syncTasks,
|
|
39
|
+
allowEarlyTermination = true,
|
|
40
|
+
skipPolling = false,
|
|
41
|
+
}) => {
|
|
42
|
+
const accountId = getAccountId(accountConfig.portalId);
|
|
43
|
+
const parentAccountId = getAccountId(parentAccountConfig.portalId);
|
|
44
|
+
const spinnies = new Spinnies({
|
|
45
|
+
succeedColor: 'white',
|
|
46
|
+
});
|
|
47
|
+
let initiateSyncResponse;
|
|
48
|
+
let availableSyncTasks = syncTasks;
|
|
49
|
+
|
|
50
|
+
const baseUrl = getHubSpotWebsiteOrigin(env);
|
|
51
|
+
const syncStatusUrl = `${baseUrl}/sandboxes-developer/${parentAccountId}/${getSandboxTypeAsString(
|
|
52
|
+
accountConfig.sandboxAccountType
|
|
53
|
+
)}`;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
// If no sync tasks exist, fetch sync types based on default account. Parent account required for fetch
|
|
57
|
+
if (
|
|
58
|
+
!availableSyncTasks ||
|
|
59
|
+
(typeof availableSyncTasks === 'object' &&
|
|
60
|
+
availableSyncTasks.length === 0)
|
|
61
|
+
) {
|
|
62
|
+
availableSyncTasks = await getAvailableSyncTypes(
|
|
63
|
+
parentAccountConfig,
|
|
64
|
+
accountConfig
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
spinnies.add('sandboxSync', {
|
|
69
|
+
text: i18n(`${i18nKey}.loading.startSync`),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
initiateSyncResponse = await initiateSync(
|
|
73
|
+
parentAccountId,
|
|
74
|
+
accountId,
|
|
75
|
+
availableSyncTasks,
|
|
76
|
+
accountId
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (allowEarlyTermination) {
|
|
80
|
+
logger.log(i18n(`${i18nKey}.info.earlyExit`));
|
|
81
|
+
}
|
|
82
|
+
spinnies.succeed('sandboxSync', {
|
|
83
|
+
text: i18n(`${i18nKey}.loading.succeed`, {
|
|
84
|
+
accountName: uiAccountDescription(accountId),
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
if (
|
|
88
|
+
skipPolling &&
|
|
89
|
+
sandboxTypeMap[accountConfig.sandboxAccountType] === DEVELOPER_SANDBOX
|
|
90
|
+
) {
|
|
91
|
+
if (syncTasks.some(t => t.type === syncTypes.OBJECT_RECORDS)) {
|
|
92
|
+
logger.log(i18n(`${i18nKey}.loading.skipPollingWithContacts`));
|
|
93
|
+
} else {
|
|
94
|
+
logger.log(i18n(`${i18nKey}.loading.skipPolling`));
|
|
95
|
+
}
|
|
96
|
+
logger.log('');
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
spinnies.fail('sandboxSync', {
|
|
100
|
+
text: i18n(`${i18nKey}.loading.fail`),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
logger.log('');
|
|
104
|
+
if (isMissingScopeError(err)) {
|
|
105
|
+
logger.error(
|
|
106
|
+
i18n(`${i18nKey}.failure.missingScopes`, {
|
|
107
|
+
accountName: getAccountName(parentAccountConfig),
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
} else if (
|
|
111
|
+
isSpecifiedError(err, {
|
|
112
|
+
statusCode: 429,
|
|
113
|
+
category: 'RATE_LIMITS',
|
|
114
|
+
subCategory: 'sandboxes-sync-api.SYNC_IN_PROGRESS',
|
|
115
|
+
})
|
|
116
|
+
) {
|
|
117
|
+
logger.error(
|
|
118
|
+
i18n(`${i18nKey}.failure.syncInProgress`, {
|
|
119
|
+
url: `${baseUrl}/sandboxes-developer/${parentAccountId}/syncactivitylog`,
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
} else if (
|
|
123
|
+
isSpecifiedError(err, {
|
|
124
|
+
statusCode: 403,
|
|
125
|
+
category: 'BANNED',
|
|
126
|
+
subCategory: 'sandboxes-sync-api.SYNC_NOT_ALLOWED_INVALID_USERID',
|
|
127
|
+
})
|
|
128
|
+
) {
|
|
129
|
+
// This will only trigger if a user is not a super admin of the target account.
|
|
130
|
+
logger.error(
|
|
131
|
+
i18n(`${i18nKey}.failure.notSuperAdmin`, {
|
|
132
|
+
account: getAccountName(accountConfig),
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
} else if (
|
|
136
|
+
isSpecifiedError(err, {
|
|
137
|
+
statusCode: 404,
|
|
138
|
+
category: 'OBJECT_NOT_FOUND',
|
|
139
|
+
subCategory: 'SandboxErrors.SANDBOX_NOT_FOUND',
|
|
140
|
+
})
|
|
141
|
+
) {
|
|
142
|
+
logger.error(
|
|
143
|
+
i18n(`${i18nKey}.failure.objectNotFound`, {
|
|
144
|
+
account: getAccountName(accountConfig),
|
|
145
|
+
})
|
|
146
|
+
);
|
|
147
|
+
} else {
|
|
148
|
+
logErrorInstance(err);
|
|
149
|
+
}
|
|
150
|
+
logger.log('');
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!skipPolling) {
|
|
155
|
+
try {
|
|
156
|
+
logger.log('');
|
|
157
|
+
logger.log('Sync progress:');
|
|
158
|
+
// Poll sync task status to show progress bars
|
|
159
|
+
await pollSyncTaskStatus(
|
|
160
|
+
parentAccountId,
|
|
161
|
+
initiateSyncResponse.id,
|
|
162
|
+
syncStatusUrl,
|
|
163
|
+
allowEarlyTermination
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
logger.log('');
|
|
167
|
+
spinnies.add('syncComplete', {
|
|
168
|
+
text: i18n(`${i18nKey}.polling.syncing`),
|
|
169
|
+
});
|
|
170
|
+
spinnies.succeed('syncComplete', {
|
|
171
|
+
text: i18n(`${i18nKey}.polling.succeed`),
|
|
172
|
+
});
|
|
173
|
+
logger.log('');
|
|
174
|
+
logger.log(
|
|
175
|
+
i18n(`${i18nKey}.info.syncStatus`, {
|
|
176
|
+
url: syncStatusUrl,
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
// If polling fails at this point, we do not track a failed sync since it is running in the background.
|
|
181
|
+
logErrorInstance(err);
|
|
182
|
+
|
|
183
|
+
spinnies.add('syncComplete', {
|
|
184
|
+
text: i18n(`${i18nKey}.polling.syncing`),
|
|
185
|
+
});
|
|
186
|
+
spinnies.fail('syncComplete', {
|
|
187
|
+
text: i18n(`${i18nKey}.polling.fail`, {
|
|
188
|
+
url: syncStatusUrl,
|
|
189
|
+
}),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
throw err;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
module.exports = {
|
|
198
|
+
syncSandbox,
|
|
199
|
+
};
|