-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathview.ts
More file actions
163 lines (145 loc) · 5.05 KB
/
Copy pathview.ts
File metadata and controls
163 lines (145 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS104: Avoid inline assignments
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import * as _ from "@aminya/underscore-plus"
import yargs from "yargs"
import semver from "semver"
import Command from "./command"
import * as config from "./apm"
import * as request from "./request"
import { tree } from "./tree"
import type { CliOptions, RunCallback } from "./apm-cli"
import { PackageData } from "./stars"
import { PackageMetadata } from "./packages"
export default class View extends Command {
parseOptions(argv: string[]) {
const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth()))
options.usage(`\
Usage: apm view <package_name>
View information about a package/theme in the atom.io registry.\
`)
options.alias("h", "help").describe("help", "Print this usage message")
options.boolean("json").describe("json", "Output featured packages as JSON array")
return options
.string("compatible")
.describe("compatible", "Show the latest version compatible with this Atom version")
}
loadInstalledAtomVersion(options, callback) {
return process.nextTick(() => {
let installedAtomVersion
if (options.argv.compatible) {
const version = this.normalizeVersion(options.argv.compatible)
if (semver.valid(version)) {
installedAtomVersion = version
}
}
return callback(installedAtomVersion)
})
}
getLatestCompatibleVersion(pack: PackageData, options, callback) {
return this.loadInstalledAtomVersion(options, function (installedAtomVersion) {
if (!installedAtomVersion) {
return callback(pack.releases.latest)
}
let latestVersion = null
const object = pack.versions != null ? pack.versions : {}
for (const version in object) {
const metadata = object[version]
if (!semver.valid(version)) {
continue
}
if (!metadata) {
continue
}
const engine = metadata.engines?.atom != null ? metadata.engines?.atom : "*"
if (!semver.validRange(engine)) {
continue
}
if (!semver.satisfies(installedAtomVersion, engine)) {
continue
}
if (latestVersion == null) {
latestVersion = version
}
if (semver.gt(version, latestVersion)) {
latestVersion = version
}
}
return callback(latestVersion)
})
}
getRepository(pack: PackageMetadata) {
let repository
if ((repository = pack.repository?.url != null ? pack.repository?.url : pack.repository)) {
return repository.replace(/\.git$/, "")
}
}
getPackage(packageName: string, options: CliOptions, callback: (error: string, pack?: any) => any) {
const requestSettings = {
url: `${config.getAtomPackagesUrl()}/${packageName}`,
json: true,
}
return request.get(requestSettings, (error, response, body = {}) => {
if (error != null) {
return callback(error)
} else if (response.statusCode === 200) {
return this.getLatestCompatibleVersion(body, options, function (version) {
const { name, readme, downloads, stargazers_count } = body
const metadata = body.versions?.[version] != null ? body.versions?.[version] : { name }
const pack = { ...metadata, readme, downloads, stargazers_count }
return callback(null, pack)
})
} else {
let left
const message = (left = body.message != null ? body.message : body.error) != null ? left : body
return callback(`Requesting package failed: ${message}`)
}
})
}
run(options: CliOptions, callback: RunCallback) {
options = this.parseOptions(options.commandArgs)
const [packageName] = Array.from(options.argv._)
if (!packageName) {
callback("Missing required package name")
return
}
return this.getPackage(packageName, options, (error, pack) => {
if (error != null) {
callback(error)
return
}
if (options.argv.json) {
console.log(JSON.stringify(pack, null, 2))
} else {
let repository
console.log(`${pack.name.cyan}`)
const items = []
if (pack.version) {
items.push(pack.version.yellow)
}
if ((repository = this.getRepository(pack))) {
items.push(repository.underline)
}
if (pack.description) {
items.push(pack.description.replace(/\s+/g, " "))
}
if (pack.downloads >= 0) {
items.push(_.pluralize(pack.downloads, "download"))
}
if (pack.stargazers_count >= 0) {
items.push(_.pluralize(pack.stargazers_count, "star"))
}
tree(items)
console.log()
console.log(`Run \`apm install ${pack.name}\` to install this package.`)
console.log()
}
return callback()
})
}
}