From cb1866631c4986d2b93195ede03e38f88876a192 Mon Sep 17 00:00:00 2001 From: Luke Hagar Date: Tue, 29 Jul 2025 14:50:30 -0500 Subject: [PATCH] Refactor Usage Statistics Tracker to support multiple package types, removing the config input in favor of specific inputs for npm, GitHub, PyPI, Homebrew, PowerShell, Postman, and Go. Update action.yml, README, and examples to reflect new input structure and enhance documentation. --- INSTALLATION.md | 28 +++++--- README.md | 71 ++++++++++++++------ action.yml | 46 +++++++++++-- examples/basic-usage.yml | 8 ++- examples/input-based-config.yml | 59 +++++++++++++++++ src/action.ts | 99 ++++++++++++++-------------- src/aggregator.ts | 40 +----------- src/config.ts | 112 -------------------------------- src/index.test.ts | 48 ++++++++------ src/index.ts | 96 +++++++++++++-------------- src/types/index.ts | 3 - 11 files changed, 303 insertions(+), 307 deletions(-) create mode 100644 examples/input-based-config.yml delete mode 100644 src/config.ts diff --git a/INSTALLATION.md b/INSTALLATION.md index 458945f..639b73f 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -10,7 +10,13 @@ Add this to your GitHub Actions workflow: - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'stats.json' update-readme: 'true' github-token: ${{ secrets.GITHUB_TOKEN }} @@ -37,7 +43,13 @@ jobs: - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'stats.json' csv-output-path: 'stats.csv' report-output-path: 'docs/usage-report.md' @@ -68,19 +80,17 @@ Last updated: 2025-07-29T18:53:52.619Z - **Unique Packages**: 8 - **Platforms Tracked**: npm, pypi, homebrew, go +### Platform Totals +- **HOMEBREW**: 380,163 downloads (2 packages) +- **NPM**: 34,311 downloads (2 packages) +- **GO**: 33 downloads (2 packages) + ### Top Packages 1. **node** (homebrew) - 226,882 downloads 2. **git** (homebrew) - 153,281 downloads 3. **axios** (npm) - 18,397 downloads 4. **lodash** (npm) - 15,914 downloads 5. **github.com/go-chi/chi** (go) - 33 downloads - -### Recent Activity -- **node** (homebrew) - 226,882 downloads on 7/29/2025 -- **git** (homebrew) - 153,281 downloads on 7/29/2025 -- **axios** (npm) - 722 downloads on 7/29/2025 -- **lodash** (npm) - 857 downloads on 7/29/2025 -- **axios** (npm) - 936 downloads on 7/28/2025 ``` diff --git a/README.md b/README.md index 1d286a0..40edb95 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,13 @@ A comprehensive GitHub Action for tracking download statistics across multiple p - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'stats.json' csv-output-path: 'stats.csv' report-output-path: 'report.md' @@ -50,7 +56,13 @@ bun test | Parameter | Description | Required | Default | |-----------|-------------|----------|---------| -| `config` | Configuration mode or JSON | No | `production` | +| `npm-packages` | Comma-separated list of NPM packages | No | (empty) | +| `github-repositories` | Comma-separated list of GitHub repos (owner/repo) | No | (empty) | +| `pypi-packages` | Comma-separated list of PyPI packages | No | (empty) | +| `homebrew-formulas` | Comma-separated list of Homebrew formulas | No | (empty) | +| `powershell-modules` | Comma-separated list of PowerShell modules | No | (empty) | +| `postman-collections` | Comma-separated list of Postman collection IDs | No | (empty) | +| `go-modules` | Comma-separated list of Go modules | No | (empty) | | `json-output-path` | Path for JSON output | No | `stats.json` | | `csv-output-path` | Path for CSV output | No | (empty) | | `report-output-path` | Path for human-readable report | No | (empty) | @@ -61,30 +73,36 @@ bun test | `commit-message` | Commit message for changes | No | `chore: update usage statistics [skip ci]` | | `preview-mode` | Run with mock data | No | `false` | -### Configuration Modes +### Configuration Examples -#### Production Mode +#### NPM Packages Only ```yaml - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios,react' ``` -#### Development Mode +#### GitHub Repositories Only ```yaml - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'development' + github-repositories: 'microsoft/vscode,facebook/react,vercel/next.js' ``` -#### Custom JSON Configuration +#### Mixed Platform Configuration ```yaml - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: '{"npmPackages": ["lodash", "axios"], "githubRepositories": ["microsoft/vscode"]}' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' ``` ### Outputs @@ -121,7 +139,13 @@ jobs: - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'stats.json' update-readme: 'true' github-token: ${{ secrets.GITHUB_TOKEN }} @@ -141,7 +165,13 @@ jobs: - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios,react' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'data/stats.json' csv-output-path: 'data/stats.csv' report-output-path: 'docs/usage-report.md' @@ -172,7 +202,11 @@ jobs: id: stats uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + powershell-modules: 'PowerShellGet' + postman-collections: '12345' + go-modules: 'github.com/gin-gonic/gin' json-output-path: 'stats.json' - name: Use Statistics Data @@ -198,19 +232,17 @@ Last updated: 2025-07-29T18:53:52.619Z - **Unique Packages**: 8 - **Platforms Tracked**: npm, pypi, homebrew, go +### Platform Totals +- **HOMEBREW**: 380,163 downloads (2 packages) +- **NPM**: 34,311 downloads (2 packages) +- **GO**: 33 downloads (2 packages) + ### Top Packages 1. **node** (homebrew) - 226,882 downloads 2. **git** (homebrew) - 153,281 downloads 3. **axios** (npm) - 18,397 downloads 4. **lodash** (npm) - 15,914 downloads 5. **github.com/go-chi/chi** (go) - 33 downloads - -### Recent Activity -- **node** (homebrew) - 226,882 downloads on 7/29/2025 -- **git** (homebrew) - 153,281 downloads on 7/29/2025 -- **axios** (npm) - 722 downloads on 7/29/2025 -- **lodash** (npm) - 857 downloads on 7/29/2025 -- **axios** (npm) - 936 downloads on 7/28/2025 ``` @@ -246,7 +278,6 @@ usage-statistics/ ├── src/ │ ├── index.ts # Main library entry point │ ├── action.ts # GitHub Action entry point -│ ├── config.ts # Configuration management │ ├── aggregator.ts # Statistics aggregation │ ├── types/ # TypeScript type definitions │ ├── trackers/ # Platform-specific trackers diff --git a/action.yml b/action.yml index 646d30b..7755a2b 100644 --- a/action.yml +++ b/action.yml @@ -3,11 +3,47 @@ description: 'Track download statistics across multiple platforms (NPM, GitHub, author: 'LukeHagar' inputs: - # Configuration - config: - description: 'Configuration for tracking (development, production, test, or custom JSON)' + # NPM Configuration + npm-packages: + description: 'Comma-separated list of NPM packages to track' required: false - default: 'production' + default: '' + + # GitHub Configuration + github-repositories: + description: 'Comma-separated list of GitHub repositories (format: owner/repo)' + required: false + default: '' + + # PyPI Configuration + pypi-packages: + description: 'Comma-separated list of PyPI packages to track' + required: false + default: '' + + # Homebrew Configuration + homebrew-formulas: + description: 'Comma-separated list of Homebrew formulas to track' + required: false + default: '' + + # PowerShell Configuration + powershell-modules: + description: 'Comma-separated list of PowerShell modules to track' + required: false + default: '' + + # Postman Configuration + postman-collections: + description: 'Comma-separated list of Postman collection IDs to track' + required: false + default: '' + + # Go Configuration + go-modules: + description: 'Comma-separated list of Go modules to track' + required: false + default: '' # Output paths json-output-path: @@ -80,4 +116,4 @@ outputs: runs: using: 'node20' - main: 'dist/index.js' \ No newline at end of file + main: 'dist/action.js' \ No newline at end of file diff --git a/examples/basic-usage.yml b/examples/basic-usage.yml index bd877ee..2258134 100644 --- a/examples/basic-usage.yml +++ b/examples/basic-usage.yml @@ -16,7 +16,13 @@ jobs: - name: Usage Statistics Tracker uses: LukeHagar/usage-statistics@v1 with: - config: 'production' + npm-packages: 'lodash,axios' + github-repositories: 'microsoft/vscode,facebook/react' + pypi-packages: 'requests,numpy' + homebrew-formulas: 'git,node' + powershell-modules: 'PowerShellGet,PSReadLine' + postman-collections: '12345,67890' + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' json-output-path: 'stats.json' csv-output-path: 'stats.csv' report-output-path: 'docs/usage-report.md' diff --git a/examples/input-based-config.yml b/examples/input-based-config.yml new file mode 100644 index 0000000..e1892b6 --- /dev/null +++ b/examples/input-based-config.yml @@ -0,0 +1,59 @@ +name: Usage Statistics with Input-Based Configuration + +on: + schedule: + - cron: '0 0 * * *' # Daily at midnight + workflow_dispatch: + +jobs: + update-stats: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Usage Statistics Tracker + uses: LukeHagar/usage-statistics@v1 + with: + # NPM packages to track + npm-packages: 'lodash,axios,react,vue' + + # GitHub repositories to track + github-repositories: 'microsoft/vscode,facebook/react,vercel/next.js' + + # PyPI packages to track + pypi-packages: 'requests,numpy,pandas' + + # Homebrew formulas to track + homebrew-formulas: 'git,node,postgresql' + + # PowerShell modules to track + powershell-modules: 'PowerShellGet,PSReadLine' + + # Go modules to track + go-modules: 'github.com/gin-gonic/gin,github.com/go-chi/chi' + + # Output configuration + json-output-path: 'data/stats.json' + csv-output-path: 'data/stats.csv' + report-output-path: 'docs/usage-report.md' + + # README integration + update-readme: 'true' + readme-path: 'README.md' + + # API tokens + github-token: ${{ secrets.GITHUB_TOKEN }} + postman-api-key: ${{ secrets.POSTMAN_API_KEY }} + + # Commit settings + commit-message: 'feat: update usage statistics with detailed report' + + - name: Commit and push changes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add data/stats.json data/stats.csv docs/usage-report.md README.md + git commit -m "chore: update usage statistics [skip ci]" || echo "No changes to commit" + git push \ No newline at end of file diff --git a/src/action.ts b/src/action.ts index fdb9177..3960f7a 100644 --- a/src/action.ts +++ b/src/action.ts @@ -3,12 +3,19 @@ import * as core from '@actions/core'; import * as fs from 'fs/promises'; import * as path from 'path'; import { UsageStatisticsManager } from './index'; -import { getConfig, validateConfig } from './config'; +import type { TrackingConfig } from './types'; async function run() { try { // Get inputs - const configInput = core.getInput('config'); + const npmPackages = core.getInput('npm-packages'); + const githubRepositories = core.getInput('github-repositories'); + const pypiPackages = core.getInput('pypi-packages'); + const homebrewFormulas = core.getInput('homebrew-formulas'); + const powershellModules = core.getInput('powershell-modules'); + const postmanCollections = core.getInput('postman-collections'); + const goModules = core.getInput('go-modules'); + const jsonOutputPath = core.getInput('json-output-path'); const csvOutputPath = core.getInput('csv-output-path'); const reportOutputPath = core.getInput('report-output-path'); @@ -27,31 +34,35 @@ async function run() { process.env.POSTMAN_API_KEY = postmanApiKey; } - // Get configuration - let trackingConfig; - if (configInput === 'development' || configInput === 'production' || configInput === 'test') { - trackingConfig = getConfig(configInput as 'development' | 'production' | 'test'); - } else { - // Try to parse as JSON - try { - trackingConfig = JSON.parse(configInput); - } catch (error) { - core.setFailed(`Invalid config input: ${configInput}. Must be 'development', 'production', 'test', or valid JSON.`); - return; - } - } + // Build configuration from inputs + const trackingConfig: TrackingConfig = { + enableLogging: true, + updateInterval: 60 * 60 * 1000, // 1 hour + npmPackages: npmPackages ? npmPackages.split(',').map(p => p.trim()).filter(p => p) : [], + githubRepos: githubRepositories ? githubRepositories.split(',').map(r => r.trim()).filter(r => r) : [], + pythonPackages: pypiPackages ? pypiPackages.split(',').map(p => p.trim()).filter(p => p) : [], + homebrewPackages: homebrewFormulas ? homebrewFormulas.split(',').map(f => f.trim()).filter(f => f) : [], + powershellModules: powershellModules ? powershellModules.split(',').map(m => m.trim()).filter(m => m) : [], + postmanCollections: postmanCollections ? postmanCollections.split(',').map(c => c.trim()).filter(c => c) : [], + goModules: goModules ? goModules.split(',').map(m => m.trim()).filter(m => m) : [] + }; - // Validate configuration - try { - validateConfig(trackingConfig); - } catch (error) { - core.setFailed(`Configuration validation failed: ${error}`); - return; + // Validate that at least one platform has packages configured + const totalPackages = (trackingConfig.npmPackages?.length || 0) + + (trackingConfig.githubRepos?.length || 0) + + (trackingConfig.pythonPackages?.length || 0) + + (trackingConfig.homebrewPackages?.length || 0) + + (trackingConfig.powershellModules?.length || 0) + + (trackingConfig.postmanCollections?.length || 0) + + (trackingConfig.goModules?.length || 0); + + if (totalPackages === 0 && !previewMode) { + core.warning('No packages configured for tracking. Consider adding packages to track or enabling preview mode.'); } // Create manager const manager = new UsageStatisticsManager(trackingConfig); - + // Generate report let report; if (previewMode) { @@ -61,10 +72,10 @@ async function run() { core.info('📊 Generating comprehensive usage statistics report...'); report = await manager.generateComprehensiveReport(); } - + // Display report await manager.displayReport(report); - + // Write JSON output if (jsonOutputPath) { const jsonContent = JSON.stringify(report, null, 2); @@ -112,36 +123,28 @@ async function run() { } async function generateHumanReadableReport(report: any): Promise { - let content = '# Usage Statistics Report\n\n'; + let content = '# Usage Statistics Summary\n\n'; content += `Generated on: ${new Date().toISOString()}\n\n`; - // Summary - content += '## Summary\n\n'; + // Overall Summary + content += '## Overall Summary\n\n'; content += `- **Total Downloads**: ${report.totalDownloads.toLocaleString()}\n`; content += `- **Unique Packages**: ${report.uniquePackages}\n`; content += `- **Platforms Tracked**: ${report.platforms.join(', ')}\n\n`; - // Platform Breakdown - content += '## Platform Breakdown\n\n'; + // Platform Totals + content += '## Platform Totals\n\n'; for (const [platform, data] of Object.entries(report.platformBreakdown)) { content += `### ${platform.toUpperCase()}\n`; - content += `- Downloads: ${data.totalDownloads.toLocaleString()}\n`; - content += `- Packages: ${data.uniquePackages}\n`; - content += `- Package List: ${data.packages.join(', ')}\n\n`; + content += `- **Downloads**: ${data.totalDownloads.toLocaleString()}\n`; + content += `- **Packages**: ${data.uniquePackages}\n\n`; } - // Top Packages - content += '## Top Packages\n\n'; - report.topPackages.slice(0, 10).forEach((pkg: any, index: number) => { + // Package Rankings + content += '## Package Rankings\n\n'; + report.topPackages.forEach((pkg: any, index: number) => { content += `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads\n`; }); - content += '\n'; - - // Recent Activity - content += '## Recent Activity\n\n'; - report.recentActivity.slice(0, 5).forEach((activity: any) => { - content += `- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}\n`; - }); return content; } @@ -163,14 +166,14 @@ Last updated: ${new Date().toISOString()} - **Unique Packages**: ${report.uniquePackages} - **Platforms Tracked**: ${report.platforms.join(', ')} -### Top Packages -${report.topPackages.slice(0, 10).map((pkg: any, index: number) => - `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads` +### Platform Totals +${Object.entries(report.platformBreakdown).map(([platform, data]: [string, any]) => + `- **${platform.toUpperCase()}**: ${data.totalDownloads.toLocaleString()} downloads (${data.uniquePackages} packages)` ).join('\n')} -### Recent Activity -${report.recentActivity.slice(0, 5).map((activity: any) => - `- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}` +### Top Packages +${report.topPackages.map((pkg: any, index: number) => + `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads` ).join('\n')} `; diff --git a/src/aggregator.ts b/src/aggregator.ts index 448f7b4..c8a16ec 100644 --- a/src/aggregator.ts +++ b/src/aggregator.ts @@ -17,7 +17,6 @@ export interface AggregatedStats { totalDownloads: number; uniquePackages: number; platforms: string[]; - timeRange: { start: Date; end: Date } | null; platformBreakdown: Record; - recentActivity: Array<{ - packageName: string; - platform: string; - downloads: number; - timestamp: Date; - }>; } export class DownloadStatsAggregator implements DownloadStatsAggregator { @@ -64,17 +57,10 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator { }> = {}; const packageMap = new Map(); - const recentActivity: Array<{ - packageName: string; - platform: string; - downloads: number; - timestamp: Date; - }> = []; let totalDownloads = 0; let uniquePackages = 0; const platforms = new Set(); - const timeRange = { start: new Date(), end: new Date(0) }; // Process each stat for (const stat of stats) { @@ -104,27 +90,8 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator { platformBreakdown[stat.platform].packages.push(stat.packageName); platformBreakdown[stat.platform].uniquePackages++; } - - // Track recent activity - recentActivity.push({ - packageName: stat.packageName, - platform: stat.platform, - downloads: stat.downloadCount, - timestamp: stat.timestamp - }); - - // Update time range - if (stat.timestamp < timeRange.start) { - timeRange.start = stat.timestamp; - } - if (stat.timestamp > timeRange.end) { - timeRange.end = stat.timestamp; - } } - // Sort recent activity by timestamp - recentActivity.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime()); - // Get top packages const topPackages = Array.from(packageMap.entries()) .map(([key, data]) => ({ @@ -132,17 +99,14 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator { platform: data.platform, downloads: data.downloads })) - .sort((a, b) => b.downloads - a.downloads) - .slice(0, 10); + .sort((a, b) => b.downloads - a.downloads); return { totalDownloads, uniquePackages, platforms: Array.from(platforms), - timeRange: timeRange.start < timeRange.end ? timeRange : null, platformBreakdown, - topPackages, - recentActivity: recentActivity.slice(0, 20) + topPackages }; } diff --git a/src/config.ts b/src/config.ts deleted file mode 100644 index 219b79e..0000000 --- a/src/config.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Configuration for usage statistics tracking - * Customize this file to track your specific packages and tools - */ - -import type { TrackingConfig } from './types'; - -export const defaultConfig: TrackingConfig = { - // NPM packages - Add your NPM package names here - npmPackages: [ - 'lodash', - 'axios' - ], - - // GitHub repositories - Format: 'owner/repo' - githubRepos: [ - 'microsoft/vscode', - 'facebook/react' - ], - - // PyPI packages - Add your Python package names here - pythonPackages: [ - 'requests', - 'numpy' - ], - - // Homebrew formulae - Add your Homebrew package names here - homebrewPackages: [ - 'git', - 'node' - ], - - // PowerShell modules - Add your PowerShell module names here - powershellModules: [ - 'PowerShellGet' - ], - - // Postman collections - Add your Postman collection IDs here - postmanCollections: [ - // Note: These are example IDs - replace with real collection IDs - // For testing, we'll leave these empty to avoid errors - ], - - // Go modules - Add your Go module paths here - goModules: [ - 'github.com/gin-gonic/gin', - 'github.com/go-chi/chi' - ], - - // Update interval in milliseconds (default: 1 hour) - updateInterval: 60 * 60 * 1000, - - // Enable detailed logging - enableLogging: true -}; - -// Test configuration with minimal packages -export const testConfig: TrackingConfig = { - npmPackages: ['lodash'], - githubRepos: [], - pythonPackages: ['requests'], - homebrewPackages: ['git'], - powershellModules: [], - postmanCollections: [], - goModules: [], - updateInterval: 60 * 60 * 1000, - enableLogging: false -}; - -// Environment-specific configurations -export const developmentConfig: TrackingConfig = { - ...defaultConfig, - enableLogging: true, - updateInterval: 5 * 60 * 1000, // 5 minutes for development -}; - -export const productionConfig: TrackingConfig = { - ...defaultConfig, - enableLogging: false, - updateInterval: 60 * 60 * 1000, // 1 hour for production -}; - -// Helper function to get configuration based on environment -export function getConfig(environment: 'development' | 'production' | 'default' | 'test' = 'default'): TrackingConfig { - switch (environment) { - case 'development': - return developmentConfig; - case 'production': - return productionConfig; - case 'test': - return testConfig; - default: - return defaultConfig; - } -} - -// Helper function to validate configuration -export function validateConfig(config: TrackingConfig): string[] { - const errors: string[] = []; - - if (!config.npmPackages && !config.githubRepos && !config.pythonPackages && - !config.homebrewPackages && !config.powershellModules && - !config.postmanCollections && !config.goModules) { - errors.push('No packages configured for tracking. Please add packages to at least one platform.'); - } - - if (config.updateInterval && config.updateInterval < 60000) { - errors.push('Update interval should be at least 60 seconds to avoid rate limiting.'); - } - - return errors; -} \ No newline at end of file diff --git a/src/index.test.ts b/src/index.test.ts index 38bd939..a7111a1 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,12 +1,22 @@ import { describe, it, expect, beforeEach } from "bun:test"; import { UsageStatisticsManager } from "./index"; -import { getConfig } from "./config"; +import type { TrackingConfig } from "./types"; describe("UsageStatisticsManager", () => { let manager: UsageStatisticsManager; beforeEach(() => { - const config = getConfig('test'); + const config: TrackingConfig = { + enableLogging: true, + updateInterval: 60 * 60 * 1000, + npmPackages: ['lodash', 'axios'], + githubRepos: ['microsoft/vscode', 'facebook/react'], + pythonPackages: ['requests', 'numpy'], + homebrewPackages: ['git', 'node'], + powershellModules: ['PowerShellGet'], + postmanCollections: [], + goModules: ['github.com/gin-gonic/gin', 'github.com/go-chi/chi'] + }; manager = new UsageStatisticsManager(config); }); @@ -19,7 +29,7 @@ describe("UsageStatisticsManager", () => { expect(report.uniquePackages).toBeGreaterThanOrEqual(0); expect(Array.isArray(report.platforms)).toBe(true); expect(Array.isArray(report.topPackages)).toBe(true); - expect(Array.isArray(report.recentActivity)).toBe(true); + expect(report.topPackages.length).toBeGreaterThan(0); expect(typeof report.platformBreakdown).toBe('object'); }, 30000); // 30 second timeout }); @@ -72,27 +82,23 @@ describe("UsageStatisticsManager", () => { }); describe("Configuration", () => { - it("should load development config", () => { - const config = getConfig('development'); - - expect(config).toBeDefined(); - expect(config.enableLogging).toBe(true); - expect(config.updateInterval).toBe(5 * 60 * 1000); // 5 minutes - }); - - it("should load production config", () => { - const config = getConfig('production'); - - expect(config).toBeDefined(); - expect(config.enableLogging).toBe(false); - expect(config.updateInterval).toBe(60 * 60 * 1000); // 1 hour - }); - - it("should load default config", () => { - const config = getConfig('default'); + it("should create valid config", () => { + const config: TrackingConfig = { + enableLogging: true, + updateInterval: 60 * 60 * 1000, + npmPackages: ['lodash', 'axios'], + githubRepos: ['microsoft/vscode'], + pythonPackages: ['requests'], + homebrewPackages: ['git'], + powershellModules: ['PowerShellGet'], + postmanCollections: [], + goModules: ['github.com/gin-gonic/gin'] + }; expect(config).toBeDefined(); expect(config.enableLogging).toBe(true); expect(config.updateInterval).toBe(60 * 60 * 1000); // 1 hour + expect(config.npmPackages).toContain('lodash'); + expect(config.githubRepos).toContain('microsoft/vscode'); }); }); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index a92dcc8..138288f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,6 @@ import type { TrackingConfig } from './types'; import { DownloadStatsAggregator } from './aggregator'; import type { AggregatedStats } from './aggregator'; -import { getConfig, validateConfig } from './config'; import { promises as fs } from 'fs'; import path from 'path'; import { execSync } from 'node:child_process'; @@ -45,14 +44,9 @@ Last updated: ${new Date().toISOString()} - **Platforms Tracked**: ${stats.platforms.join(', ')} ### Top Packages -${stats.topPackages.slice(0, 10).map((pkg, index) => +${stats.topPackages.map((pkg, index) => `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads` ).join('\n')} - -### Recent Activity -${stats.recentActivity.slice(0, 5).map(activity => - `- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}` -).join('\n')} `; const startMarker = readmeContent.indexOf(STATS_MARKER_START); @@ -80,8 +74,6 @@ async function gitCommitAndPush(files: string[], message: string) { execSync(`git push`); } -const trackingConfig: TrackingConfig = getConfig(process.env.NODE_ENV as 'development' | 'production' || 'default'); - class UsageStatisticsManager { private aggregator: DownloadStatsAggregator; private lastUpdateTime: Date | null = null; @@ -110,9 +102,9 @@ class UsageStatisticsManager { const report = await this.generateComprehensiveReport(); if (format === 'csv') { - const csvHeader = 'Platform,Package,Downloads,Last Updated\n'; + const csvHeader = 'Platform,Package,Downloads\n'; const csvRows = report.topPackages.map(pkg => - `${pkg.platform},${pkg.name},${pkg.downloads},${new Date().toISOString()}` + `${pkg.platform},${pkg.name},${pkg.downloads}` ).join('\n'); return csvHeader + csvRows; } @@ -125,36 +117,27 @@ class UsageStatisticsManager { } async displayReport(report: AggregatedStats) { - console.log('🚀 Usage Statistics Report'); + console.log('📊 Usage Statistics Summary'); console.log('==================================================\n'); - console.log('📈 Summary:'); + // Overall Summary + console.log('📈 Overall Summary:'); console.log(`Total Downloads: ${report.totalDownloads.toLocaleString()}`); console.log(`Unique Packages: ${report.uniquePackages}`); - console.log(`Platforms Tracked: ${report.platforms.join(', ')}`); - if (report.timeRange) { - console.log(`Time Range: ${report.timeRange.start.toLocaleDateString()} to ${report.timeRange.end.toLocaleDateString()}\n`); - } + console.log(`Platforms Tracked: ${report.platforms.join(', ')}\n`); - console.log('🏗️ Platform Breakdown:'); + // Platform Totals + console.log('🏗️ Platform Totals:'); for (const [platform, data] of Object.entries(report.platformBreakdown)) { - console.log(` ${platform.toUpperCase()}:`); - console.log(` Downloads: ${data.totalDownloads.toLocaleString()}`); - console.log(` Packages: ${data.uniquePackages}`); - console.log(` Package List: ${data.packages.join(', ')}`); + console.log(` ${platform.toUpperCase()}: ${data.totalDownloads.toLocaleString()} downloads (${data.uniquePackages} packages)`); } - console.log(); + console.log(''); - console.log('🏆 Top Packages:'); - report.topPackages.slice(0, 10).forEach((pkg, index) => { + // Package Rankings + console.log('🏆 Package Rankings:'); + report.topPackages.forEach((pkg, index) => { console.log(` ${index + 1}. ${pkg.name} (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`); }); - console.log(); - - console.log('🕒 Recent Activity:'); - report.recentActivity.slice(0, 5).forEach(activity => { - console.log(` ${activity.packageName} (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}`); - }); console.log('=================================================='); } @@ -167,41 +150,49 @@ class UsageStatisticsManager { platform: 'npm', packageName: 'lodash', downloadCount: 1500000, - timestamp: new Date(), - period: 'total' as const, metadata: { version: '4.17.21' } }, { platform: 'npm', packageName: 'axios', downloadCount: 800000, - timestamp: new Date(), - period: 'total' as const, metadata: { version: '1.6.0' } }, { platform: 'github', packageName: 'microsoft/vscode', downloadCount: 500000, - timestamp: new Date(), - period: 'total' as const, metadata: { release: 'v1.85.0' } }, { platform: 'pypi', packageName: 'requests', downloadCount: 300000, - timestamp: new Date(), - period: 'total' as const, metadata: { version: '2.31.0' } }, { platform: 'homebrew', packageName: 'git', downloadCount: 250000, - timestamp: new Date(), - period: 'total' as const, metadata: { version: '2.43.0' } + }, + { + platform: 'powershell', + packageName: 'PowerShellGet', + downloadCount: 120000, + metadata: { version: '2.2.5' } + }, + { + platform: 'postman', + packageName: 'Postman Collection', + downloadCount: 75000, + metadata: { collectionId: '12345' } + }, + { + platform: 'go', + packageName: 'github.com/gin-gonic/gin', + downloadCount: 45000, + metadata: { version: 'v1.9.1' } } ]; @@ -214,15 +205,20 @@ class UsageStatisticsManager { async function main() { console.log('🚀 Usage Statistics Tracker Starting...\n'); - // Validate configuration - try { - validateConfig(trackingConfig); - } catch (error) { - console.error('❌ Configuration validation failed:', error); - process.exit(1); - } + // Create a default configuration for CLI usage + const defaultConfig: TrackingConfig = { + enableLogging: true, + updateInterval: 60 * 60 * 1000, // 1 hour + npmPackages: ['lodash', 'axios'], + githubRepos: ['microsoft/vscode', 'facebook/react'], + pythonPackages: ['requests', 'numpy'], + homebrewPackages: ['git', 'node'], + powershellModules: ['PowerShellGet'], + postmanCollections: [], + goModules: ['github.com/gin-gonic/gin', 'github.com/go-chi/chi'] + }; - const manager = new UsageStatisticsManager(trackingConfig); + const manager = new UsageStatisticsManager(defaultConfig); try { // Check for preview mode @@ -263,4 +259,4 @@ if (import.meta.main) { main(); } -export { UsageStatisticsManager, trackingConfig }; \ No newline at end of file +export { UsageStatisticsManager }; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index 4dde74d..44763ec 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,8 +7,6 @@ export interface BaseDownloadStats { packageName: string; version?: string; downloadCount: number; - timestamp: Date; - period?: 'daily' | 'weekly' | 'monthly' | 'total'; metadata?: Record; } @@ -24,7 +22,6 @@ export interface DownloadStatsAggregator { totalDownloads: number; uniquePackages: number; platforms: string[]; - timeRange: { start: Date; end: Date } | null; }; }