|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +import fs from 'fs' |
| 4 | +import path from 'path' |
| 5 | +import { fileURLToPath } from 'url' |
| 6 | +import { Command } from 'commander' |
| 7 | +import walkFiles from '#src/workflows/walk-files.ts' |
| 8 | +import readFrontmatter from '@/frame/lib/read-frontmatter.js' |
| 9 | +import { getKustoClient } from '#src/metrics/lib/kusto-client.js' |
| 10 | +import { getDates } from 'src/metrics/lib/dates.js' |
| 11 | +import { getViews } from '#src/metrics/queries/views.js' |
| 12 | +import { getUsers } from '#src/metrics/queries/users.js' |
| 13 | + |
| 14 | +const __filename = fileURLToPath(import.meta.url) |
| 15 | +const __dirname = path.dirname(__filename) |
| 16 | +const ROOTDIR = process.cwd() |
| 17 | + |
| 18 | +const program = new Command() |
| 19 | + |
| 20 | +program |
| 21 | + .name('docsaudit') |
| 22 | + .description('Get data about a top-level docs product and output a CSV') |
| 23 | + .argument('<auditDir>', 'Name of the content directory you want to audit, e.g., actions') |
| 24 | + .option('-r, --range <days>', 'Number of days to look back', 30) |
| 25 | + .option('--verbose', 'Display Kusto queries being executed') |
| 26 | + .parse(process.argv) |
| 27 | + |
| 28 | +const options = program.opts() |
| 29 | +const [auditDirName] = program.args |
| 30 | +const contentDir = path.join(ROOTDIR, 'content') |
| 31 | +const auditDir = path.join(contentDir, auditDirName) |
| 32 | +const outputFile = path.join(__dirname, `${auditDirName}-audit.csv`) |
| 33 | + |
| 34 | +if (!fs.existsSync(auditDir)) { |
| 35 | + console.error(`${auditDirName} not found`) |
| 36 | + process.exit(1) |
| 37 | +} |
| 38 | + |
| 39 | +// Get dates object in format { endDate, startDate, friendlyRange } |
| 40 | +const dates = getDates(options.range) |
| 41 | + |
| 42 | +const files = walkFiles(auditDir, ['.md']) |
| 43 | +console.log(`Auditing the ${files.length} "${auditDirName}" files. This may take a while.\n`) |
| 44 | + |
| 45 | +main() |
| 46 | + |
| 47 | +async function main() { |
| 48 | + const client = getKustoClient() |
| 49 | + |
| 50 | + let csvString = `title,path,versions,${options.range}d views,${options.range}d users\n` |
| 51 | + console.log(`Assembling data for these CSV columns: ${csvString}`) |
| 52 | + |
| 53 | + // Get the title, path, and versions from the filesystem |
| 54 | + // Get the views and users from the Kusto API |
| 55 | + const results = [] |
| 56 | + for (const file of files) { |
| 57 | + const contents = await fs.promises.readFile(file) |
| 58 | + const contentPath = path.relative(ROOTDIR, file) |
| 59 | + const { data } = readFrontmatter(contents) |
| 60 | + const versionString = JSON.stringify(data.versions).replaceAll('"', "'") |
| 61 | + const pathToQuery = getPathToQuery(file) |
| 62 | + // Pass null to get all versions (the default if no version is provided) |
| 63 | + const version = null |
| 64 | + // Only pass true for verbose on the first iteration |
| 65 | + const isFirst = results.length === 0 |
| 66 | + const views = await getViews(pathToQuery, client, dates, version, options.verbose && isFirst) |
| 67 | + const users = await getUsers(pathToQuery, client, dates, version, options.verbose && isFirst) |
| 68 | + const csvEntry = `"${data.title}","${contentPath}","${versionString}","${views}","${users}"` |
| 69 | + console.log(csvEntry) |
| 70 | + results.push(csvEntry) |
| 71 | + } |
| 72 | + csvString += results.join('\n') + '\n' |
| 73 | + |
| 74 | + fs.writeFileSync(outputFile, csvString.trim(), 'utf8') |
| 75 | + console.log(`Done! Wrote ${outputFile}`) |
| 76 | +} |
| 77 | + |
| 78 | +function getPathToQuery(file) { |
| 79 | + return path.relative(contentDir, file).replace('/index.md', '').replace('.md', '') |
| 80 | +} |
0 commit comments