adapt-cli 3.0.6 → 3.0.8
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/lib/api.js +25 -12
- package/lib/cli.js +1 -0
- package/lib/commands/ls.js +28 -2
- package/lib/econnreset.js +7 -0
- package/lib/integration/AdaptFramework/getLatestVersion.js +9 -14
- package/lib/integration/PluginManagement/autenticate.js +8 -17
- package/lib/integration/PluginManagement/install.js +1 -1
- package/lib/integration/PluginManagement/rename.js +6 -12
- package/lib/integration/PluginManagement/search.js +7 -16
- package/lib/integration/PluginManagement/unregister.js +6 -16
- package/lib/util/download.js +2 -2
- package/lib/util/extract.js +2 -2
- package/package.json +3 -3
package/lib/api.js
CHANGED
@@ -19,6 +19,7 @@ import Plugin from './integration/Plugin.js'
|
|
19
19
|
import Project from './integration/Project.js'
|
20
20
|
import fs from 'fs-extra'
|
21
21
|
import async from 'async'
|
22
|
+
import './econnreset.js'
|
22
23
|
|
23
24
|
// TODO: api, check no interactivity, should be sorted, will fail silently if it absolutely cannot do what you've asked
|
24
25
|
// TODO: api, console and error output, error on fail when isInteractive: false? or something else? return Targets?
|
@@ -36,17 +37,20 @@ class API {
|
|
36
37
|
async installFramework ({
|
37
38
|
version = null,
|
38
39
|
repository = ADAPT_FRAMEWORK,
|
39
|
-
cwd = process.cwd()
|
40
|
+
cwd = process.cwd(),
|
41
|
+
logger
|
40
42
|
} = {}) {
|
41
43
|
if (!version) version = await getLatestVersion({ repository })
|
42
44
|
await erase({
|
43
45
|
isInteractive: false,
|
44
|
-
cwd
|
46
|
+
cwd,
|
47
|
+
logger
|
45
48
|
})
|
46
49
|
await download({
|
47
50
|
repository,
|
48
51
|
branch: version,
|
49
|
-
cwd
|
52
|
+
cwd,
|
53
|
+
logger
|
50
54
|
})
|
51
55
|
await deleteSrcCourse({
|
52
56
|
cwd
|
@@ -55,7 +59,8 @@ class API {
|
|
55
59
|
cwd
|
56
60
|
})
|
57
61
|
await npmInstall({
|
58
|
-
cwd
|
62
|
+
cwd,
|
63
|
+
logger
|
59
64
|
})
|
60
65
|
}
|
61
66
|
|
@@ -87,7 +92,8 @@ class API {
|
|
87
92
|
cache = true,
|
88
93
|
outputDir = null,
|
89
94
|
cachePath = './build/.cache',
|
90
|
-
cwd = process.cwd()
|
95
|
+
cwd = process.cwd(),
|
96
|
+
logger
|
91
97
|
} = {}) {
|
92
98
|
await build({
|
93
99
|
sourceMaps,
|
@@ -95,7 +101,8 @@ class API {
|
|
95
101
|
cache,
|
96
102
|
cwd,
|
97
103
|
outputDir,
|
98
|
-
cachePath
|
104
|
+
cachePath,
|
105
|
+
logger
|
99
106
|
})
|
100
107
|
}
|
101
108
|
|
@@ -109,12 +116,14 @@ class API {
|
|
109
116
|
*/
|
110
117
|
async installPlugins ({
|
111
118
|
plugins = null,
|
112
|
-
cwd = process.cwd()
|
119
|
+
cwd = process.cwd(),
|
120
|
+
logger
|
113
121
|
} = {}) {
|
114
122
|
return await install({
|
115
123
|
plugins,
|
116
124
|
isInteractive: false,
|
117
|
-
cwd
|
125
|
+
cwd,
|
126
|
+
logger
|
118
127
|
})
|
119
128
|
}
|
120
129
|
|
@@ -127,12 +136,14 @@ class API {
|
|
127
136
|
*/
|
128
137
|
async uninstallPlugins ({
|
129
138
|
plugins = null,
|
130
|
-
cwd = process.cwd()
|
139
|
+
cwd = process.cwd(),
|
140
|
+
logger
|
131
141
|
} = {}) {
|
132
142
|
return await uninstall({
|
133
143
|
plugins,
|
134
144
|
isInteractive: false,
|
135
|
-
cwd
|
145
|
+
cwd,
|
146
|
+
logger
|
136
147
|
})
|
137
148
|
}
|
138
149
|
|
@@ -146,12 +157,14 @@ class API {
|
|
146
157
|
*/
|
147
158
|
async updatePlugins ({
|
148
159
|
plugins = null,
|
149
|
-
cwd = process.cwd()
|
160
|
+
cwd = process.cwd(),
|
161
|
+
logger
|
150
162
|
} = {}) {
|
151
163
|
return await update({
|
152
164
|
plugins,
|
153
165
|
isInteractive: false,
|
154
|
-
cwd
|
166
|
+
cwd,
|
167
|
+
logger
|
155
168
|
})
|
156
169
|
}
|
157
170
|
|
package/lib/cli.js
CHANGED
package/lib/commands/ls.js
CHANGED
@@ -1,9 +1,35 @@
|
|
1
1
|
import chalk from 'chalk'
|
2
|
+
import _ from 'lodash'
|
2
3
|
import Project from '../integration/Project.js'
|
4
|
+
import { eachOfLimitProgress } from '../util/promises.js'
|
3
5
|
|
4
6
|
export default async function ls (logger) {
|
5
7
|
const project = new Project({ logger })
|
8
|
+
const frameworkVersion = project.version
|
6
9
|
project.tryThrowInvalidPath()
|
7
|
-
const installTargets = await project.getInstallTargets()
|
8
|
-
installTargets.
|
10
|
+
const installTargets = (await project.getInstallTargets())
|
11
|
+
const installTargetsIndex = installTargets.reduce((hash, p) => {
|
12
|
+
const name = (p.name || p.sourcePath)
|
13
|
+
hash[name] = p
|
14
|
+
return hash
|
15
|
+
}, {})
|
16
|
+
const installedPlugins = await project.getInstalledPlugins();
|
17
|
+
const notInstalled = _.difference(installTargets.map(p => (p.name || p.sourcePath)), installedPlugins.map(p => (p.name || p.sourcePath)))
|
18
|
+
const plugins = installedPlugins.concat(notInstalled.map(name => installTargetsIndex[name]))
|
19
|
+
await eachOfLimitProgress(
|
20
|
+
plugins,
|
21
|
+
async (target) => {
|
22
|
+
await target.fetchProjectInfo()
|
23
|
+
await target.fetchSourceInfo()
|
24
|
+
await target.findCompatibleVersion(frameworkVersion)
|
25
|
+
},
|
26
|
+
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Getting plugin info ${percentage}% complete`)
|
27
|
+
)
|
28
|
+
logger?.log(`${chalk.bold.cyan('<info>')} Getting plugin info 100% complete`)
|
29
|
+
plugins
|
30
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
31
|
+
.forEach(p => {
|
32
|
+
const name = (p.name || p.sourcePath)
|
33
|
+
logger?.log(`${chalk.cyan(p.name || p.sourcePath)} ${chalk.green('adapt.json')}: ${installTargetsIndex[name]?.requestedVersion || 'n/a'} ${chalk.green('installed')}: ${p.sourcePath || p.projectVersion || 'n/a'} ${chalk.green('latest')}: ${p.sourcePath || p.latestCompatibleSourceVersion || 'n/a'}`)
|
34
|
+
})
|
9
35
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
// guard against ECONNRESET issues https://github.com/adaptlearning/adapt-cli/issues/169
|
2
|
+
process.on('uncaughtException', (error, origin) => {
|
3
|
+
if (error?.code === 'ECONNRESET') return
|
4
|
+
console.error('UNCAUGHT EXCEPTION')
|
5
|
+
console.error(error)
|
6
|
+
console.error(origin)
|
7
|
+
})
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import fetch from 'node-fetch'
|
2
2
|
import semver from 'semver'
|
3
3
|
import gh from 'parse-github-url'
|
4
4
|
import { ADAPT_DEFAULT_USER_AGENT, ADAPT_FRAMEWORK, ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js'
|
@@ -29,24 +29,19 @@ export default async function getLatestVersion ({ versionLimit, repository = ADA
|
|
29
29
|
return links
|
30
30
|
}
|
31
31
|
const processPage = async () => {
|
32
|
-
const
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
uri: nextPage,
|
38
|
-
method: 'GET'
|
39
|
-
}, (error, response, body) => {
|
40
|
-
if (error) return reject(error)
|
41
|
-
resolve([response, body])
|
42
|
-
})
|
32
|
+
const response = await fetch(nextPage, {
|
33
|
+
headers: {
|
34
|
+
'User-Agent': ADAPT_DEFAULT_USER_AGENT
|
35
|
+
},
|
36
|
+
method: 'GET'
|
43
37
|
})
|
44
|
-
|
38
|
+
const body = await response.text()
|
39
|
+
if (response?.status === 403 && response?.headers['x-ratelimit-remaining'] === '0') {
|
45
40
|
// we've exceeded the API limit
|
46
41
|
const reqsReset = new Date(response.headers['x-ratelimit-reset'] * 1000)
|
47
42
|
throw new Error(`Couldn't check latest version of ${NAME}. You have exceeded GitHub's request limit of ${response.headers['x-ratelimit-limit']} requests per hour. Please wait until at least ${reqsReset.toTimeString()} before trying again.`)
|
48
43
|
}
|
49
|
-
if (response?.
|
44
|
+
if (response?.status !== 200) {
|
50
45
|
throw new Error(`Couldn't check latest version of ${NAME}. GitubAPI did not respond with a 200 status code.`)
|
51
46
|
}
|
52
47
|
nextPage = parseLinkHeader(response.headers.link).next
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import chalk from 'chalk'
|
2
2
|
import inquirer from 'inquirer'
|
3
|
-
import
|
3
|
+
import fetch from 'node-fetch'
|
4
4
|
import getBowerRegistryConfig from '../getBowerRegistryConfig.js'
|
5
5
|
import path from 'path'
|
6
6
|
|
@@ -36,21 +36,12 @@ export default async function authenticate ({
|
|
36
36
|
({ pluginName } = confirmation)
|
37
37
|
}
|
38
38
|
const { username, token } = confirmation
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
headers: { 'User-Agent': 'adapt-cli' },
|
44
|
-
followRedirect: false
|
45
|
-
}, (err, res, body) => {
|
46
|
-
if (err) return reject(err)
|
47
|
-
if (res.statusCode !== 200) reject(new Error(`The server responded with ${res.statusCode}`))
|
48
|
-
try {
|
49
|
-
const bodyJSON = JSON.parse(body)
|
50
|
-
resolve({ username, token, pluginName, ...bodyJSON })
|
51
|
-
} catch (err) {
|
52
|
-
reject(err)
|
53
|
-
}
|
54
|
-
})
|
39
|
+
const response = await fetch(`${BOWER_REGISTRY_CONFIG.register}authenticate/${username}/${pluginName}?access_token=${token}`, {
|
40
|
+
headers: { 'User-Agent': 'adapt-cli' },
|
41
|
+
followRedirect: false,
|
42
|
+
method: 'GET'
|
55
43
|
})
|
44
|
+
if (response.status !== 200) throw new Error(`The server responded with ${response.status}`)
|
45
|
+
const body = await response.json()
|
46
|
+
return { username, token, pluginName, ...body }
|
56
47
|
}
|
@@ -131,7 +131,7 @@ async function conflictResolution ({ logger, targets, isInteractive, dev }) {
|
|
131
131
|
? { name: `latest compatible version [${target.latestCompatibleSourceVersion}]`, value: 'l' }
|
132
132
|
: target.latestSourceVersion
|
133
133
|
? { name: `latest version [${target.latestSourceVersion}]`, value: 'l' }
|
134
|
-
: { name:
|
134
|
+
: { name: 'master [master]', value: 'm' },
|
135
135
|
{ name: 'skip', value: 's' }
|
136
136
|
].filter(Boolean)
|
137
137
|
const result = await createPromptTask({ message: chalk.reset(target.packageName), choices, type: 'list', default: 's' })
|
@@ -3,7 +3,7 @@ import authenticate from './autenticate.js'
|
|
3
3
|
import bower from 'bower'
|
4
4
|
import chalk from 'chalk'
|
5
5
|
import inquirer from 'inquirer'
|
6
|
-
import
|
6
|
+
import fetch from 'node-fetch'
|
7
7
|
import path from 'path'
|
8
8
|
import Plugin from '../Plugin.js'
|
9
9
|
|
@@ -68,18 +68,12 @@ async function renameInBowerRepo ({
|
|
68
68
|
}) {
|
69
69
|
const path = 'packages/rename/' + username + '/' + oldName + '/' + newName
|
70
70
|
const query = '?access_token=' + token
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
headers: { 'User-Agent': 'adapt-cli' },
|
76
|
-
followRedirect: false
|
77
|
-
}, (err, res) => {
|
78
|
-
if (err) return reject(err)
|
79
|
-
if (res.statusCode !== 201) reject(new Error(`The server responded with ${res.statusCode}`))
|
80
|
-
resolve()
|
81
|
-
})
|
71
|
+
const response = await fetch(BOWER_REGISTRY_CONFIG.register + path + query, {
|
72
|
+
method: 'GET',
|
73
|
+
headers: { 'User-Agent': 'adapt-cli' },
|
74
|
+
followRedirect: false
|
82
75
|
})
|
76
|
+
if (response.status !== 201) throw new Error(`The server responded with ${response.status}`)
|
83
77
|
}
|
84
78
|
|
85
79
|
/**
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import getBowerRegistryConfig from '../getBowerRegistryConfig.js'
|
2
2
|
import chalk from 'chalk'
|
3
|
-
import
|
3
|
+
import fetch from 'node-fetch'
|
4
4
|
import path from 'path'
|
5
5
|
|
6
6
|
export default async function search ({
|
@@ -14,22 +14,13 @@ export default async function search ({
|
|
14
14
|
const uniqueResults = {}
|
15
15
|
for (const serverURI of BOWER_REGISTRY_CONFIG.search) {
|
16
16
|
try {
|
17
|
-
const
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
headers: { 'User-Agent': 'adapt-cli' },
|
22
|
-
followRedirect: false
|
23
|
-
}, (err, res, body) => {
|
24
|
-
if (err) return reject(err)
|
25
|
-
if (res.statusCode !== 200) reject(new Error(`The server responded with ${res.statusCode}`))
|
26
|
-
try {
|
27
|
-
resolve(JSON.parse(body))
|
28
|
-
} catch (err) {
|
29
|
-
reject(err)
|
30
|
-
}
|
31
|
-
})
|
17
|
+
const response = await fetch(`${serverURI}packages/search/${searchTerm}`, {
|
18
|
+
method: 'GET',
|
19
|
+
headers: { 'User-Agent': 'adapt-cli' },
|
20
|
+
followRedirect: false
|
32
21
|
})
|
22
|
+
if (response.status !== 200) throw new Error(`The server responded with ${response.status}`)
|
23
|
+
const immediateResults = await response.json()
|
33
24
|
immediateResults?.forEach(result => (uniqueResults[result.name] = uniqueResults[result.name] ?? result))
|
34
25
|
} catch (err) {}
|
35
26
|
}
|
@@ -6,7 +6,7 @@ import chalk from 'chalk'
|
|
6
6
|
import inquirer from 'inquirer'
|
7
7
|
import { readValidateJSON } from '../../util/JSONReadValidate.js'
|
8
8
|
import Plugin from '../Plugin.js'
|
9
|
-
import
|
9
|
+
import fetch from 'node-fetch'
|
10
10
|
|
11
11
|
export default async function unregister ({
|
12
12
|
logger,
|
@@ -82,20 +82,10 @@ async function unregisterInBowerRepo ({
|
|
82
82
|
BOWER_REGISTRY_CONFIG
|
83
83
|
}) {
|
84
84
|
const uri = `${BOWER_REGISTRY_CONFIG.register}packages/${username}/${pluginName}?access_token=${token}`
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
headers: { 'User-Agent': 'adapt-cli' },
|
90
|
-
followRedirect: false
|
91
|
-
}, (err, res, body) => {
|
92
|
-
if (err) return reject(err)
|
93
|
-
if (res.statusCode !== 204) reject(new Error(`The server responded with ${res.statusCode}`))
|
94
|
-
try {
|
95
|
-
resolve()
|
96
|
-
} catch (err) {
|
97
|
-
reject(err)
|
98
|
-
}
|
99
|
-
})
|
85
|
+
const response = await fetch(uri, {
|
86
|
+
method: 'DELETE',
|
87
|
+
headers: { 'User-Agent': 'adapt-cli' },
|
88
|
+
followRedirect: false
|
100
89
|
})
|
90
|
+
if (response.status !== 204) throw new Error(`The server responded with ${response.status}`)
|
101
91
|
}
|
package/lib/util/download.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import chalk from 'chalk'
|
2
|
-
import uuid from 'uuid'
|
2
|
+
import { v4 as uuid } from 'uuid'
|
3
3
|
import fs from 'fs-extra'
|
4
4
|
import path from 'path'
|
5
5
|
import urljoin from 'url-join'
|
@@ -17,7 +17,7 @@ export default async function download ({
|
|
17
17
|
if (!branch && !repository) throw new Error('Repository details are required.')
|
18
18
|
const repositoryName = gh(repository).name
|
19
19
|
logger?.write(chalk.cyan(`downloading ${repositoryName} to ${cwd}\t`))
|
20
|
-
tmp = (tmp || path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid
|
20
|
+
tmp = (tmp || path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid()))
|
21
21
|
const downloadFileName = await new Promise((resolve, reject) => {
|
22
22
|
let downloadFileName = ''
|
23
23
|
const url = urljoin(repository, 'archive', branch + '.zip')
|
package/lib/util/extract.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import uuid from 'uuid'
|
1
|
+
import { v4 as uuid } from 'uuid'
|
2
2
|
import path from 'path'
|
3
3
|
import decompress from 'decompress'
|
4
4
|
import { HOME_DIRECTORY } from './constants.js'
|
@@ -7,7 +7,7 @@ export default async function extract ({
|
|
7
7
|
sourcePath,
|
8
8
|
cwd
|
9
9
|
} = {}) {
|
10
|
-
const rootPath = path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid
|
10
|
+
const rootPath = path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid()).replace(/\\/g, '/')
|
11
11
|
const files = await decompress(path.join(cwd, sourcePath), rootPath, {
|
12
12
|
filter: file => !file.path.endsWith('/')
|
13
13
|
})
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "adapt-cli",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.8",
|
4
4
|
"description": "Command line tools for Adapt",
|
5
5
|
"main": "./lib/api.js",
|
6
6
|
"type": "module",
|
@@ -17,12 +17,12 @@
|
|
17
17
|
"inquirer": "^7.3.3",
|
18
18
|
"json-lint": "^0.1.0",
|
19
19
|
"lodash-es": "^4.17.21",
|
20
|
+
"node-fetch": "^3.2.10",
|
20
21
|
"parse-github-url": "^1.0.2",
|
21
|
-
"request": "^2.88.0",
|
22
22
|
"semver": "^7.3.5",
|
23
23
|
"speakingurl": "^14.0.1",
|
24
24
|
"url-join": "^4.0.0",
|
25
|
-
"uuid": "^
|
25
|
+
"uuid": "^8.3.2"
|
26
26
|
},
|
27
27
|
"license": "GPL-3.0",
|
28
28
|
"preferGlobal": true,
|