@contentstack/cli-cm-bulk-publish 0.1.1-beta.1 → 0.1.1-beta.4
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 +70 -18
- package/oclif.manifest.json +1 -1
- package/package.json +6 -5
- package/src/commands/cm/bulk-publish/add-fields.js +18 -13
- package/src/commands/cm/bulk-publish/assets.js +15 -10
- package/src/commands/cm/bulk-publish/clear.js +8 -6
- package/src/commands/cm/bulk-publish/configure.js +5 -7
- package/src/commands/cm/bulk-publish/cross-publish.js +24 -26
- package/src/commands/cm/bulk-publish/entries.js +26 -20
- package/src/commands/cm/bulk-publish/entry-edits.js +23 -17
- package/src/commands/cm/bulk-publish/nonlocalized-field-changes.js +14 -9
- package/src/commands/cm/bulk-publish/revert.js +5 -5
- package/src/commands/cm/bulk-publish/unpublish.js +24 -15
- package/src/commands/cm/bulk-publish/unpublished-entries.js +17 -12
- package/src/config/index.js +88 -88
- package/src/consumer/publish.js +5 -7
- package/src/producer/add-fields.js +30 -35
- package/src/producer/cross-publish.js +99 -92
- package/src/producer/nonlocalized-field-changes.js +27 -38
- package/src/producer/publish-assets.js +18 -25
- package/src/producer/publish-edits.js +24 -35
- package/src/producer/publish-entries.js +26 -33
- package/src/producer/publish-unpublished-env.js +24 -35
- package/src/producer/revert.js +4 -4
- package/src/producer/unpublish.js +99 -106
- package/src/util/client.js +16 -11
- package/src/util/queue.js +2 -2
- package/src/util/request.js +6 -4
- package/src/util/store.js +8 -12
|
@@ -7,11 +7,10 @@ const {getQueue} = require('../util/queue')
|
|
|
7
7
|
const defaults = require('../config/defaults.json')
|
|
8
8
|
const req = require('../util/request')
|
|
9
9
|
const {
|
|
10
|
-
|
|
10
|
+
performBulkUnPublish, UnpublishEntry, UnpublishAsset, initializeLogger,
|
|
11
11
|
} = require('../consumer/publish')
|
|
12
12
|
const retryFailedLogs = require('../util/retryfailed')
|
|
13
13
|
const {validateFile} = require('../util/fs')
|
|
14
|
-
const types = 'asset_published,entry_published'
|
|
15
14
|
const queue = getQueue()
|
|
16
15
|
const entryQueue = getQueue()
|
|
17
16
|
const assetQueue = getQueue()
|
|
@@ -28,7 +27,7 @@ let filePath
|
|
|
28
27
|
function setConfig(conf, bup) {
|
|
29
28
|
if (bup) {
|
|
30
29
|
logFileName = 'bulk-unpublish'
|
|
31
|
-
queue.consumer =
|
|
30
|
+
queue.consumer = performBulkUnPublish
|
|
32
31
|
} else {
|
|
33
32
|
logFileName = 'unpublish'
|
|
34
33
|
entryQueue.consumer = UnpublishEntry
|
|
@@ -54,71 +53,70 @@ function getQueryParams(filter) {
|
|
|
54
53
|
return queryString
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
publish_details: [items[index].data.publish_details] || [],
|
|
72
|
-
})
|
|
73
|
-
}
|
|
56
|
+
function bulkAction(stack, items, bulkUnpublish, environment, locale) {
|
|
57
|
+
return new Promise(async resolve => {
|
|
58
|
+
for (let index = 0; index < items.length; index++) {
|
|
59
|
+
changedFlag = true
|
|
60
|
+
|
|
61
|
+
if (bulkUnpublish) {
|
|
62
|
+
if (bulkUnPublishSet.length < 10 && items[index].type === 'entry_published') {
|
|
63
|
+
bulkUnPublishSet.push({
|
|
64
|
+
uid: items[index].data.uid,
|
|
65
|
+
content_type: items[index].content_type_uid,
|
|
66
|
+
locale: items[index].data.locale || 'en-us',
|
|
67
|
+
publish_details: [items[index].data.publish_details] || [],
|
|
68
|
+
})
|
|
69
|
+
}
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
if (bulkUnPulishAssetSet.length < 10 && items[index].type === 'asset_published') {
|
|
72
|
+
bulkUnPulishAssetSet.push({
|
|
73
|
+
uid: items[index].data.uid,
|
|
74
|
+
version: items[index].data._version,
|
|
75
|
+
publish_details: [items[index].data.publish_details] || [],
|
|
76
|
+
})
|
|
77
|
+
}
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
79
|
+
if (bulkUnPulishAssetSet.length === 10) {
|
|
80
|
+
await queue.Enqueue({
|
|
81
|
+
assets: bulkUnPulishAssetSet, Type: 'asset', locale: locale, environments: [environment], stack: stack
|
|
82
|
+
})
|
|
83
|
+
bulkUnPulishAssetSet = []
|
|
84
|
+
}
|
|
89
85
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
if (bulkUnPublishSet.length === 10) {
|
|
87
|
+
await queue.Enqueue({
|
|
88
|
+
entries: bulkUnPublishSet, locale: locale, Type: 'entry', environments: [environment], stack: stack
|
|
89
|
+
})
|
|
90
|
+
bulkUnPublishSet = []
|
|
91
|
+
}
|
|
92
|
+
if (index === items.length - 1 && bulkUnPulishAssetSet.length <= 10 && bulkUnPulishAssetSet.length > 0) {
|
|
93
|
+
await queue.Enqueue({
|
|
94
|
+
assets: bulkUnPulishAssetSet, Type: 'asset', locale: locale, environments: [environment], stack: stack
|
|
95
|
+
})
|
|
96
|
+
bulkUnPulishAssetSet = []
|
|
97
|
+
}
|
|
102
98
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
99
|
+
if (index === items.length - 1 && bulkUnPublishSet.length <= 10 && bulkUnPublishSet.length > 0) {
|
|
100
|
+
await queue.Enqueue({
|
|
101
|
+
entries: bulkUnPublishSet, locale: locale, Type: 'entry', environments: [environment], stack: stack
|
|
102
|
+
})
|
|
103
|
+
bulkUnPublishSet = []
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
if (items[index].type === 'entry_published') {
|
|
107
|
+
await entryQueue.Enqueue({
|
|
108
|
+
content_type: items[index].content_type_uid, publish_details: [items[index].data.publish_details], environments: [environment], entryUid: items[index].data.uid, locale: items[index].data.locale || 'en-us', Type: 'entry', stack: stack
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
if (items[index].type === 'asset_published') {
|
|
112
|
+
await assetQueue.Enqueue({
|
|
113
|
+
assetUid: items[index].data.uid, publish_details: [items[index].data.publish_details], environments: [environment], Type: 'entry', stack: stack
|
|
114
|
+
})
|
|
115
|
+
}
|
|
119
116
|
}
|
|
120
117
|
}
|
|
121
|
-
|
|
118
|
+
return resolve()
|
|
119
|
+
})
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
async function getSyncEntries(stack, config, locale, queryParams, bulkUnpublish, environment, deliveryToken, paginationToken = null) {
|
|
@@ -134,20 +132,19 @@ async function getSyncEntries(stack, config, locale, queryParams, bulkUnpublish,
|
|
|
134
132
|
}
|
|
135
133
|
const entriesResponse = await req(conf)
|
|
136
134
|
if (entriesResponse.items.length > 0) {
|
|
137
|
-
bulkAction(stack, entriesResponse.items, bulkUnpublish, environment, locale)
|
|
135
|
+
await bulkAction(stack, entriesResponse.items, bulkUnpublish, environment, locale)
|
|
138
136
|
}
|
|
139
137
|
if (entriesResponse.items.length === 0) {
|
|
140
138
|
if (!changedFlag) console.log('No Entries/Assets Found published on specified environment')
|
|
141
139
|
return resolve()
|
|
142
140
|
}
|
|
143
|
-
setTimeout(() => {
|
|
144
|
-
getSyncEntries(stack, config, locale, queryParams, bulkUnpublish, environment, deliveryToken, null)
|
|
141
|
+
setTimeout(async () => {
|
|
142
|
+
await getSyncEntries(stack, config, locale, queryParams, bulkUnpublish, environment, deliveryToken, null)
|
|
145
143
|
}, 3000)
|
|
146
144
|
} catch (error) {
|
|
147
145
|
reject(error)
|
|
148
146
|
}
|
|
149
147
|
})
|
|
150
|
-
// return true
|
|
151
148
|
}
|
|
152
149
|
|
|
153
150
|
async function start({retryFailed, bulkUnpublish, contentType, locale, environment, deliveryToken, onlyAssets, onlyEntries, f_types}, stack, config) {
|
|
@@ -159,51 +156,47 @@ async function start({retryFailed, bulkUnpublish, contentType, locale, environme
|
|
|
159
156
|
} else if (!isSuccessLogEmpty) {
|
|
160
157
|
console.log(`The success log for this session is stored at ${filePath}.success`)
|
|
161
158
|
}
|
|
162
|
-
process.exit(0)
|
|
159
|
+
process.exit(0)
|
|
163
160
|
})
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
if (retryFailed) {
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
return false
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
bulkUnpublish = retryFailed.match(new RegExp('bulk')) ? true : false
|
|
173
|
-
setConfig(config, bulkUnpublish)
|
|
174
|
-
|
|
175
|
-
if (bulkUnpublish) {
|
|
176
|
-
await retryFailedLogs(retryFailed, queue, 'bulk')
|
|
177
|
-
} else {
|
|
178
|
-
await retryFailedLogs(retryFailed, {entryQueue, assetQueue}, 'publish')
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
let filter = {
|
|
183
|
-
environment,
|
|
184
|
-
locale,
|
|
185
|
-
}
|
|
186
|
-
filter.type = (f_types) ? f_types : types // types mentioned in the config file (f_types) are given preference
|
|
187
|
-
if (contentType) {
|
|
188
|
-
filter.content_type_uid = contentType
|
|
189
|
-
}
|
|
190
|
-
if (onlyAssets) {
|
|
191
|
-
filter.type = 'asset_published'
|
|
192
|
-
delete filter.content_type_uid
|
|
193
|
-
}
|
|
194
|
-
if (onlyEntries) {
|
|
195
|
-
filter.type = 'entry_published'
|
|
162
|
+
if (retryFailed) {
|
|
163
|
+
if (typeof retryFailed === 'string' && retryFailed.length > 0) {
|
|
164
|
+
if (!validateFile(retryFailed, ['unpublish', 'bulk-unpublish'])) {
|
|
165
|
+
return false
|
|
196
166
|
}
|
|
167
|
+
|
|
168
|
+
bulkUnpublish = retryFailed.match(new RegExp('bulk')) ? true : false
|
|
197
169
|
setConfig(config, bulkUnpublish)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
await
|
|
201
|
-
}
|
|
202
|
-
|
|
170
|
+
|
|
171
|
+
if (bulkUnpublish) {
|
|
172
|
+
await retryFailedLogs(retryFailed, queue, 'bulk')
|
|
173
|
+
} else {
|
|
174
|
+
await retryFailedLogs(retryFailed, {entryQueue, assetQueue}, 'publish')
|
|
203
175
|
}
|
|
204
176
|
}
|
|
205
|
-
}
|
|
206
|
-
|
|
177
|
+
} else {
|
|
178
|
+
let filter = {
|
|
179
|
+
environment,
|
|
180
|
+
locale,
|
|
181
|
+
}
|
|
182
|
+
if (f_types) {
|
|
183
|
+
filter.type = f_types
|
|
184
|
+
}
|
|
185
|
+
// filter.type = (f_types) ? f_types : types // types mentioned in the config file (f_types) are given preference
|
|
186
|
+
if (contentType) {
|
|
187
|
+
filter.content_type_uid = contentType
|
|
188
|
+
filter.type = 'entry_published'
|
|
189
|
+
}
|
|
190
|
+
if (onlyAssets) {
|
|
191
|
+
filter.type = 'asset_published'
|
|
192
|
+
delete filter.content_type_uid
|
|
193
|
+
}
|
|
194
|
+
if (onlyEntries) {
|
|
195
|
+
filter.type = 'entry_published'
|
|
196
|
+
}
|
|
197
|
+
setConfig(config, bulkUnpublish)
|
|
198
|
+
const queryParams = getQueryParams(filter)
|
|
199
|
+
await getSyncEntries(stack, config, locale, queryParams, bulkUnpublish, environment, deliveryToken)
|
|
207
200
|
}
|
|
208
201
|
}
|
|
209
202
|
|
|
@@ -214,4 +207,4 @@ module.exports = {
|
|
|
214
207
|
setConfig,
|
|
215
208
|
getQueryParams,
|
|
216
209
|
start,
|
|
217
|
-
}
|
|
210
|
+
}
|
package/src/util/client.js
CHANGED
|
@@ -3,21 +3,26 @@ const {Command} = require('@contentstack/cli-command')
|
|
|
3
3
|
const command = new Command()
|
|
4
4
|
|
|
5
5
|
const Configstore = require('configstore')
|
|
6
|
+
// eslint-disable-next-line no-unused-vars
|
|
6
7
|
const config = new Configstore('contentstack_cli')
|
|
7
|
-
const {
|
|
8
|
+
const {formatHostname} = require('../util')
|
|
8
9
|
|
|
9
10
|
function getStack(data) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
const tokenDetails = command.getToken(data.alias)
|
|
12
|
+
const client = contentstackSdk.client({
|
|
13
|
+
headers: {
|
|
14
|
+
branch: data.branch,
|
|
15
|
+
},
|
|
16
|
+
host: formatHostname(data.host),
|
|
17
|
+
// eslint-disable-next-line no-unused-vars
|
|
18
|
+
logHandler: level => {},
|
|
19
|
+
})
|
|
20
|
+
const stack = client.stack({api_key: tokenDetails.apiKey, management_token: tokenDetails.token})
|
|
21
|
+
stack.alias = data.alias
|
|
22
|
+
stack.host = data.host
|
|
23
|
+
return stack
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
module.exports = {
|
|
22
|
-
getStack
|
|
27
|
+
getStack,
|
|
23
28
|
}
|
package/src/util/queue.js
CHANGED
package/src/util/request.js
CHANGED
|
@@ -26,21 +26,23 @@ var makeCall = module.exports = function (req, RETRY) {
|
|
|
26
26
|
let timeDelay
|
|
27
27
|
if (response.statusCode >= 200 && response.statusCode <= 399) {
|
|
28
28
|
return resolve(JSON.parse(response.body))
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
|
+
if (response.statusCode === 429) {
|
|
30
31
|
// eslint-disable-next-line no-mixed-operators
|
|
31
32
|
timeDelay = Math.SQRT2 ** RETRY * 100
|
|
32
33
|
debug(`API rate limit exceeded.\nReceived ${response.statusCode} status\nBody ${JSON.stringify(response)}`)
|
|
33
34
|
debug(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`)
|
|
34
|
-
return setTimeout((
|
|
35
|
+
return setTimeout((req1, RETRY1) => makeCall(req1, RETRY1)
|
|
35
36
|
.then(resolve)
|
|
36
37
|
.catch(reject), timeDelay, req, RETRY)
|
|
37
|
-
}
|
|
38
|
+
}
|
|
39
|
+
if (response.statusCode >= 500) {
|
|
38
40
|
// retry, with delay
|
|
39
41
|
timeDelay = Math.SQRT2 ** RETRY * 100
|
|
40
42
|
debug(`Recevied ${response.statusCode} status\nBody ${JSON.stringify(response)}`)
|
|
41
43
|
debug(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`)
|
|
42
44
|
RETRY++
|
|
43
|
-
return setTimeout((
|
|
45
|
+
return setTimeout((req2, RETRY2) => makeCall(req2, RETRY2)
|
|
44
46
|
.then(resolve)
|
|
45
47
|
.catch(reject), timeDelay, req, RETRY)
|
|
46
48
|
}
|
package/src/util/store.js
CHANGED
|
@@ -52,11 +52,7 @@ function get(key, filePath) {
|
|
|
52
52
|
|
|
53
53
|
function updateMissing(key, flags) {
|
|
54
54
|
let savedConfig
|
|
55
|
-
|
|
56
|
-
savedConfig = get(key, path.resolve(flags.config))
|
|
57
|
-
} catch(error) {
|
|
58
|
-
throw error
|
|
59
|
-
}
|
|
55
|
+
savedConfig = get(key, path.resolve(flags.config))
|
|
60
56
|
Object.keys(savedConfig).forEach(element => {
|
|
61
57
|
if (flags[element] === undefined) {
|
|
62
58
|
console.log(`Using ${element} from config file`)
|
|
@@ -74,13 +70,13 @@ function updateMissing(key, flags) {
|
|
|
74
70
|
// because both unpublish and cross-publish commands build the filter object
|
|
75
71
|
// internally, and in the original bulk-publish script the filter object was
|
|
76
72
|
// mentioned in the config file itself
|
|
77
|
-
function handleFilterObj(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
delete
|
|
83
|
-
return
|
|
73
|
+
function handleFilterObj(config1) {
|
|
74
|
+
config1.environment = config1.filter.environment
|
|
75
|
+
config1.contentType = config1.filter.content_type_uid
|
|
76
|
+
config1.locale = config1.filter.locale
|
|
77
|
+
config1.f_types = config1.filter.type // adding f_types to differentiate the types specified in the config.js, and the types defined internally in Unpublish and Cross Publish
|
|
78
|
+
delete config1.filter
|
|
79
|
+
return config1
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
module.exports = {
|