adapt-cli 3.0.2 → 3.0.6

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.
Files changed (78) hide show
  1. package/.bowerrc +2 -2
  2. package/.eslintignore +1 -1
  3. package/.eslintrc.json +14 -14
  4. package/.github/CONTRIBUTING.md +8 -0
  5. package/.github/ISSUE_TEMPLATE.md +17 -0
  6. package/.github/pull_request_template.md +25 -0
  7. package/.github/workflows/addtomainproject.yml +19 -0
  8. package/.github/workflows/releases.yml +25 -0
  9. package/.travis.yml +46 -46
  10. package/README.md +266 -266
  11. package/bin/adapt.js +3 -3
  12. package/json/help-create/component.json +9 -9
  13. package/json/help-create/course.json +9 -9
  14. package/json/help-create/question.json +9 -9
  15. package/json/help-create.json +12 -12
  16. package/json/help-devinstall.json +9 -9
  17. package/json/help-install.json +10 -10
  18. package/json/help-ls.json +7 -7
  19. package/json/help-register.json +7 -7
  20. package/json/help-rename.json +7 -7
  21. package/json/help-search.json +8 -8
  22. package/json/help-uninstall.json +7 -7
  23. package/json/help-unregister.json +8 -8
  24. package/json/help-update.json +12 -12
  25. package/json/help-version.json +7 -7
  26. package/json/help.json +19 -19
  27. package/lib/api.js +260 -260
  28. package/lib/cli.js +69 -69
  29. package/lib/commands/authenticate.js +18 -18
  30. package/lib/commands/create/component.js +64 -64
  31. package/lib/commands/create/course.js +26 -26
  32. package/lib/commands/create/question.js +18 -18
  33. package/lib/commands/create.js +94 -85
  34. package/lib/commands/devinstall.js +35 -35
  35. package/lib/commands/help.js +31 -31
  36. package/lib/commands/install.js +16 -16
  37. package/lib/commands/ls.js +9 -9
  38. package/lib/commands/register.js +11 -11
  39. package/lib/commands/rename.js +14 -14
  40. package/lib/commands/search.js +11 -11
  41. package/lib/commands/uninstall.js +9 -9
  42. package/lib/commands/unregister.js +12 -12
  43. package/lib/commands/update.js +12 -12
  44. package/lib/commands/version.js +13 -13
  45. package/lib/integration/AdaptFramework/build.js +42 -42
  46. package/lib/integration/AdaptFramework/clone.js +27 -27
  47. package/lib/integration/AdaptFramework/deleteSrcCore.js +9 -9
  48. package/lib/integration/AdaptFramework/deleteSrcCourse.js +9 -9
  49. package/lib/integration/AdaptFramework/download.js +21 -21
  50. package/lib/integration/AdaptFramework/erase.js +34 -34
  51. package/lib/integration/AdaptFramework/getLatestVersion.js +79 -79
  52. package/lib/integration/AdaptFramework/npmInstall.js +21 -21
  53. package/lib/integration/AdaptFramework.js +19 -19
  54. package/lib/integration/Plugin.js +404 -404
  55. package/lib/integration/PluginManagement/autenticate.js +56 -56
  56. package/lib/integration/PluginManagement/install.js +224 -224
  57. package/lib/integration/PluginManagement/print.js +52 -52
  58. package/lib/integration/PluginManagement/register.js +130 -130
  59. package/lib/integration/PluginManagement/rename.js +101 -101
  60. package/lib/integration/PluginManagement/schemas.js +8 -8
  61. package/lib/integration/PluginManagement/search.js +46 -46
  62. package/lib/integration/PluginManagement/uninstall.js +141 -141
  63. package/lib/integration/PluginManagement/unregister.js +101 -101
  64. package/lib/integration/PluginManagement/update.js +224 -224
  65. package/lib/integration/PluginManagement.js +21 -21
  66. package/lib/integration/Project.js +146 -146
  67. package/lib/integration/Target.js +299 -299
  68. package/lib/integration/getBowerRegistryConfig.js +34 -34
  69. package/lib/logger.js +28 -28
  70. package/lib/util/JSONReadValidate.js +34 -34
  71. package/lib/util/constants.js +38 -38
  72. package/lib/util/createPromptTask.js +7 -7
  73. package/lib/util/download.js +45 -45
  74. package/lib/util/errors.js +58 -58
  75. package/lib/util/extract.js +24 -24
  76. package/lib/util/getDirNameFromImportMeta.js +6 -6
  77. package/lib/util/promises.js +36 -36
  78. package/package.json +74 -40
@@ -1,14 +1,14 @@
1
- import { rename as pluginRename } from '../integration/PluginManagement.js'
2
-
3
- export default async function rename (logger, ...args) {
4
- /** strip flags */
5
- args = args.filter(arg => !String(arg).startsWith('--'))
6
- const oldName = args[0]
7
- const newName = args[1]
8
- await pluginRename({
9
- logger,
10
- cwd: process.cwd(),
11
- oldName,
12
- newName
13
- })
14
- }
1
+ import { rename as pluginRename } from '../integration/PluginManagement.js'
2
+
3
+ export default async function rename (logger, ...args) {
4
+ /** strip flags */
5
+ args = args.filter(arg => !String(arg).startsWith('--'))
6
+ const oldName = args[0]
7
+ const newName = args[1]
8
+ await pluginRename({
9
+ logger,
10
+ cwd: process.cwd(),
11
+ oldName,
12
+ newName
13
+ })
14
+ }
@@ -1,11 +1,11 @@
1
- import { search as pluginsSearch } from '../integration/PluginManagement.js'
2
-
3
- export default async function search (logger, ...args) {
4
- /** strip flags */
5
- args = args.filter(arg => !String(arg).startsWith('--'))
6
- const searchTerm = (args[0] || '')
7
- await pluginsSearch({
8
- logger,
9
- searchTerm
10
- })
11
- }
1
+ import { search as pluginsSearch } from '../integration/PluginManagement.js'
2
+
3
+ export default async function search (logger, ...args) {
4
+ /** strip flags */
5
+ args = args.filter(arg => !String(arg).startsWith('--'))
6
+ const searchTerm = (args[0] || '')
7
+ await pluginsSearch({
8
+ logger,
9
+ searchTerm
10
+ })
11
+ }
@@ -1,9 +1,9 @@
1
- import { uninstall as pluginsUninstall } from '../integration/PluginManagement.js'
2
-
3
- export default async function uninstall (logger, ...args) {
4
- const plugins = args.filter(arg => !String(arg).startsWith('--'))
5
- await pluginsUninstall({
6
- logger,
7
- plugins
8
- })
9
- }
1
+ import { uninstall as pluginsUninstall } from '../integration/PluginManagement.js'
2
+
3
+ export default async function uninstall (logger, ...args) {
4
+ const plugins = args.filter(arg => !String(arg).startsWith('--'))
5
+ await pluginsUninstall({
6
+ logger,
7
+ plugins
8
+ })
9
+ }
@@ -1,12 +1,12 @@
1
- import { unregister as pluginUnregister } from '../integration/PluginManagement.js'
2
-
3
- export default async function register (logger, ...args) {
4
- // strip flags
5
- args = args.filter(arg => !String(arg).startsWith('--'))
6
- const pluginName = args[0]
7
- return await pluginUnregister({
8
- logger,
9
- cwd: process.cwd(),
10
- pluginName
11
- })
12
- }
1
+ import { unregister as pluginUnregister } from '../integration/PluginManagement.js'
2
+
3
+ export default async function register (logger, ...args) {
4
+ // strip flags
5
+ args = args.filter(arg => !String(arg).startsWith('--'))
6
+ const pluginName = args[0]
7
+ return await pluginUnregister({
8
+ logger,
9
+ cwd: process.cwd(),
10
+ pluginName
11
+ })
12
+ }
@@ -1,12 +1,12 @@
1
- import { update as pluginsUpdate } from '../integration/PluginManagement.js'
2
-
3
- export default async function update (logger, ...args) {
4
- /** strip flags */
5
- const isDryRun = args.includes('--dry-run') || args.includes('--check')
6
- const plugins = args.filter(arg => !String(arg).startsWith('--'))
7
- await pluginsUpdate({
8
- logger,
9
- plugins,
10
- isDryRun
11
- })
12
- }
1
+ import { update as pluginsUpdate } from '../integration/PluginManagement.js'
2
+
3
+ export default async function update (logger, ...args) {
4
+ /** strip flags */
5
+ const isDryRun = args.includes('--dry-run') || args.includes('--check')
6
+ const plugins = args.filter(arg => !String(arg).startsWith('--'))
7
+ await pluginsUpdate({
8
+ logger,
9
+ plugins,
10
+ isDryRun
11
+ })
12
+ }
@@ -1,13 +1,13 @@
1
- import Project from '../integration/Project.js'
2
- import path from 'path'
3
- import { readValidateJSONSync } from '../util/JSONReadValidate.js'
4
- import getDirNameFromImportMeta from '../util/getDirNameFromImportMeta.js'
5
- const __dirname = getDirNameFromImportMeta(import.meta)
6
-
7
- export default function version (logger) {
8
- const cliVersionPath = path.join(__dirname, '../../package.json')
9
- const cliVersion = readValidateJSONSync(cliVersionPath).version
10
- const project = new Project()
11
- logger?.log('CLI: ' + cliVersion)
12
- logger?.log('Framework: ' + project.version)
13
- }
1
+ import Project from '../integration/Project.js'
2
+ import path from 'path'
3
+ import { readValidateJSONSync } from '../util/JSONReadValidate.js'
4
+ import getDirNameFromImportMeta from '../util/getDirNameFromImportMeta.js'
5
+ const __dirname = getDirNameFromImportMeta(import.meta)
6
+
7
+ export default function version (logger) {
8
+ const cliVersionPath = path.join(__dirname, '../../package.json')
9
+ const cliVersion = readValidateJSONSync(cliVersionPath).version
10
+ const project = new Project()
11
+ logger?.log('CLI: ' + cliVersion)
12
+ logger?.log('Framework: ' + project.version)
13
+ }
@@ -1,42 +1,42 @@
1
- import chalk from 'chalk'
2
- import { exec } from 'child_process'
3
- import Project from '../Project.js'
4
- import path from 'path'
5
-
6
- export default async function adaptBuild ({
7
- sourceMaps = false,
8
- checkJSON = false,
9
- cache = true,
10
- outputDir = null,
11
- cachePath = null,
12
- cwd = process.cwd(),
13
- logger
14
- } = {}) {
15
- cwd = path.resolve(process.cwd(), cwd)
16
- const project = new Project({ cwd, logger })
17
- project.tryThrowInvalidPath()
18
- logger?.log(chalk.cyan('running build'))
19
- await new Promise((resolve, reject) => {
20
- const cmd = [
21
- 'npx grunt',
22
- !checkJSON
23
- ? `server-build:${sourceMaps ? 'dev' : 'prod'}` // AAT
24
- : `${sourceMaps ? 'diff' : 'build'}`, // Handbuilt
25
- !cache && '--disable-cache',
26
- outputDir && `--outputdir=${outputDir}`,
27
- cachePath && `--cachepath=${cachePath}`
28
- ].filter(Boolean).join(' ');
29
- exec(cmd, { cwd }, (error, stdout, stderr) => {
30
- if(error || stderr) {
31
- const matches = stdout.match(/>> Error:\s(.+)\s/);
32
- const e = new Error('grunt tasks failed')
33
- e.cmd = cmd;
34
- e.raw = matches?.[1] ?? stdout;
35
- e.source = error;
36
- e.stderr = stderr;
37
- return reject(e)
38
- }
39
- resolve()
40
- })
41
- })
42
- }
1
+ import chalk from 'chalk'
2
+ import { exec } from 'child_process'
3
+ import Project from '../Project.js'
4
+ import path from 'path'
5
+
6
+ export default async function adaptBuild ({
7
+ sourceMaps = false,
8
+ checkJSON = false,
9
+ cache = true,
10
+ outputDir = null,
11
+ cachePath = null,
12
+ cwd = process.cwd(),
13
+ logger
14
+ } = {}) {
15
+ cwd = path.resolve(process.cwd(), cwd)
16
+ const project = new Project({ cwd, logger })
17
+ project.tryThrowInvalidPath()
18
+ logger?.log(chalk.cyan('running build'))
19
+ await new Promise((resolve, reject) => {
20
+ const cmd = [
21
+ 'npx grunt',
22
+ !checkJSON
23
+ ? `server-build:${sourceMaps ? 'dev' : 'prod'}` // AAT
24
+ : `${sourceMaps ? 'diff' : 'build'}`, // Handbuilt
25
+ !cache && '--disable-cache',
26
+ outputDir && `--outputdir=${outputDir}`,
27
+ cachePath && `--cachepath=${cachePath}`
28
+ ].filter(Boolean).join(' ');
29
+ exec(cmd, { cwd }, (error, stdout, stderr) => {
30
+ if(error || stderr) {
31
+ const matches = stdout.match(/>> Error:\s(.+)\s/);
32
+ const e = new Error('grunt tasks failed')
33
+ e.cmd = cmd;
34
+ e.raw = matches?.[1] ?? stdout;
35
+ e.source = error;
36
+ e.stderr = stderr;
37
+ return reject(e)
38
+ }
39
+ resolve()
40
+ })
41
+ })
42
+ }
@@ -1,27 +1,27 @@
1
- import chalk from 'chalk'
2
- import { exec } from 'child_process'
3
- import { ADAPT_FRAMEWORK } from '../../util/constants.js'
4
- import path from 'path'
5
-
6
- export default async function clone ({
7
- repository = ADAPT_FRAMEWORK,
8
- branch = 'master',
9
- cwd = process.cwd(),
10
- logger
11
- } = {}) {
12
- repository = repository.replace(/\.git/g, '')
13
- cwd = path.resolve(process.cwd(), cwd)
14
- if (!branch && !repository) throw new Error('Repository details are required.')
15
- logger?.write(chalk.cyan('cloning framework to', cwd, '\t'))
16
- await new Promise(function (resolve, reject) {
17
- const child = exec(`git clone ${repository} "${cwd}"`)
18
- child.addListener('error', reject)
19
- child.addListener('exit', resolve)
20
- })
21
- await new Promise(function (resolve, reject) {
22
- const child = exec(`git checkout ${branch}`)
23
- child.addListener('error', reject)
24
- child.addListener('exit', resolve)
25
- })
26
- logger?.log(' ', 'done!')
27
- }
1
+ import chalk from 'chalk'
2
+ import { exec } from 'child_process'
3
+ import { ADAPT_FRAMEWORK } from '../../util/constants.js'
4
+ import path from 'path'
5
+
6
+ export default async function clone ({
7
+ repository = ADAPT_FRAMEWORK,
8
+ branch = 'master',
9
+ cwd = process.cwd(),
10
+ logger
11
+ } = {}) {
12
+ repository = repository.replace(/\.git/g, '')
13
+ cwd = path.resolve(process.cwd(), cwd)
14
+ if (!branch && !repository) throw new Error('Repository details are required.')
15
+ logger?.write(chalk.cyan('cloning framework to', cwd, '\t'))
16
+ await new Promise(function (resolve, reject) {
17
+ const child = exec(`git clone ${repository} "${cwd}"`)
18
+ child.addListener('error', reject)
19
+ child.addListener('exit', resolve)
20
+ })
21
+ await new Promise(function (resolve, reject) {
22
+ const child = exec(`git checkout ${branch}`)
23
+ child.addListener('error', reject)
24
+ child.addListener('exit', resolve)
25
+ })
26
+ logger?.log(' ', 'done!')
27
+ }
@@ -1,9 +1,9 @@
1
- import fs from 'fs-extra'
2
- import path from 'path'
3
-
4
- export default function deleteSrcCore ({
5
- cwd = process.cwd()
6
- } = {}) {
7
- cwd = path.resolve(process.cwd(), cwd)
8
- return fs.rm(path.resolve(cwd, 'src/core'), { recursive: true, force: true })
9
- }
1
+ import fs from 'fs-extra'
2
+ import path from 'path'
3
+
4
+ export default function deleteSrcCore ({
5
+ cwd = process.cwd()
6
+ } = {}) {
7
+ cwd = path.resolve(process.cwd(), cwd)
8
+ return fs.rm(path.resolve(cwd, 'src/core'), { recursive: true, force: true })
9
+ }
@@ -1,9 +1,9 @@
1
- import fs from 'fs-extra'
2
- import path from 'path'
3
-
4
- export default function deleteSrcCourse ({
5
- cwd = process.cwd()
6
- } = {}) {
7
- cwd = path.resolve(process.cwd(), cwd)
8
- return fs.rm(path.resolve(cwd, 'src/course'), { recursive: true, force: true })
9
- }
1
+ import fs from 'fs-extra'
2
+ import path from 'path'
3
+
4
+ export default function deleteSrcCourse ({
5
+ cwd = process.cwd()
6
+ } = {}) {
7
+ cwd = path.resolve(process.cwd(), cwd)
8
+ return fs.rm(path.resolve(cwd, 'src/course'), { recursive: true, force: true })
9
+ }
@@ -1,21 +1,21 @@
1
- import downloader from '../../util/download.js'
2
- import { ADAPT_FRAMEWORK } from '../../util/constants.js'
3
- import path from 'path'
4
-
5
- export default async function download ({
6
- repository = ADAPT_FRAMEWORK,
7
- branch,
8
- tmp,
9
- cwd,
10
- logger
11
- } = {}) {
12
- repository = repository.replace(/\.git/g, '')
13
- cwd = path.resolve(process.cwd(), cwd)
14
- return downloader({
15
- repository,
16
- branch,
17
- tmp,
18
- cwd,
19
- logger
20
- })
21
- }
1
+ import downloader from '../../util/download.js'
2
+ import { ADAPT_FRAMEWORK } from '../../util/constants.js'
3
+ import path from 'path'
4
+
5
+ export default async function download ({
6
+ repository = ADAPT_FRAMEWORK,
7
+ branch,
8
+ tmp,
9
+ cwd,
10
+ logger
11
+ } = {}) {
12
+ repository = repository.replace(/\.git/g, '')
13
+ cwd = path.resolve(process.cwd(), cwd)
14
+ return downloader({
15
+ repository,
16
+ branch,
17
+ tmp,
18
+ cwd,
19
+ logger
20
+ })
21
+ }
@@ -1,34 +1,34 @@
1
- import chalk from 'chalk'
2
- import fs from 'fs-extra'
3
- import inquirer from 'inquirer'
4
- import globs from 'globs'
5
- import path from 'path'
6
-
7
- export default async function erase ({
8
- isInteractive = true,
9
- cwd,
10
- logger
11
- } = {}) {
12
- cwd = path.resolve(process.cwd(), cwd)
13
- if (!fs.existsSync(cwd)) return
14
- if (isInteractive) {
15
- const results = await inquirer.prompt([{
16
- name: 'overwrite existing course?',
17
- type: 'confirm',
18
- default: false
19
- }])
20
- if (!results['overwrite existing course?']) {
21
- throw new Error('Course already exists and cannot overwrite.')
22
- }
23
- }
24
- logger?.log(chalk.cyan('deleting existing course'))
25
- const files = await new Promise((resolve, reject) => {
26
- globs('**', { cwd }, (err, files) => {
27
- if (err) return reject(err)
28
- resolve(files)
29
- })
30
- })
31
- for (const file of files) {
32
- await fs.rm(file, { recursive: true })
33
- }
34
- }
1
+ import chalk from 'chalk'
2
+ import fs from 'fs-extra'
3
+ import inquirer from 'inquirer'
4
+ import globs from 'globs'
5
+ import path from 'path'
6
+
7
+ export default async function erase ({
8
+ isInteractive = true,
9
+ cwd,
10
+ logger
11
+ } = {}) {
12
+ cwd = path.resolve(process.cwd(), cwd)
13
+ if (!fs.existsSync(cwd)) return
14
+ if (isInteractive) {
15
+ const results = await inquirer.prompt([{
16
+ name: 'overwrite existing course?',
17
+ type: 'confirm',
18
+ default: false
19
+ }])
20
+ if (!results['overwrite existing course?']) {
21
+ throw new Error('Course already exists and cannot overwrite.')
22
+ }
23
+ }
24
+ logger?.log(chalk.cyan('deleting existing course'))
25
+ const files = await new Promise((resolve, reject) => {
26
+ globs('**', { cwd }, (err, files) => {
27
+ if (err) return reject(err)
28
+ resolve(files)
29
+ })
30
+ })
31
+ for (const file of files) {
32
+ await fs.rm(file, { recursive: true })
33
+ }
34
+ }
@@ -1,79 +1,79 @@
1
- import request from 'request'
2
- import semver from 'semver'
3
- import gh from 'parse-github-url'
4
- import { ADAPT_DEFAULT_USER_AGENT, ADAPT_FRAMEWORK, ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js'
5
- const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE }
6
-
7
- export default async function getLatestVersion ({ versionLimit, repository = ADAPT_FRAMEWORK }) {
8
- repository = repository.replace(/\.git/g, '')
9
- const OWNER = gh(repository).owner
10
- const NAME = gh(repository).name
11
- // used in pagination
12
- let nextPage = `https://api.github.com/repos/${OWNER}/${NAME}/releases`
13
- // taken from https://gist.github.com/niallo/3109252
14
- const parseLinkHeader = header => {
15
- if (!header || header.length === 0) {
16
- return []
17
- }
18
- const links = {}
19
- // Parse each part into a named link
20
- header.split(',').forEach(p => {
21
- const section = p.split(';')
22
- if (section.length !== 2) {
23
- throw new Error("section could not be split on ';'")
24
- }
25
- const url = section[0].replace(/<(.*)>/, '$1').trim()
26
- const name = section[1].replace(/rel="(.*)"/, '$1').trim()
27
- links[name] = url
28
- })
29
- return links
30
- }
31
- const processPage = async () => {
32
- const [response, body] = await new Promise((resolve, reject) => {
33
- request({
34
- headers: {
35
- 'User-Agent': ADAPT_DEFAULT_USER_AGENT
36
- },
37
- uri: nextPage,
38
- method: 'GET'
39
- }, (error, response, body) => {
40
- if (error) return reject(error)
41
- resolve([response, body])
42
- })
43
- })
44
- if (response?.statusCode === 403 && response?.headers['x-ratelimit-remaining'] === '0') {
45
- // we've exceeded the API limit
46
- const reqsReset = new Date(response.headers['x-ratelimit-reset'] * 1000)
47
- 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
- }
49
- if (response?.statusCode !== 200) {
50
- throw new Error(`Couldn't check latest version of ${NAME}. GitubAPI did not respond with a 200 status code.`)
51
- }
52
- nextPage = parseLinkHeader(response.headers.link).next
53
- let releases
54
- try {
55
- // parse and sort releases (newest first)
56
- releases = JSON.parse(body).sort((a, b) => {
57
- if (semver.lt(a.tag_name, b.tag_name, semverOptions)) return 1
58
- if (semver.gt(a.tag_name, b.tag_name, semverOptions)) return -1
59
- return 0
60
- })
61
- } catch (e) {
62
- throw new Error(`Failed to parse GitHub release data\n${e}`)
63
- }
64
- const compatibleRelease = releases.find(release => {
65
- const isFullRelease = !release.draft && !release.prerelease
66
- const satisfiesVersion = !versionLimit || semver.satisfies(release.tag_name, versionLimit, semverOptions)
67
- if (!isFullRelease || !satisfiesVersion) return false
68
- return true
69
- })
70
- if (!compatibleRelease && nextPage) {
71
- return await processPage()
72
- }
73
- if (!compatibleRelease) {
74
- throw new Error(`Couldn't find any releases compatible with specified framework version (${versionLimit}), please check that it is a valid version.`)
75
- }
76
- return compatibleRelease.tag_name
77
- }
78
- return await processPage()
79
- }
1
+ import request from 'request'
2
+ import semver from 'semver'
3
+ import gh from 'parse-github-url'
4
+ import { ADAPT_DEFAULT_USER_AGENT, ADAPT_FRAMEWORK, ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js'
5
+ const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE }
6
+
7
+ export default async function getLatestVersion ({ versionLimit, repository = ADAPT_FRAMEWORK }) {
8
+ repository = repository.replace(/\.git/g, '')
9
+ const OWNER = gh(repository).owner
10
+ const NAME = gh(repository).name
11
+ // used in pagination
12
+ let nextPage = `https://api.github.com/repos/${OWNER}/${NAME}/releases`
13
+ // taken from https://gist.github.com/niallo/3109252
14
+ const parseLinkHeader = header => {
15
+ if (!header || header.length === 0) {
16
+ return []
17
+ }
18
+ const links = {}
19
+ // Parse each part into a named link
20
+ header.split(',').forEach(p => {
21
+ const section = p.split(';')
22
+ if (section.length !== 2) {
23
+ throw new Error("section could not be split on ';'")
24
+ }
25
+ const url = section[0].replace(/<(.*)>/, '$1').trim()
26
+ const name = section[1].replace(/rel="(.*)"/, '$1').trim()
27
+ links[name] = url
28
+ })
29
+ return links
30
+ }
31
+ const processPage = async () => {
32
+ const [response, body] = await new Promise((resolve, reject) => {
33
+ request({
34
+ headers: {
35
+ 'User-Agent': ADAPT_DEFAULT_USER_AGENT
36
+ },
37
+ uri: nextPage,
38
+ method: 'GET'
39
+ }, (error, response, body) => {
40
+ if (error) return reject(error)
41
+ resolve([response, body])
42
+ })
43
+ })
44
+ if (response?.statusCode === 403 && response?.headers['x-ratelimit-remaining'] === '0') {
45
+ // we've exceeded the API limit
46
+ const reqsReset = new Date(response.headers['x-ratelimit-reset'] * 1000)
47
+ 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
+ }
49
+ if (response?.statusCode !== 200) {
50
+ throw new Error(`Couldn't check latest version of ${NAME}. GitubAPI did not respond with a 200 status code.`)
51
+ }
52
+ nextPage = parseLinkHeader(response.headers.link).next
53
+ let releases
54
+ try {
55
+ // parse and sort releases (newest first)
56
+ releases = JSON.parse(body).sort((a, b) => {
57
+ if (semver.lt(a.tag_name, b.tag_name, semverOptions)) return 1
58
+ if (semver.gt(a.tag_name, b.tag_name, semverOptions)) return -1
59
+ return 0
60
+ })
61
+ } catch (e) {
62
+ throw new Error(`Failed to parse GitHub release data\n${e}`)
63
+ }
64
+ const compatibleRelease = releases.find(release => {
65
+ const isFullRelease = !release.draft && !release.prerelease
66
+ const satisfiesVersion = !versionLimit || semver.satisfies(release.tag_name, versionLimit, semverOptions)
67
+ if (!isFullRelease || !satisfiesVersion) return false
68
+ return true
69
+ })
70
+ if (!compatibleRelease && nextPage) {
71
+ return await processPage()
72
+ }
73
+ if (!compatibleRelease) {
74
+ throw new Error(`Couldn't find any releases compatible with specified framework version (${versionLimit}), please check that it is a valid version.`)
75
+ }
76
+ return compatibleRelease.tag_name
77
+ }
78
+ return await processPage()
79
+ }
@@ -1,21 +1,21 @@
1
- import chalk from 'chalk'
2
- import { spawn } from 'child_process'
3
- import path from 'path'
4
-
5
- export default async function npmInstall ({
6
- logger,
7
- cwd
8
- } = {}) {
9
- cwd = path.resolve(process.cwd(), cwd)
10
- await new Promise((resolve, reject) => {
11
- logger?.log(chalk.cyan('installing node dependencies'))
12
- const npm = spawn((process.platform === 'win32' ? 'npm.cmd' : 'npm'), ['--unsafe-perm', 'install'], {
13
- stdio: 'inherit',
14
- cwd
15
- })
16
- npm.on('close', code => {
17
- if (code) return reject(new Error('npm install failed'))
18
- resolve()
19
- })
20
- })
21
- }
1
+ import chalk from 'chalk'
2
+ import { spawn } from 'child_process'
3
+ import path from 'path'
4
+
5
+ export default async function npmInstall ({
6
+ logger,
7
+ cwd
8
+ } = {}) {
9
+ cwd = path.resolve(process.cwd(), cwd)
10
+ await new Promise((resolve, reject) => {
11
+ logger?.log(chalk.cyan('installing node dependencies'))
12
+ const npm = spawn((process.platform === 'win32' ? 'npm.cmd' : 'npm'), ['--unsafe-perm', 'install'], {
13
+ stdio: 'inherit',
14
+ cwd
15
+ })
16
+ npm.on('close', code => {
17
+ if (code) return reject(new Error('npm install failed'))
18
+ resolve()
19
+ })
20
+ })
21
+ }