mirror of
https://github.com/LukeHagar/usage-statistics.git
synced 2025-12-06 04:21:55 +00:00
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.
This commit is contained in:
@@ -10,7 +10,13 @@ Add this to your GitHub Actions workflow:
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
update-readme: 'true'
|
update-readme: 'true'
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -37,7 +43,13 @@ jobs:
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
csv-output-path: 'stats.csv'
|
csv-output-path: 'stats.csv'
|
||||||
report-output-path: 'docs/usage-report.md'
|
report-output-path: 'docs/usage-report.md'
|
||||||
@@ -68,19 +80,17 @@ Last updated: 2025-07-29T18:53:52.619Z
|
|||||||
- **Unique Packages**: 8
|
- **Unique Packages**: 8
|
||||||
- **Platforms Tracked**: npm, pypi, homebrew, go
|
- **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
|
### Top Packages
|
||||||
1. **node** (homebrew) - 226,882 downloads
|
1. **node** (homebrew) - 226,882 downloads
|
||||||
2. **git** (homebrew) - 153,281 downloads
|
2. **git** (homebrew) - 153,281 downloads
|
||||||
3. **axios** (npm) - 18,397 downloads
|
3. **axios** (npm) - 18,397 downloads
|
||||||
4. **lodash** (npm) - 15,914 downloads
|
4. **lodash** (npm) - 15,914 downloads
|
||||||
5. **github.com/go-chi/chi** (go) - 33 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
|
|
||||||
<!-- USAGE_STATS_END -->
|
<!-- USAGE_STATS_END -->
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
71
README.md
71
README.md
@@ -20,7 +20,13 @@ A comprehensive GitHub Action for tracking download statistics across multiple p
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
csv-output-path: 'stats.csv'
|
csv-output-path: 'stats.csv'
|
||||||
report-output-path: 'report.md'
|
report-output-path: 'report.md'
|
||||||
@@ -50,7 +56,13 @@ bun test
|
|||||||
|
|
||||||
| Parameter | Description | Required | Default |
|
| 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` |
|
| `json-output-path` | Path for JSON output | No | `stats.json` |
|
||||||
| `csv-output-path` | Path for CSV output | No | (empty) |
|
| `csv-output-path` | Path for CSV output | No | (empty) |
|
||||||
| `report-output-path` | Path for human-readable report | 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]` |
|
| `commit-message` | Commit message for changes | No | `chore: update usage statistics [skip ci]` |
|
||||||
| `preview-mode` | Run with mock data | No | `false` |
|
| `preview-mode` | Run with mock data | No | `false` |
|
||||||
|
|
||||||
### Configuration Modes
|
### Configuration Examples
|
||||||
|
|
||||||
#### Production Mode
|
#### NPM Packages Only
|
||||||
```yaml
|
```yaml
|
||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
with:
|
||||||
config: 'production'
|
npm-packages: 'lodash,axios,react'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Development Mode
|
#### GitHub Repositories Only
|
||||||
```yaml
|
```yaml
|
||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
with:
|
||||||
config: 'development'
|
github-repositories: 'microsoft/vscode,facebook/react,vercel/next.js'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Custom JSON Configuration
|
#### Mixed Platform Configuration
|
||||||
```yaml
|
```yaml
|
||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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
|
### Outputs
|
||||||
@@ -121,7 +139,13 @@ jobs:
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
update-readme: 'true'
|
update-readme: 'true'
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -141,7 +165,13 @@ jobs:
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'data/stats.json'
|
||||||
csv-output-path: 'data/stats.csv'
|
csv-output-path: 'data/stats.csv'
|
||||||
report-output-path: 'docs/usage-report.md'
|
report-output-path: 'docs/usage-report.md'
|
||||||
@@ -172,7 +202,11 @@ jobs:
|
|||||||
id: stats
|
id: stats
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
|
|
||||||
- name: Use Statistics Data
|
- name: Use Statistics Data
|
||||||
@@ -198,19 +232,17 @@ Last updated: 2025-07-29T18:53:52.619Z
|
|||||||
- **Unique Packages**: 8
|
- **Unique Packages**: 8
|
||||||
- **Platforms Tracked**: npm, pypi, homebrew, go
|
- **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
|
### Top Packages
|
||||||
1. **node** (homebrew) - 226,882 downloads
|
1. **node** (homebrew) - 226,882 downloads
|
||||||
2. **git** (homebrew) - 153,281 downloads
|
2. **git** (homebrew) - 153,281 downloads
|
||||||
3. **axios** (npm) - 18,397 downloads
|
3. **axios** (npm) - 18,397 downloads
|
||||||
4. **lodash** (npm) - 15,914 downloads
|
4. **lodash** (npm) - 15,914 downloads
|
||||||
5. **github.com/go-chi/chi** (go) - 33 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
|
|
||||||
<!-- USAGE_STATS_END -->
|
<!-- USAGE_STATS_END -->
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -246,7 +278,6 @@ usage-statistics/
|
|||||||
├── src/
|
├── src/
|
||||||
│ ├── index.ts # Main library entry point
|
│ ├── index.ts # Main library entry point
|
||||||
│ ├── action.ts # GitHub Action entry point
|
│ ├── action.ts # GitHub Action entry point
|
||||||
│ ├── config.ts # Configuration management
|
|
||||||
│ ├── aggregator.ts # Statistics aggregation
|
│ ├── aggregator.ts # Statistics aggregation
|
||||||
│ ├── types/ # TypeScript type definitions
|
│ ├── types/ # TypeScript type definitions
|
||||||
│ ├── trackers/ # Platform-specific trackers
|
│ ├── trackers/ # Platform-specific trackers
|
||||||
|
|||||||
46
action.yml
46
action.yml
@@ -3,11 +3,47 @@ description: 'Track download statistics across multiple platforms (NPM, GitHub,
|
|||||||
author: 'LukeHagar'
|
author: 'LukeHagar'
|
||||||
|
|
||||||
inputs:
|
inputs:
|
||||||
# Configuration
|
# NPM Configuration
|
||||||
config:
|
npm-packages:
|
||||||
description: 'Configuration for tracking (development, production, test, or custom JSON)'
|
description: 'Comma-separated list of NPM packages to track'
|
||||||
required: false
|
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
|
# Output paths
|
||||||
json-output-path:
|
json-output-path:
|
||||||
@@ -80,4 +116,4 @@ outputs:
|
|||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: 'dist/index.js'
|
main: 'dist/action.js'
|
||||||
@@ -16,7 +16,13 @@ jobs:
|
|||||||
- name: Usage Statistics Tracker
|
- name: Usage Statistics Tracker
|
||||||
uses: LukeHagar/usage-statistics@v1
|
uses: LukeHagar/usage-statistics@v1
|
||||||
with:
|
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'
|
json-output-path: 'stats.json'
|
||||||
csv-output-path: 'stats.csv'
|
csv-output-path: 'stats.csv'
|
||||||
report-output-path: 'docs/usage-report.md'
|
report-output-path: 'docs/usage-report.md'
|
||||||
|
|||||||
59
examples/input-based-config.yml
Normal file
59
examples/input-based-config.yml
Normal file
@@ -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
|
||||||
@@ -3,12 +3,19 @@ import * as core from '@actions/core';
|
|||||||
import * as fs from 'fs/promises';
|
import * as fs from 'fs/promises';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { UsageStatisticsManager } from './index';
|
import { UsageStatisticsManager } from './index';
|
||||||
import { getConfig, validateConfig } from './config';
|
import type { TrackingConfig } from './types';
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
// Get inputs
|
// 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 jsonOutputPath = core.getInput('json-output-path');
|
||||||
const csvOutputPath = core.getInput('csv-output-path');
|
const csvOutputPath = core.getInput('csv-output-path');
|
||||||
const reportOutputPath = core.getInput('report-output-path');
|
const reportOutputPath = core.getInput('report-output-path');
|
||||||
@@ -27,31 +34,35 @@ async function run() {
|
|||||||
process.env.POSTMAN_API_KEY = postmanApiKey;
|
process.env.POSTMAN_API_KEY = postmanApiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get configuration
|
// Build configuration from inputs
|
||||||
let trackingConfig;
|
const trackingConfig: TrackingConfig = {
|
||||||
if (configInput === 'development' || configInput === 'production' || configInput === 'test') {
|
enableLogging: true,
|
||||||
trackingConfig = getConfig(configInput as 'development' | 'production' | 'test');
|
updateInterval: 60 * 60 * 1000, // 1 hour
|
||||||
} else {
|
npmPackages: npmPackages ? npmPackages.split(',').map(p => p.trim()).filter(p => p) : [],
|
||||||
// Try to parse as JSON
|
githubRepos: githubRepositories ? githubRepositories.split(',').map(r => r.trim()).filter(r => r) : [],
|
||||||
try {
|
pythonPackages: pypiPackages ? pypiPackages.split(',').map(p => p.trim()).filter(p => p) : [],
|
||||||
trackingConfig = JSON.parse(configInput);
|
homebrewPackages: homebrewFormulas ? homebrewFormulas.split(',').map(f => f.trim()).filter(f => f) : [],
|
||||||
} catch (error) {
|
powershellModules: powershellModules ? powershellModules.split(',').map(m => m.trim()).filter(m => m) : [],
|
||||||
core.setFailed(`Invalid config input: ${configInput}. Must be 'development', 'production', 'test', or valid JSON.`);
|
postmanCollections: postmanCollections ? postmanCollections.split(',').map(c => c.trim()).filter(c => c) : [],
|
||||||
return;
|
goModules: goModules ? goModules.split(',').map(m => m.trim()).filter(m => m) : []
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Validate configuration
|
// Validate that at least one platform has packages configured
|
||||||
try {
|
const totalPackages = (trackingConfig.npmPackages?.length || 0) +
|
||||||
validateConfig(trackingConfig);
|
(trackingConfig.githubRepos?.length || 0) +
|
||||||
} catch (error) {
|
(trackingConfig.pythonPackages?.length || 0) +
|
||||||
core.setFailed(`Configuration validation failed: ${error}`);
|
(trackingConfig.homebrewPackages?.length || 0) +
|
||||||
return;
|
(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
|
// Create manager
|
||||||
const manager = new UsageStatisticsManager(trackingConfig);
|
const manager = new UsageStatisticsManager(trackingConfig);
|
||||||
|
|
||||||
// Generate report
|
// Generate report
|
||||||
let report;
|
let report;
|
||||||
if (previewMode) {
|
if (previewMode) {
|
||||||
@@ -61,10 +72,10 @@ async function run() {
|
|||||||
core.info('📊 Generating comprehensive usage statistics report...');
|
core.info('📊 Generating comprehensive usage statistics report...');
|
||||||
report = await manager.generateComprehensiveReport();
|
report = await manager.generateComprehensiveReport();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display report
|
// Display report
|
||||||
await manager.displayReport(report);
|
await manager.displayReport(report);
|
||||||
|
|
||||||
// Write JSON output
|
// Write JSON output
|
||||||
if (jsonOutputPath) {
|
if (jsonOutputPath) {
|
||||||
const jsonContent = JSON.stringify(report, null, 2);
|
const jsonContent = JSON.stringify(report, null, 2);
|
||||||
@@ -112,36 +123,28 @@ async function run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function generateHumanReadableReport(report: any): Promise<string> {
|
async function generateHumanReadableReport(report: any): Promise<string> {
|
||||||
let content = '# Usage Statistics Report\n\n';
|
let content = '# Usage Statistics Summary\n\n';
|
||||||
content += `Generated on: ${new Date().toISOString()}\n\n`;
|
content += `Generated on: ${new Date().toISOString()}\n\n`;
|
||||||
|
|
||||||
// Summary
|
// Overall Summary
|
||||||
content += '## Summary\n\n';
|
content += '## Overall Summary\n\n';
|
||||||
content += `- **Total Downloads**: ${report.totalDownloads.toLocaleString()}\n`;
|
content += `- **Total Downloads**: ${report.totalDownloads.toLocaleString()}\n`;
|
||||||
content += `- **Unique Packages**: ${report.uniquePackages}\n`;
|
content += `- **Unique Packages**: ${report.uniquePackages}\n`;
|
||||||
content += `- **Platforms Tracked**: ${report.platforms.join(', ')}\n\n`;
|
content += `- **Platforms Tracked**: ${report.platforms.join(', ')}\n\n`;
|
||||||
|
|
||||||
// Platform Breakdown
|
// Platform Totals
|
||||||
content += '## Platform Breakdown\n\n';
|
content += '## Platform Totals\n\n';
|
||||||
for (const [platform, data] of Object.entries(report.platformBreakdown)) {
|
for (const [platform, data] of Object.entries(report.platformBreakdown)) {
|
||||||
content += `### ${platform.toUpperCase()}\n`;
|
content += `### ${platform.toUpperCase()}\n`;
|
||||||
content += `- Downloads: ${data.totalDownloads.toLocaleString()}\n`;
|
content += `- **Downloads**: ${data.totalDownloads.toLocaleString()}\n`;
|
||||||
content += `- Packages: ${data.uniquePackages}\n`;
|
content += `- **Packages**: ${data.uniquePackages}\n\n`;
|
||||||
content += `- Package List: ${data.packages.join(', ')}\n\n`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top Packages
|
// Package Rankings
|
||||||
content += '## Top Packages\n\n';
|
content += '## Package Rankings\n\n';
|
||||||
report.topPackages.slice(0, 10).forEach((pkg: any, index: number) => {
|
report.topPackages.forEach((pkg: any, index: number) => {
|
||||||
content += `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads\n`;
|
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;
|
return content;
|
||||||
}
|
}
|
||||||
@@ -163,14 +166,14 @@ Last updated: ${new Date().toISOString()}
|
|||||||
- **Unique Packages**: ${report.uniquePackages}
|
- **Unique Packages**: ${report.uniquePackages}
|
||||||
- **Platforms Tracked**: ${report.platforms.join(', ')}
|
- **Platforms Tracked**: ${report.platforms.join(', ')}
|
||||||
|
|
||||||
### Top Packages
|
### Platform Totals
|
||||||
${report.topPackages.slice(0, 10).map((pkg: any, index: number) =>
|
${Object.entries(report.platformBreakdown).map(([platform, data]: [string, any]) =>
|
||||||
`${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`
|
`- **${platform.toUpperCase()}**: ${data.totalDownloads.toLocaleString()} downloads (${data.uniquePackages} packages)`
|
||||||
).join('\n')}
|
).join('\n')}
|
||||||
|
|
||||||
### Recent Activity
|
### Top Packages
|
||||||
${report.recentActivity.slice(0, 5).map((activity: any) =>
|
${report.topPackages.map((pkg: any, index: number) =>
|
||||||
`- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}`
|
`${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`
|
||||||
).join('\n')}
|
).join('\n')}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export interface AggregatedStats {
|
|||||||
totalDownloads: number;
|
totalDownloads: number;
|
||||||
uniquePackages: number;
|
uniquePackages: number;
|
||||||
platforms: string[];
|
platforms: string[];
|
||||||
timeRange: { start: Date; end: Date } | null;
|
|
||||||
platformBreakdown: Record<string, {
|
platformBreakdown: Record<string, {
|
||||||
totalDownloads: number;
|
totalDownloads: number;
|
||||||
uniquePackages: number;
|
uniquePackages: number;
|
||||||
@@ -28,12 +27,6 @@ export interface AggregatedStats {
|
|||||||
platform: string;
|
platform: string;
|
||||||
downloads: number;
|
downloads: number;
|
||||||
}>;
|
}>;
|
||||||
recentActivity: Array<{
|
|
||||||
packageName: string;
|
|
||||||
platform: string;
|
|
||||||
downloads: number;
|
|
||||||
timestamp: Date;
|
|
||||||
}>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DownloadStatsAggregator implements DownloadStatsAggregator {
|
export class DownloadStatsAggregator implements DownloadStatsAggregator {
|
||||||
@@ -64,17 +57,10 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator {
|
|||||||
}> = {};
|
}> = {};
|
||||||
|
|
||||||
const packageMap = new Map<string, { downloads: number; platform: string }>();
|
const packageMap = new Map<string, { downloads: number; platform: string }>();
|
||||||
const recentActivity: Array<{
|
|
||||||
packageName: string;
|
|
||||||
platform: string;
|
|
||||||
downloads: number;
|
|
||||||
timestamp: Date;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
let totalDownloads = 0;
|
let totalDownloads = 0;
|
||||||
let uniquePackages = 0;
|
let uniquePackages = 0;
|
||||||
const platforms = new Set<string>();
|
const platforms = new Set<string>();
|
||||||
const timeRange = { start: new Date(), end: new Date(0) };
|
|
||||||
|
|
||||||
// Process each stat
|
// Process each stat
|
||||||
for (const stat of stats) {
|
for (const stat of stats) {
|
||||||
@@ -104,27 +90,8 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator {
|
|||||||
platformBreakdown[stat.platform].packages.push(stat.packageName);
|
platformBreakdown[stat.platform].packages.push(stat.packageName);
|
||||||
platformBreakdown[stat.platform].uniquePackages++;
|
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
|
// Get top packages
|
||||||
const topPackages = Array.from(packageMap.entries())
|
const topPackages = Array.from(packageMap.entries())
|
||||||
.map(([key, data]) => ({
|
.map(([key, data]) => ({
|
||||||
@@ -132,17 +99,14 @@ export class DownloadStatsAggregator implements DownloadStatsAggregator {
|
|||||||
platform: data.platform,
|
platform: data.platform,
|
||||||
downloads: data.downloads
|
downloads: data.downloads
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => b.downloads - a.downloads)
|
.sort((a, b) => b.downloads - a.downloads);
|
||||||
.slice(0, 10);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalDownloads,
|
totalDownloads,
|
||||||
uniquePackages,
|
uniquePackages,
|
||||||
platforms: Array.from(platforms),
|
platforms: Array.from(platforms),
|
||||||
timeRange: timeRange.start < timeRange.end ? timeRange : null,
|
|
||||||
platformBreakdown,
|
platformBreakdown,
|
||||||
topPackages,
|
topPackages
|
||||||
recentActivity: recentActivity.slice(0, 20)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
112
src/config.ts
112
src/config.ts
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,22 @@
|
|||||||
import { describe, it, expect, beforeEach } from "bun:test";
|
import { describe, it, expect, beforeEach } from "bun:test";
|
||||||
import { UsageStatisticsManager } from "./index";
|
import { UsageStatisticsManager } from "./index";
|
||||||
import { getConfig } from "./config";
|
import type { TrackingConfig } from "./types";
|
||||||
|
|
||||||
describe("UsageStatisticsManager", () => {
|
describe("UsageStatisticsManager", () => {
|
||||||
let manager: UsageStatisticsManager;
|
let manager: UsageStatisticsManager;
|
||||||
|
|
||||||
beforeEach(() => {
|
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);
|
manager = new UsageStatisticsManager(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -19,7 +29,7 @@ describe("UsageStatisticsManager", () => {
|
|||||||
expect(report.uniquePackages).toBeGreaterThanOrEqual(0);
|
expect(report.uniquePackages).toBeGreaterThanOrEqual(0);
|
||||||
expect(Array.isArray(report.platforms)).toBe(true);
|
expect(Array.isArray(report.platforms)).toBe(true);
|
||||||
expect(Array.isArray(report.topPackages)).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');
|
expect(typeof report.platformBreakdown).toBe('object');
|
||||||
}, 30000); // 30 second timeout
|
}, 30000); // 30 second timeout
|
||||||
});
|
});
|
||||||
@@ -72,27 +82,23 @@ describe("UsageStatisticsManager", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Configuration", () => {
|
describe("Configuration", () => {
|
||||||
it("should load development config", () => {
|
it("should create valid config", () => {
|
||||||
const config = getConfig('development');
|
const config: TrackingConfig = {
|
||||||
|
enableLogging: true,
|
||||||
expect(config).toBeDefined();
|
updateInterval: 60 * 60 * 1000,
|
||||||
expect(config.enableLogging).toBe(true);
|
npmPackages: ['lodash', 'axios'],
|
||||||
expect(config.updateInterval).toBe(5 * 60 * 1000); // 5 minutes
|
githubRepos: ['microsoft/vscode'],
|
||||||
});
|
pythonPackages: ['requests'],
|
||||||
|
homebrewPackages: ['git'],
|
||||||
it("should load production config", () => {
|
powershellModules: ['PowerShellGet'],
|
||||||
const config = getConfig('production');
|
postmanCollections: [],
|
||||||
|
goModules: ['github.com/gin-gonic/gin']
|
||||||
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');
|
|
||||||
|
|
||||||
expect(config).toBeDefined();
|
expect(config).toBeDefined();
|
||||||
expect(config.enableLogging).toBe(true);
|
expect(config.enableLogging).toBe(true);
|
||||||
expect(config.updateInterval).toBe(60 * 60 * 1000); // 1 hour
|
expect(config.updateInterval).toBe(60 * 60 * 1000); // 1 hour
|
||||||
|
expect(config.npmPackages).toContain('lodash');
|
||||||
|
expect(config.githubRepos).toContain('microsoft/vscode');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
96
src/index.ts
96
src/index.ts
@@ -2,7 +2,6 @@
|
|||||||
import type { TrackingConfig } from './types';
|
import type { TrackingConfig } from './types';
|
||||||
import { DownloadStatsAggregator } from './aggregator';
|
import { DownloadStatsAggregator } from './aggregator';
|
||||||
import type { AggregatedStats } from './aggregator';
|
import type { AggregatedStats } from './aggregator';
|
||||||
import { getConfig, validateConfig } from './config';
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { execSync } from 'node:child_process';
|
import { execSync } from 'node:child_process';
|
||||||
@@ -45,14 +44,9 @@ Last updated: ${new Date().toISOString()}
|
|||||||
- **Platforms Tracked**: ${stats.platforms.join(', ')}
|
- **Platforms Tracked**: ${stats.platforms.join(', ')}
|
||||||
|
|
||||||
### Top Packages
|
### 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`
|
`${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`
|
||||||
).join('\n')}
|
).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);
|
const startMarker = readmeContent.indexOf(STATS_MARKER_START);
|
||||||
@@ -80,8 +74,6 @@ async function gitCommitAndPush(files: string[], message: string) {
|
|||||||
execSync(`git push`);
|
execSync(`git push`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackingConfig: TrackingConfig = getConfig(process.env.NODE_ENV as 'development' | 'production' || 'default');
|
|
||||||
|
|
||||||
class UsageStatisticsManager {
|
class UsageStatisticsManager {
|
||||||
private aggregator: DownloadStatsAggregator;
|
private aggregator: DownloadStatsAggregator;
|
||||||
private lastUpdateTime: Date | null = null;
|
private lastUpdateTime: Date | null = null;
|
||||||
@@ -110,9 +102,9 @@ class UsageStatisticsManager {
|
|||||||
const report = await this.generateComprehensiveReport();
|
const report = await this.generateComprehensiveReport();
|
||||||
|
|
||||||
if (format === 'csv') {
|
if (format === 'csv') {
|
||||||
const csvHeader = 'Platform,Package,Downloads,Last Updated\n';
|
const csvHeader = 'Platform,Package,Downloads\n';
|
||||||
const csvRows = report.topPackages.map(pkg =>
|
const csvRows = report.topPackages.map(pkg =>
|
||||||
`${pkg.platform},${pkg.name},${pkg.downloads},${new Date().toISOString()}`
|
`${pkg.platform},${pkg.name},${pkg.downloads}`
|
||||||
).join('\n');
|
).join('\n');
|
||||||
return csvHeader + csvRows;
|
return csvHeader + csvRows;
|
||||||
}
|
}
|
||||||
@@ -125,36 +117,27 @@ class UsageStatisticsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async displayReport(report: AggregatedStats) {
|
async displayReport(report: AggregatedStats) {
|
||||||
console.log('🚀 Usage Statistics Report');
|
console.log('📊 Usage Statistics Summary');
|
||||||
console.log('==================================================\n');
|
console.log('==================================================\n');
|
||||||
|
|
||||||
console.log('📈 Summary:');
|
// Overall Summary
|
||||||
|
console.log('📈 Overall Summary:');
|
||||||
console.log(`Total Downloads: ${report.totalDownloads.toLocaleString()}`);
|
console.log(`Total Downloads: ${report.totalDownloads.toLocaleString()}`);
|
||||||
console.log(`Unique Packages: ${report.uniquePackages}`);
|
console.log(`Unique Packages: ${report.uniquePackages}`);
|
||||||
console.log(`Platforms Tracked: ${report.platforms.join(', ')}`);
|
console.log(`Platforms Tracked: ${report.platforms.join(', ')}\n`);
|
||||||
if (report.timeRange) {
|
|
||||||
console.log(`Time Range: ${report.timeRange.start.toLocaleDateString()} to ${report.timeRange.end.toLocaleDateString()}\n`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🏗️ Platform Breakdown:');
|
// Platform Totals
|
||||||
|
console.log('🏗️ Platform Totals:');
|
||||||
for (const [platform, data] of Object.entries(report.platformBreakdown)) {
|
for (const [platform, data] of Object.entries(report.platformBreakdown)) {
|
||||||
console.log(` ${platform.toUpperCase()}:`);
|
console.log(` ${platform.toUpperCase()}: ${data.totalDownloads.toLocaleString()} downloads (${data.uniquePackages} packages)`);
|
||||||
console.log(` Downloads: ${data.totalDownloads.toLocaleString()}`);
|
|
||||||
console.log(` Packages: ${data.uniquePackages}`);
|
|
||||||
console.log(` Package List: ${data.packages.join(', ')}`);
|
|
||||||
}
|
}
|
||||||
console.log();
|
console.log('');
|
||||||
|
|
||||||
console.log('🏆 Top Packages:');
|
// Package Rankings
|
||||||
report.topPackages.slice(0, 10).forEach((pkg, index) => {
|
console.log('🏆 Package Rankings:');
|
||||||
|
report.topPackages.forEach((pkg, index) => {
|
||||||
console.log(` ${index + 1}. ${pkg.name} (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`);
|
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('==================================================');
|
console.log('==================================================');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,41 +150,49 @@ class UsageStatisticsManager {
|
|||||||
platform: 'npm',
|
platform: 'npm',
|
||||||
packageName: 'lodash',
|
packageName: 'lodash',
|
||||||
downloadCount: 1500000,
|
downloadCount: 1500000,
|
||||||
timestamp: new Date(),
|
|
||||||
period: 'total' as const,
|
|
||||||
metadata: { version: '4.17.21' }
|
metadata: { version: '4.17.21' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
platform: 'npm',
|
platform: 'npm',
|
||||||
packageName: 'axios',
|
packageName: 'axios',
|
||||||
downloadCount: 800000,
|
downloadCount: 800000,
|
||||||
timestamp: new Date(),
|
|
||||||
period: 'total' as const,
|
|
||||||
metadata: { version: '1.6.0' }
|
metadata: { version: '1.6.0' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
platform: 'github',
|
platform: 'github',
|
||||||
packageName: 'microsoft/vscode',
|
packageName: 'microsoft/vscode',
|
||||||
downloadCount: 500000,
|
downloadCount: 500000,
|
||||||
timestamp: new Date(),
|
|
||||||
period: 'total' as const,
|
|
||||||
metadata: { release: 'v1.85.0' }
|
metadata: { release: 'v1.85.0' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
platform: 'pypi',
|
platform: 'pypi',
|
||||||
packageName: 'requests',
|
packageName: 'requests',
|
||||||
downloadCount: 300000,
|
downloadCount: 300000,
|
||||||
timestamp: new Date(),
|
|
||||||
period: 'total' as const,
|
|
||||||
metadata: { version: '2.31.0' }
|
metadata: { version: '2.31.0' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
platform: 'homebrew',
|
platform: 'homebrew',
|
||||||
packageName: 'git',
|
packageName: 'git',
|
||||||
downloadCount: 250000,
|
downloadCount: 250000,
|
||||||
timestamp: new Date(),
|
|
||||||
period: 'total' as const,
|
|
||||||
metadata: { version: '2.43.0' }
|
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() {
|
async function main() {
|
||||||
console.log('🚀 Usage Statistics Tracker Starting...\n');
|
console.log('🚀 Usage Statistics Tracker Starting...\n');
|
||||||
|
|
||||||
// Validate configuration
|
// Create a default configuration for CLI usage
|
||||||
try {
|
const defaultConfig: TrackingConfig = {
|
||||||
validateConfig(trackingConfig);
|
enableLogging: true,
|
||||||
} catch (error) {
|
updateInterval: 60 * 60 * 1000, // 1 hour
|
||||||
console.error('❌ Configuration validation failed:', error);
|
npmPackages: ['lodash', 'axios'],
|
||||||
process.exit(1);
|
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 {
|
try {
|
||||||
// Check for preview mode
|
// Check for preview mode
|
||||||
@@ -263,4 +259,4 @@ if (import.meta.main) {
|
|||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
export { UsageStatisticsManager, trackingConfig };
|
export { UsageStatisticsManager };
|
||||||
@@ -7,8 +7,6 @@ export interface BaseDownloadStats {
|
|||||||
packageName: string;
|
packageName: string;
|
||||||
version?: string;
|
version?: string;
|
||||||
downloadCount: number;
|
downloadCount: number;
|
||||||
timestamp: Date;
|
|
||||||
period?: 'daily' | 'weekly' | 'monthly' | 'total';
|
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +22,6 @@ export interface DownloadStatsAggregator {
|
|||||||
totalDownloads: number;
|
totalDownloads: number;
|
||||||
uniquePackages: number;
|
uniquePackages: number;
|
||||||
platforms: string[];
|
platforms: string[];
|
||||||
timeRange: { start: Date; end: Date } | null;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user