@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.
@@ -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
+ };