-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbundlephobia.ts
136 lines (114 loc) Β· 4.72 KB
/
bundlephobia.ts
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
import {Command, flags} from '@oclif/command'
import axios from 'axios'
import chalk from 'chalk'
import Logger from '../utilities/logger'
import Utilities from '../utilities/utilities'
// TODO:
// ADD VALID tests ( for now they just ignoring )
export default class Bundlephobia extends Command {
static description = 'Find cost of adding a npm/yarn packages or all dependencies in package.json file'
static flags = {
help: flags.help({char: 'h'}),
packages: flags.string({
char: 'p',
description: 'packages for which cost is required, can pass more than one separated by space',
multiple: true // can get multiple package names
}),
file: flags.string({char: 'f', description: 'path for package.json file'}),
}
static args = [{name: 'package'}] // only one can be passed club which one passed through flag and arg
private static getSize(byteSize: number) {
if (byteSize >= 1024 * 1024)
return `${chalk.red((byteSize / (1024 * 1024)).toFixed(1) + 'MB')}`
else if (byteSize >= 1024)
return `${chalk.blue((byteSize / (1024)).toFixed(1) + 'KB')}`
else //if (byteSize < 1024)
return `${chalk.green(byteSize.toFixed(1) + 'B')}`
}
// values needed package
async run() {
const {args, flags} = this.parse(Bundlephobia)
args.packages = this.getPackages(flags, args) // get a list
Logger.info(this, `running bundlephobia for ${args.packages.length} packages`)
this.checkParameters(flags, args)
this.bundlePhobia(flags, args)
}
private getErrorMessage(pkg: string, message: string) {
// replacing will be useful when we do not have specific version
// output will be like below
/*
β @codingtools/cdt@1.2.3 This package has not been published with this particular version.
Valid versions - `<code>latest</code>`, `<code>0.1.1</code>` and `<code>0.1.2</code>`
*/
if (message.includes('This package has not been published with this particular version.'))
message = message.replace(/`<code>|<\/code>`/g, '')
return `${chalk.red(pkg)} ${message}`
}
private getPackages(flags: any, args: any) {
let packages = []
if (args.package)
packages.push(args.package)
if (flags.packages)
packages = packages.concat(flags.packages) // not inplace operation
// package.json file passed
if (flags.file) {
let jsonObject = Utilities.getJsonObjectFromFile(this, flags.file)
packages = packages.concat(this.convertObjectToArray(jsonObject.dependencies))
}
return packages
}
// tslint:disable-next-line:no-unused
private checkParameters(flags: unknown, args: any) {
if (args.packages.length === 0)
Logger.error(this, 'At least one package must be passed')
}
// tslint:disable-next-line:no-unused
private bundlePhobia(flags: any, args: any) {
Logger.progressStart(this, 'finding size...')
let size = 0
let gzip = 0
let dependencyCount = 0
let packagesResolved = 0
let packagesInfo: any[] = args.packages.map(
(pkg: string) => {
return {
url: `https://bundlephobia.com/api/size?package=${pkg}`,
pkg
}
}
)
// tslint:disable-next-line:no-unsafe-any no-unused
let x = axios.all(packagesInfo.map((packageInfo: any) => { // have to use x for removing TSLintError: promises must be handled appropriately
return axios.get(packageInfo.url).then(successResponse => {
packagesResolved ++
size += successResponse.data.size
gzip += successResponse.data.gzip
dependencyCount += successResponse.data.dependencyCount
Logger.progressStop(this, this.getSuccessMessage(successResponse.data))
}).catch(errorResponse => {
Logger.progressStopError(this, this.getErrorMessage(packageInfo.pkg, errorResponse.response.data.error.message))
})
// tslint:disable-next-line:no-unused
}))
.then(() => {}).catch(() => {})
. finally(() => {
Logger.success(this, this.getFinalMessage({
count: packagesResolved,
dependencyCount,
size,
gzip
}))
})
}
private getFinalMessage(data: any) {
return `\n${chalk.magenta('Total')} [${chalk.cyan(data.count + ' packages resolved')}] has ${data.dependencyCount} dependencies with size of ${Bundlephobia.getSize(data.size)}(${Bundlephobia.getSize(data.gzip)} gzipped)`
}
private getSuccessMessage(data: any) {
return `${chalk.magenta(data.name)}@${chalk.cyan(data.version)} has ${data.dependencyCount} dependencies with size of ${Bundlephobia.getSize(data.size)}(${Bundlephobia.getSize(data.gzip)} gzipped)`
}
private convertObjectToArray(jsobObject: any) {
return Object.keys(jsobObject).map(key => {
return `${key}@${jsobObject[key]}`
})
}
}