snapshot-npm-downloads.mjs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { mkdir, writeFile } from 'node:fs/promises'
  2. import { dirname, resolve } from 'node:path'
  3. import { fileURLToPath } from 'node:url'
  4. const scriptDir = dirname(fileURLToPath(import.meta.url))
  5. const sourceRoot = resolve(scriptDir, '..')
  6. const args = process.argv.slice(2)
  7. const defaultPackages = [
  8. '@file-viewer/core',
  9. '@file-viewer/web',
  10. '@file-viewer/web-full',
  11. '@file-viewer/vue3',
  12. '@file-viewer/vue3-full',
  13. '@file-viewer/react',
  14. '@file-viewer/react-full',
  15. '@file-viewer/svelte',
  16. '@file-viewer/svelte-full'
  17. ]
  18. const optionValue = name => {
  19. const prefix = `${name}=`
  20. const match = args.find(arg => arg.startsWith(prefix))
  21. return match ? match.slice(prefix.length) : null
  22. }
  23. const period = optionValue('--period') || 'last-week'
  24. const output = optionValue('--output')
  25. const jsonOutput = args.includes('--json')
  26. const packages = args
  27. .filter(arg => !arg.startsWith('--'))
  28. .flatMap(arg => arg.split(','))
  29. .map(arg => arg.trim())
  30. .filter(Boolean)
  31. const packageNames = packages.length ? packages : defaultPackages
  32. const readDownloads = async name => {
  33. const encoded = encodeURIComponent(name)
  34. const response = await fetch(`https://api.npmjs.org/downloads/point/${period}/${encoded}`)
  35. if (!response.ok) {
  36. return {
  37. package: name,
  38. downloads: null,
  39. start: null,
  40. end: null,
  41. error: `${response.status} ${response.statusText}`.trim()
  42. }
  43. }
  44. return response.json()
  45. }
  46. const rows = await Promise.all(packageNames.map(readDownloads))
  47. const snapshot = {
  48. generatedAt: new Date().toISOString(),
  49. period,
  50. packages: rows.map(row => ({
  51. package: row.package,
  52. downloads: row.downloads,
  53. start: row.start,
  54. end: row.end,
  55. error: row.error || null
  56. }))
  57. }
  58. const renderMarkdown = data => [
  59. '# npm Downloads Snapshot',
  60. '',
  61. `- Generated at: ${data.generatedAt}`,
  62. `- Period: ${data.period}`,
  63. '',
  64. '| Package | Downloads | Start | End | Status |',
  65. '| --- | --- | --- | --- | --- |',
  66. ...data.packages.map(row => `| ${row.package} | ${row.downloads ?? '-'} | ${row.start ?? '-'} | ${row.end ?? '-'} | ${row.error ? `unavailable: ${row.error}` : 'ok'} |`),
  67. ''
  68. ].join('\n')
  69. const body = jsonOutput ? `${JSON.stringify(snapshot, null, 2)}\n` : renderMarkdown(snapshot)
  70. if (output) {
  71. const outputPath = resolve(sourceRoot, output)
  72. await mkdir(dirname(outputPath), { recursive: true })
  73. await writeFile(outputPath, body)
  74. console.log(`Wrote ${outputPath.replace(`${sourceRoot}/`, '')}`)
  75. } else {
  76. process.stdout.write(body)
  77. }