| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- import { mkdir, readFile, writeFile } from 'node:fs/promises'
- import { dirname, join, resolve } from 'node:path'
- import { spawnSync } from 'node:child_process'
- import { fileURLToPath } from 'node:url'
- const scriptDir = dirname(fileURLToPath(import.meta.url))
- const sourceRoot = resolve(scriptDir, '..')
- const args = process.argv.slice(2)
- const readJson = async path => JSON.parse(await readFile(path, 'utf8'))
- const branchRoles = await readJson(join(sourceRoot, 'ecosystem', 'branch-roles.json'))
- const optionValue = name => {
- const prefix = `${name}=`
- const match = args.find(arg => arg.startsWith(prefix))
- return match ? match.slice(prefix.length) : null
- }
- const repoSlugFromUrl = url => {
- const match = String(url).match(/github\.com[:/]([^/]+\/[^/]+?)(?:\.git)?$/)
- if (!match) {
- throw new Error(`Unable to parse GitHub repository URL: ${url}`)
- }
- return match[1]
- }
- const repo = optionValue('--repo') || repoSlugFromUrl(branchRoles.publicMainRepository.github)
- const output = optionValue('--output')
- const jsonOutput = args.includes('--json')
- const runGhJson = commandArgs => {
- const result = spawnSync('gh', commandArgs, {
- cwd: sourceRoot,
- encoding: 'utf8',
- stdio: 'pipe'
- })
- if (result.status !== 0) {
- const details = [result.stderr, result.stdout].filter(Boolean).join('\n')
- throw new Error(`Command failed: gh ${commandArgs.join(' ')}${details ? `\n${details}` : ''}`)
- }
- return JSON.parse(result.stdout || '{}')
- }
- const api = path => runGhJson(['api', `repos/${repo}${path}`])
- const [repoInfo, views, clones, referrers, paths] = [
- api(''),
- api('/traffic/views'),
- api('/traffic/clones'),
- api('/traffic/popular/referrers'),
- api('/traffic/popular/paths')
- ]
- const snapshot = {
- generatedAt: new Date().toISOString(),
- repo,
- stars: repoInfo.stargazers_count,
- forks: repoInfo.forks_count,
- openIssues: repoInfo.open_issues_count,
- watchers: repoInfo.subscribers_count,
- views,
- clones,
- referrers,
- paths
- }
- const table = (headers, rows) => {
- const line = `| ${headers.join(' | ')} |`
- const divider = `| ${headers.map(() => '---').join(' | ')} |`
- return [line, divider, ...rows.map(row => `| ${row.join(' | ')} |`)].join('\n')
- }
- const renderMarkdown = data => {
- const referrerRows = data.referrers.length
- ? data.referrers.map(item => [item.referrer, item.count, item.uniques])
- : [['-', '-', '-']]
- const pathRows = data.paths.length
- ? data.paths.map(item => [item.path, item.title || '-', item.count, item.uniques])
- : [['-', '-', '-', '-']]
- return [
- '# GitHub Traffic Snapshot',
- '',
- `- Generated at: ${data.generatedAt}`,
- `- Repository: ${data.repo}`,
- `- Stars: ${data.stars}`,
- `- Forks: ${data.forks}`,
- `- Open issues: ${data.openIssues}`,
- `- Watchers: ${data.watchers}`,
- `- Views: ${data.views.count} total / ${data.views.uniques} unique`,
- `- Clones: ${data.clones.count} total / ${data.clones.uniques} unique`,
- '',
- '## Referrers',
- '',
- table(['Referrer', 'Views', 'Unique visitors'], referrerRows),
- '',
- '## Popular Content',
- '',
- table(['Path', 'Title', 'Views', 'Unique visitors'], pathRows),
- ''
- ].join('\n')
- }
- const body = jsonOutput ? `${JSON.stringify(snapshot, null, 2)}\n` : renderMarkdown(snapshot)
- if (output) {
- const outputPath = resolve(sourceRoot, output)
- await mkdir(dirname(outputPath), { recursive: true })
- await writeFile(outputPath, body)
- console.log(`Wrote ${outputPath.replace(`${sourceRoot}/`, '')}`)
- } else {
- process.stdout.write(body)
- }
|