https://github.com/smnandre/packapi
https://github.com/smnandre/packapi
Last synced: 11 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/smnandre/packapi
- Owner: smnandre
- License: mit
- Created: 2025-09-07T02:12:04.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-09-07T02:14:57.000Z (11 months ago)
- Last Synced: 2025-09-07T04:16:52.983Z (11 months ago)
- Language: PHP
- Homepage:
- Size: 134 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README




[](https://github.com/sponsors/smnandre)

Get insights from **Composer**, **NPM**, **GitHub**, and more via a unified, strongly‑typed API.
## Features
- **Multi‑ecosystem**: Composer, NPM, GitHub, jsDelivr, OSV, BundlePhobia
- **Analyses**: Metadata, downloads, security, activity, quality
- **Strong typing**: PHP 8.3+ with strict types
- **Extensible**: Provider/factory architecture
- **Well‑tested**: Extensive automated test suite
- **Lean deps**: Symfony components and PSR interfaces
- **HTTP/3 (QUIC)** support with graceful fallback
## Quick Start
### Installation
```bash
composer require smnandre/packapi
```
### Basic Usage
```php
use PackApi\Bridge\Packagist\PackagistProviderFactory;
use PackApi\Http\HttpClientFactory;
use PackApi\Inspector\{MetadataInspector, DownloadStatsInspector};
use PackApi\Package\ComposerPackage;
$http = new HttpClientFactory();
$packagist = new PackagistProviderFactory($http);
$metadata = new MetadataInspector([
$packagist->createMetadataProvider(),
]);
$downloads = new DownloadStatsInspector([
$packagist->createStatsProvider(),
]);
$package = new ComposerPackage('symfony/console');
$meta = $metadata->getMetadata($package);
$stats = $downloads->getStats($package);
echo 'Package: '.($meta?->name ?? 'N/A')."\n";
echo 'Monthly downloads: '.($stats?->get('monthly')?->getCount() ?? 'N/A')."\n";
```
For activity, content, quality, and OSV security, add the relevant provider factories (GitHub, jsDelivr, OSV) and pass them to the corresponding inspectors.
## Supported Package Types
| Ecosystem | Package Type | Metadata | Downloads | Security | Activity | Content | Bundle Size |
|--------------|-------------------|----------|-----------|----------|----------|---------|-------------|
| **Composer** | `ComposerPackage` | Yes | Yes | Yes | Yes | Yes | No |
| **NPM** | `NpmPackage` | Yes | Yes | Yes | Yes | Yes | Yes |
| **GitHub** | Any with repo URL | Yes | Yes | Yes | Yes | Yes | No |
## Usage Examples
### Package Metadata Analysis
```php
use PackApi\Inspector\MetadataInspector;
use PackApi\Bridge\Packagist\PackagistProviderFactory;
use PackApi\Package\ComposerPackage;
$factory = new PackagistProviderFactory($httpClient);
$inspector = new MetadataInspector([
$factory->createMetadataProvider()
]);
$package = new ComposerPackage('laravel/framework');
$metadata = $inspector->getMetadata($package);
echo $metadata->getName() . "\n"; // laravel/framework
echo $metadata->getDescription() . "\n"; // The Laravel Framework
echo $metadata->getLicense() . "\n"; // MIT
echo $metadata->getRepository() . "\n"; // https://github.com/laravel/framework
```
### Download Statistics
```php
use PackApi\Inspector\DownloadStatsInspector;
use PackApi\Package\NpmPackage;
$inspector = new DownloadStatsInspector([
$npmFactory->createDownloadStatsProvider(),
$packagistFactory->createStatsProvider()
]);
$package = new NpmPackage('react');
$stats = $inspector->getStats($package);
$monthly = $stats->get('monthly');
if ($monthly) {
echo "Downloads this month: " . number_format($monthly->getCount()) . "\n";
$days = $monthly->getEnd()->diff($monthly->getStart())->days + 1;
echo "Daily average: " . number_format($monthly->getCount() / $days) . "\n";
}
```
### Security Advisory Scanning
```php
use PackApi\Inspector\SecurityInspector;
use PackApi\Bridge\OSV\OSVProviderFactory;
use PackApi\Bridge\GitHub\GitHubProviderFactory;
$inspector = new SecurityInspector([
$osvFactory->createSecurityProvider(), // OSV Database
$githubFactory->createSecurityProvider() // GitHub Security Advisories
]);
$advisories = $inspector->getSecurityAdvisories($package);
foreach ($advisories as $advisory) {
echo "ALERT: {$advisory->getTitle()}\n";
echo " Severity: {$advisory->getSeverity()}\n";
echo " Link: {$advisory->getLink()}\n\n";
}
```
### Project Activity Analysis
```php
use PackApi\Inspector\ActivityInspector;
$inspector = new ActivityInspector([
$githubFactory->createActivityProvider()
]);
$activity = $inspector->getActivitySummary($package);
echo "Last commit: " . $activity->getLastCommit()?->format('Y-m-d') . "\n";
echo "Contributors: " . $activity->getContributors() . "\n";
echo "Open issues: " . $activity->getOpenIssues() . "\n";
echo "Latest release: " . $activity->getLastRelease() . "\n";
```
### Package Content Analysis
```php
use PackApi\Inspector\ContentInspector;
$inspector = new ContentInspector([
$jsDelivrFactory->createContentProvider(),
$githubFactory->createContentProvider()
]);
$content = $inspector->getContentOverview($package);
echo "Files: " . $content->getFileCount() . "\n";
echo "Total size: " . number_format($content->getTotalSize()) . " bytes\n";
echo "Has README: " . ($content->hasReadme() ? 'Yes' : 'No') . "\n";
echo "Has tests: " . ($content->hasTests() ? 'Yes' : 'No') . "\n";
```
### Bundle Size Analysis (NPM)
```php
use PackApi\Bridge\BundlePhobia\BundlePhobiaProviderFactory;
$httpFactory = new HttpClientFactory();
$factory = new BundlePhobiaProviderFactory($httpFactory);
$sizeProvider = $factory->createBundleSizeProvider();
$package = new NpmPackage('lodash');
$bundleSize = $sizeProvider->getBundleSize($package);
if ($bundleSize) {
echo "Bundle size: " . $bundleSize->getFormattedSize() . "\n";
echo "Gzipped: " . $bundleSize->getFormattedGzipSize() . "\n";
echo "Dependencies: " . $bundleSize->getDependencyCount() . "\n";
}
```
## Configuration
### HTTP/3 (QUIC)
PackApi supports HTTP/3 for improved performance:
```php
use PackApi\Http\HttpClientFactory;
$httpFactory = new HttpClientFactory();
$client = $httpFactory->createClient([
'enable_quic' => true // Automatic fallback if not supported
]);
```
### Caching
Enable HTTP caching at the Symfony HTTP client level (e.g., `CachingHttpClient` with an HttpKernel `Store`). PackApi does not require a separate configuration object.
### Logging
Pass a PSR‑3 logger to `HttpClientFactory` to log outgoing requests in examples and providers.
### GitHub Authentication
For higher GitHub rate limits, provide a token:
```php
// Via environment variable
$_ENV['GITHUB_TOKEN'] = 'ghp_your_token_here';
// Pass the token to GitHubProviderFactory when creating providers
// $github = new GitHubProviderFactory($httpFactory, $_ENV['GITHUB_TOKEN'] ?? null);
```
## Architecture
PackApi uses a clean, extensible architecture:
### Core Components
- **Packages**: Represent different package types (`ComposerPackage`, `NpmPackage`)
- **Inspectors**: Analyze specific aspects (metadata, downloads, security, etc.)
- **Providers**: Fetch data from external sources (Packagist, GitHub, NPM, etc.)
- **Models**: Strongly-typed value objects for results
- **Builder**: Fluent API for configuration
### Provider Pattern
Each inspector accepts one or more providers from the corresponding factory. Providers are tried in order until one succeeds.
```php
$security = new SecurityInspector([
$osvFactory->createSecurityProvider(),
$githubFactory->createSecurityProvider(),
$packagistFactory->createSecurityProvider(),
]);
$advisories = $security->getSecurityAdvisories($package);
```
## Testing
PackApi has comprehensive test coverage:
```bash
# Run tests
composer test
# Run with coverage
composer test-coverage
# Check code style
composer cs
# Fix code style
composer cs-fix
```
## Examples
Run the sample scripts in `examples/` to try PackApi quickly:
- `examples/metadata-analysis.php`: print package metadata
- `examples/download-stats-analysis.php`: print download periods
- `examples/content-analysis.php`: analyze files and flags
- `examples/activity-analysis.php`: summarize repo activity (set `GITHUB_TOKEN` for richer data)
- `examples/security-analysis.php`: list security advisories (OSV/GitHub)
- `examples/bundlephobia-size.php`: show NPM bundle sizes
- `examples/all-analysis.php`: run a combined analysis with sensible fallbacks
Usage:
```bash
php examples/metadata-analysis.php
php examples/all-analysis.php
```
### Adding New Providers
```php
// 1. Implement the provider interface
class MyCustomProvider implements MetadataProviderInterface
{
public function supports(Package $package): bool { /* ... */ }
public function getMetadata(Package $package): ?Metadata { /* ... */ }
}
// 2. Create a factory
class MyCustomProviderFactory
{
public function createMetadataProvider(): MyCustomProvider
{
return new MyCustomProvider($this->httpClient);
}
}
// 3. Use in inspector
$inspector = new MetadataInspector([
new MyCustomProvider($httpClient)
]);
```
## Requirements
- **PHP 8.3+** (uses modern PHP features)
- **ext-json** (for API responses)
- **ext-curl** (for HTTP requests)
- **ext-mbstring** (for string handling)
### Optional
- **ext-curl with HTTP/3** (for QUIC support)
- **Redis/Memcached** (for distributed caching)
---
## Contributing
Contributions are welcome! Please start by creating an issue to discuss your changes.
---
## Credits
Created and maintained by [Simon André](https://github.com/smnandre).
> [!TIP]
> This library is developed and maintained by a single developer in their free time.
>
> To ensure continued maintenance and improvements, consider [sponsoring development](https://github.com/sponsors/smnandre).
---
## License
MIT License - see [LICENSE](LICENSE) file for details.