@contentstack/cli 0.1.1-beta.9 → 1.0.0
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/LICENSE +21 -0
- package/README.md +1145 -652
- package/bin/run +1 -4
- package/lib/config/index.js +9 -0
- package/lib/help.js +38 -0
- package/lib/hooks/init/context-init.js +10 -0
- package/lib/hooks/init/utils-init.js +12 -0
- package/lib/hooks/prerun/auth-guard.js +40 -0
- package/lib/hooks/prerun/command-deprecation-check.js +10 -0
- package/lib/index.js +3 -0
- package/lib/interfaces/index.js +2 -0
- package/lib/utils/context-handler.js +39 -0
- package/lib/utils/index.js +5 -0
- package/oclif.manifest.json +1 -1
- package/package.json +97 -64
- package/src/commands/config/get/region.js +0 -17
- package/src/commands/config/set/region.js +0 -70
- package/src/help.js +0 -20
- package/src/hooks/init.js +0 -21
- package/src/hooks/prerun/analytics.js +0 -40
- package/src/hooks/prerun/print-region.js +0 -11
- package/src/hooks/validate-auth-token.js +0 -7
- package/src/hooks/validate-management-token.js +0 -19
- package/src/index.js +0 -1
- package/src/util/analytics.js +0 -61
- package/src/util/contentstack-client.js +0 -17
- package/src/util/custom-errors.js +0 -7
- package/src/util/request.js +0 -71
- package/src/util/user-config.js +0 -128
package/src/util/analytics.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
const axios = require('axios')
|
|
2
|
-
const debug = require('debug')('contentstack:analytics')
|
|
3
|
-
const querystring = require('querystring')
|
|
4
|
-
|
|
5
|
-
const VERSION = 1
|
|
6
|
-
/**
|
|
7
|
-
* Using Google Analytics Measurement Protocol to track usage by users.
|
|
8
|
-
* The Google Analytics Measurement Protocol allows developers to make HTTP
|
|
9
|
-
* requests to send raw user interaction data directly to Google Analytics servers.
|
|
10
|
-
* This allows developers to measure how users interact with their business from almost
|
|
11
|
-
* any environment.
|
|
12
|
-
* See more about google analytics Measurement Protocol here: https://developers.google.com/analytics/devguides/collection/protocol/v1
|
|
13
|
-
*/
|
|
14
|
-
const GOOGLE_ANALYTICS_MEASUREMENT_PROTOCOL_URL = 'http://www.google-analytics.com/collect'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Represents analytics for CLI
|
|
18
|
-
*/
|
|
19
|
-
class Analytics {
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
* This sets settings object required to track information with Google Analytics measurement protocol
|
|
23
|
-
* @param {Object} options JSON object with trackingID(String) and cid(string) keys, trackingID is google analytics tracking code and cid is UUID to represent unique user to google analytics.
|
|
24
|
-
*/
|
|
25
|
-
constructor(options) {
|
|
26
|
-
this.settings = {
|
|
27
|
-
v: VERSION,
|
|
28
|
-
tid: options.trackingID,
|
|
29
|
-
cid: options.cid,
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
*
|
|
35
|
-
* e.g data sent to google analytics Measurement protocol will look like
|
|
36
|
-
* {
|
|
37
|
-
* t: 'event',
|
|
38
|
-
* ec: '@contentstack/contentstack-import',
|
|
39
|
-
* ea: 'cm:import',
|
|
40
|
-
* el: '0.1.0',
|
|
41
|
-
* cd1: '@contentstack/cli/0.0.0 linux-x64 node-v12.13.1',
|
|
42
|
-
* }
|
|
43
|
-
* @param {string} action Command ran by user.
|
|
44
|
-
* @param {object} analyticsOpts Contains label and os key, label represents plugin version and os represents machine details as user-agent.
|
|
45
|
-
* @returns {promises} Contains response from http client.
|
|
46
|
-
*/
|
|
47
|
-
track(action, analyticsOpts) {
|
|
48
|
-
let data = {
|
|
49
|
-
t: 'event',
|
|
50
|
-
ec: analyticsOpts.category,
|
|
51
|
-
ea: action,
|
|
52
|
-
el: analyticsOpts.label,
|
|
53
|
-
cd1: analyticsOpts.os,
|
|
54
|
-
}
|
|
55
|
-
let opts = Object.assign(this.settings, data)
|
|
56
|
-
debug('Sending event to analytics for', querystring.stringify(opts))
|
|
57
|
-
return axios.post(GOOGLE_ANALYTICS_MEASUREMENT_PROTOCOL_URL, querystring.stringify(opts))
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = Analytics
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line node/no-unpublished-require
|
|
2
|
-
const ContentstackMgmntSDK = require('@contentstack/management')
|
|
3
|
-
// const host = 'https://api.contentstack.io'
|
|
4
|
-
const axios = require('axios')
|
|
5
|
-
|
|
6
|
-
class ContentstackClient {
|
|
7
|
-
constructor(host) {
|
|
8
|
-
if (this.instance) {
|
|
9
|
-
return this.instance
|
|
10
|
-
}
|
|
11
|
-
if (host.includes('https://'))
|
|
12
|
-
host = host.replace('https://', '')
|
|
13
|
-
this.instance = ContentstackMgmntSDK.client({host})
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = ContentstackClient
|
package/src/util/request.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
var Bluebird = require('bluebird')
|
|
2
|
-
var request = Bluebird.promisify(require('request'))
|
|
3
|
-
var debug = require('debug')('util:requests')
|
|
4
|
-
var MAX_RETRY_LIMIT = 5
|
|
5
|
-
|
|
6
|
-
function validate(req) {
|
|
7
|
-
if (typeof req !== 'object') {
|
|
8
|
-
throw new TypeError(`Invalid params passed for request\n${JSON.stringify(arguments)}`)
|
|
9
|
-
}
|
|
10
|
-
if (typeof req.uri === 'undefined' && typeof req.url === 'undefined') {
|
|
11
|
-
throw new TypeError(`Missing uri in request!\n${JSON.stringify(req)}`)
|
|
12
|
-
}
|
|
13
|
-
if (typeof req.method === 'undefined') {
|
|
14
|
-
debug(`${req.uri || req.url} had no method, setting it as 'GET'`)
|
|
15
|
-
req.method = 'GET'
|
|
16
|
-
}
|
|
17
|
-
if (typeof req.json === 'undefined') {
|
|
18
|
-
req.json = true
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
var makeCall = function (req, RETRY) {
|
|
23
|
-
return new Bluebird(function (resolve, reject) {
|
|
24
|
-
try {
|
|
25
|
-
validate(req)
|
|
26
|
-
if (typeof RETRY !== 'number') {
|
|
27
|
-
RETRY = 1
|
|
28
|
-
} else if (RETRY > MAX_RETRY_LIMIT) {
|
|
29
|
-
return reject(new Error('Max retry limit exceeded!'))
|
|
30
|
-
}
|
|
31
|
-
debug(`${req.method.toUpperCase()}: ${req.uri || req.url}`)
|
|
32
|
-
return request(req).then(function (response) {
|
|
33
|
-
var timeDelay
|
|
34
|
-
if (response.statusCode >= 200 && response.statusCode <= 399) {
|
|
35
|
-
return resolve(response)
|
|
36
|
-
}
|
|
37
|
-
if (response.statusCode === 429) {
|
|
38
|
-
// eslint-disable-next-line unicorn/prefer-exponentiation-operator
|
|
39
|
-
timeDelay = Math.pow(Math.SQRT2, RETRY) * 100
|
|
40
|
-
debug(`API rate limit exceeded.\nReceived ${response.statusCode} status\nBody ${JSON.stringify(response)}`)
|
|
41
|
-
debug(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`)
|
|
42
|
-
return setTimeout(function (req, RETRY) {
|
|
43
|
-
return makeCall(req, RETRY)
|
|
44
|
-
.then(resolve)
|
|
45
|
-
.catch(reject)
|
|
46
|
-
}, timeDelay, req, RETRY)
|
|
47
|
-
}
|
|
48
|
-
if (response.statusCode >= 500) {
|
|
49
|
-
// retry, with delay
|
|
50
|
-
// eslint-disable-next-line unicorn/prefer-exponentiation-operator
|
|
51
|
-
timeDelay = Math.pow(Math.SQRT2, RETRY) * 100
|
|
52
|
-
debug(`Received ${response.statusCode} status\nBody ${JSON.stringify(response)}`)
|
|
53
|
-
debug(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`)
|
|
54
|
-
RETRY++
|
|
55
|
-
return setTimeout(function (req, RETRY) {
|
|
56
|
-
return makeCall(req, RETRY)
|
|
57
|
-
.then(resolve)
|
|
58
|
-
.catch(reject)
|
|
59
|
-
}, timeDelay, req, RETRY)
|
|
60
|
-
}
|
|
61
|
-
debug(`Request failed\n${JSON.stringify(req)}`)
|
|
62
|
-
return reject(response.body)
|
|
63
|
-
}).catch(reject)
|
|
64
|
-
} catch (error) {
|
|
65
|
-
debug(error)
|
|
66
|
-
return reject(error)
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
module.exports = makeCall
|
package/src/util/user-config.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
const {v4: uuidv4} = require('uuid')
|
|
2
|
-
const lodash = require('lodash')
|
|
3
|
-
const {cli} = require('cli-ux')
|
|
4
|
-
const Configstore = require('configstore')
|
|
5
|
-
const config = new Configstore('contentstack_cli')
|
|
6
|
-
const debug = require('debug')('contentstack:analytics')
|
|
7
|
-
const {TokenNotFound, NotLoggedIn} = require('./custom-errors')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate or return an RFC version 4 (random) UUID
|
|
11
|
-
* If UUID already stored in config it will return that
|
|
12
|
-
* Mainly used to maintain uniqueness in Analytics
|
|
13
|
-
* @returns {string} a version 4 UUID
|
|
14
|
-
*/
|
|
15
|
-
module.exports.getUUID = function () {
|
|
16
|
-
try {
|
|
17
|
-
let uuid = config.get('uuid')
|
|
18
|
-
debug('this is uuid', uuid)
|
|
19
|
-
if (!uuid) {
|
|
20
|
-
uuid = config.set('uuid', uuidv4())
|
|
21
|
-
}
|
|
22
|
-
return uuid
|
|
23
|
-
} catch (error) {
|
|
24
|
-
cli.log('Failed to generate/get UUID')
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function validURL(str) {
|
|
29
|
-
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
|
30
|
-
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
|
31
|
-
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
|
32
|
-
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
|
33
|
-
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
|
34
|
-
'(\\#[-a-z\\d_]*)?$', 'i') // fragment locator
|
|
35
|
-
return Boolean(pattern.test(str))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Available region list
|
|
39
|
-
const regions = {
|
|
40
|
-
NA: {cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', name: 'NA'},
|
|
41
|
-
EU: {cma: 'https://eu-api.contentstack.com', cda: 'https://eu-cdn.contentstack.com', name: 'EU'},
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
class UserConfig {
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* Set region to config store
|
|
48
|
-
* @param {string} region It Can be NA, EU
|
|
49
|
-
* @returns {object} region object with cma, cda, region property
|
|
50
|
-
*/
|
|
51
|
-
setRegion(region) {
|
|
52
|
-
let selectedRegion = regions[region]
|
|
53
|
-
if (selectedRegion) {
|
|
54
|
-
config.set('region', selectedRegion)
|
|
55
|
-
return selectedRegion
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
* Get current host set for CLI
|
|
62
|
-
* @returns { object } Object contains url for cma and cda, and region to which it is pointing to
|
|
63
|
-
*/
|
|
64
|
-
getRegion() {
|
|
65
|
-
const regionDetails = config.get('region')
|
|
66
|
-
if (regionDetails)
|
|
67
|
-
return regionDetails
|
|
68
|
-
|
|
69
|
-
// returns NA region if not found in config
|
|
70
|
-
return regions.NA
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
* Set region to config store
|
|
76
|
-
* @param {object} regionObject should contain cma, cda, region property
|
|
77
|
-
* @returns {object} region object with cma, cda, region(name of region) property
|
|
78
|
-
*/
|
|
79
|
-
setCustomRegion(regionObject) {
|
|
80
|
-
if (this.validateRegion(regionObject)) {
|
|
81
|
-
regionObject = this.sanitizeRegionObject(regionObject)
|
|
82
|
-
config.set('region', regionObject)
|
|
83
|
-
return regionObject
|
|
84
|
-
}
|
|
85
|
-
throw new TypeError('Custom region should include valid cma(URL), cda(URL), name(String) (Name for the Region) property.')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
*
|
|
90
|
-
* Set rateLimit to config store
|
|
91
|
-
* @param {object} rateLimitObject should contain rate limit property
|
|
92
|
-
* @returns {object} ratelimit object with limit property
|
|
93
|
-
*/
|
|
94
|
-
// setCustomRateLimit(rateLimitObject) {
|
|
95
|
-
// if(rateLimitObject !== undefined && isNaN(rateLimitObject)) {
|
|
96
|
-
// throw new TypeError(rateLimitObject + " is not a number, Please provide number as a rate limit")
|
|
97
|
-
// } else {
|
|
98
|
-
// config.set('rate-limit', rateLimitObject)
|
|
99
|
-
// return rateLimitObject
|
|
100
|
-
// }
|
|
101
|
-
// }
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Validate given region JSON object
|
|
105
|
-
* @param {*} regionObject JSON object needs to be validated
|
|
106
|
-
* @returns {boolean} True if contains cma, cda and region property otherwise false
|
|
107
|
-
*/
|
|
108
|
-
validateRegion(regionObject) {
|
|
109
|
-
if (regionObject.cma && regionObject.cda && regionObject.name) {
|
|
110
|
-
if (validURL(regionObject.cma) && validURL(regionObject.cda))
|
|
111
|
-
return true
|
|
112
|
-
}
|
|
113
|
-
return false
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Sanitize given region JSON object by removing any other properties than cma, cda and region
|
|
118
|
-
* @param { object } regionObject JSON object needs to be sanitized
|
|
119
|
-
* @returns { object } JSON object with only valid keys for region
|
|
120
|
-
*/
|
|
121
|
-
sanitizeRegionObject(regionObject) {
|
|
122
|
-
let sanitizedRegion
|
|
123
|
-
sanitizedRegion = lodash.pick(regionObject, ['cma', 'cda', 'name'])
|
|
124
|
-
return sanitizedRegion
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
module.exports.UserConfig = UserConfig
|