-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild-meta-md.ts
More file actions
123 lines (105 loc) · 3.92 KB
/
Copy pathbuild-meta-md.ts
File metadata and controls
123 lines (105 loc) · 3.92 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
import path from 'node:path'
import fs from 'node:fs'
import cp from 'node:child_process'
import { tools } from '../test/bench/stand/index.ts'
const __dirname = path.dirname(new URL(import.meta.url).pathname)
const outfile = path.resolve(__dirname, '../../META.md')
const tmpbase = path.resolve(__dirname, '../../tmp')
interface PackageInfo {
name: string
size: string // unpacked size of package
installSize: string // unpacked size + deps
node: string
browser: boolean
moduleTypes: string[]
types: boolean
}
function formatSize(bytes: number): string {
if (!bytes) return 'n/a'
if (bytes > 1024 * 1024) return (bytes / 1024 / 1024).toFixed(1) + ' MB'
return (bytes / 1024).toFixed(1) + ' kB'
}
async function getNpmMetadata(pkg: string) {
const res = await fetch(`https://registry.npmjs.org/${pkg}`)
if (!res.ok) throw new Error(`Failed to fetch ${pkg}`)
return res.json()
}
async function getPackageInfo(pkg: string, repo: string): Promise<PackageInfo> {
console.log(`fetching ${pkg} meta...`)
const tmp = path.join(tmpbase, pkg.replace('/', '-'))
await fs.promises.mkdir(tmp, { recursive: true })
await fs.promises.writeFile(path.join(tmp, 'package.json'), JSON.stringify({dependencies: { [pkg]: 'latest' }}))
const {promise, resolve, reject} = Promise.withResolvers()
cp.exec('npm install --prefer-offline --no-audit --no-fund --ignore-scripts --package-lock-only', { cwd: tmp }, (err) => err ? reject(err) : resolve(true))
await promise
const pkgLock = JSON.parse(await fs.promises.readFile(path.join(tmp, 'package-lock.json'), 'utf-8'))
const meta = await getNpmMetadata(pkg)
const latest = meta['dist-tags'].latest
const pkgInfo = meta.versions[latest]
const unpackedSize = pkgInfo.dist?.unpackedSize ?? 0
let installSize = 0
for (const [location, {version}] of Object.entries(pkgLock.packages as Record<string, {version?: string}> ?? {})) {
try {
if (!version) continue
const name = location === '' ? pkg : location.replace('node_modules/', '')
const depMeta = await getNpmMetadata(name)
installSize += depMeta.versions[version]?.dist?.unpackedSize ?? 0
} catch {
/* ignore missing dep sizes */
}
}
const engines = pkgInfo.engines?.node ?? 'n/a'
const browser = !!pkgInfo.browser
const hasTypes =
!!pkgInfo.types ||
!!pkgInfo.typings ||
(pkgInfo.devDependencies && Object.keys(pkgInfo.devDependencies).some(d => d.startsWith('@types/')))
const moduleTypes: string[] = []
if (pkgInfo.type === 'module' || pkgInfo.module || pkgInfo.exports?.['.']?.import) {
moduleTypes.push('ESM')
}
if (pkgInfo.main || pkgInfo.exports?.['.']?.require) {
moduleTypes.push('CJS')
}
return {
name: `[\`${pkg}\`](${repo})`,
size: formatSize(unpackedSize),
installSize: formatSize(installSize),
node: engines.replace('>', '\\>').replace('<', '\\<'),
browser,
moduleTypes,
types: hasTypes,
}
}
function toMarkdown(pkgs: PackageInfo[]): string {
const headers = [
'Package',
'Publish size',
'Install size',
'Node.js',
'Modules',
'Types',
]
const table = [
`| ${headers.join(' | ')} |`,
`| ${headers.map((_, i) => '---' + (i > 0 ? ':' : '')).join(' | ')} |`,
...pkgs.map(p =>
`| ${p.name} | ${p.size} | ${p.installSize} | ${p.node} | ${p.moduleTypes.join(', ')} | ${p.types ? '✓' : '❌'} |`
),
]
return table.join('\n')
}
let output = `# Package meta across libraries
> Autogenerated by [\`src/scripts/build-meta-md.ts\`](./src/scripts/build-meta-md.ts)
`
const packages = Object.keys(tools).filter((k) => k !== 'node:net' && k !== '@webpod/ip/core')
const results: PackageInfo[] = []
for (const pkg of packages) {
try {
results.push(await getPackageInfo(pkg, tools[pkg]?.ref as string || `https://www.npmjs.com/package/${pkg}`))
} catch (err) {
console.error(`Failed to fetch ${pkg}:`, err)
}
}
output += toMarkdown(results)
fs.writeFileSync(outfile, output)