465 lines
14 KiB
Markdown
465 lines
14 KiB
Markdown
|
|
# @apiclient.xyz/peeringdb 🌐
|
||
|
|
|
||
|
|
> A modern, fully-typed TypeScript client for the [PeeringDB API](https://www.peeringdb.com/apidocs/) with automatic retry handling and smart request management.
|
||
|
|
|
||
|
|
## Why This Client? ✨
|
||
|
|
|
||
|
|
- **🎯 Full TypeScript Support** - Complete type definitions for all PeeringDB resources
|
||
|
|
- **🚀 Smart Request Handling** - Automatic retry with exponential backoff for 429 rate limits
|
||
|
|
- **🔄 Fluent API** - Clean, chainable methods using `@push.rocks/smartrequest`
|
||
|
|
- **📦 Manager Pattern** - Organized access to all PeeringDB resources
|
||
|
|
- **🔍 Advanced Querying** - Field filters, pagination, depth control, and field selection
|
||
|
|
- **🔐 Auth Optional** - Works with anonymous access or API keys for write operations
|
||
|
|
- **✅ Production Ready** - Fully tested with 18/18 tests passing in Node.js
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Using pnpm (recommended)
|
||
|
|
pnpm add @apiclient.xyz/peeringdb
|
||
|
|
|
||
|
|
# Using npm
|
||
|
|
npm install @apiclient.xyz/peeringdb
|
||
|
|
|
||
|
|
# Using yarn
|
||
|
|
yarn add @apiclient.xyz/peeringdb
|
||
|
|
```
|
||
|
|
|
||
|
|
## Quick Start 🚀
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { PeeringDbClient } from '@apiclient.xyz/peeringdb';
|
||
|
|
|
||
|
|
// Create client (anonymous access - perfect for read operations)
|
||
|
|
const client = new PeeringDbClient();
|
||
|
|
|
||
|
|
// Fetch networks
|
||
|
|
const networks = await client.networks.list({ limit: 10 });
|
||
|
|
|
||
|
|
// Look up a specific network by ASN
|
||
|
|
const google = await client.networks.getByAsn(15169);
|
||
|
|
console.log(google?.name); // "Google LLC"
|
||
|
|
|
||
|
|
// Search for facilities
|
||
|
|
const equinixFacilities = await client.facilities.searchByName('Equinix');
|
||
|
|
|
||
|
|
// Get exchanges in a specific country
|
||
|
|
const usExchanges = await client.exchanges.getByCountry('US');
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Examples 📚
|
||
|
|
|
||
|
|
### Working with Networks
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// List networks with pagination
|
||
|
|
const networks = await client.networks.list({
|
||
|
|
limit: 50,
|
||
|
|
skip: 0
|
||
|
|
});
|
||
|
|
|
||
|
|
// Get a specific network by ASN
|
||
|
|
const cloudflare = await client.networks.getByAsn(13335);
|
||
|
|
|
||
|
|
// Search networks by name
|
||
|
|
const results = await client.networks.searchByName('Amazon');
|
||
|
|
|
||
|
|
// Get all networks for an organization
|
||
|
|
const orgNetworks = await client.networks.getByOrgId(123);
|
||
|
|
|
||
|
|
// Get network with expanded nested objects (depth: 0, 1, or 2)
|
||
|
|
const networkWithDetails = await client.networks.getByAsn(15169, 2);
|
||
|
|
console.log(networkWithDetails?.org); // Full organization object included
|
||
|
|
```
|
||
|
|
|
||
|
|
### Working with Organizations
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// List organizations
|
||
|
|
const orgs = await client.organizations.list({ limit: 10 });
|
||
|
|
|
||
|
|
// Get a specific organization
|
||
|
|
const org = await client.organizations.getById(2);
|
||
|
|
|
||
|
|
// Search by name
|
||
|
|
const searchResults = await client.organizations.searchByName('Google');
|
||
|
|
|
||
|
|
// Get organizations by country
|
||
|
|
const usOrgs = await client.organizations.getByCountry('US');
|
||
|
|
```
|
||
|
|
|
||
|
|
### Working with Facilities
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// List data center facilities
|
||
|
|
const facilities = await client.facilities.list({ limit: 10 });
|
||
|
|
|
||
|
|
// Get a specific facility
|
||
|
|
const facility = await client.facilities.getById(1);
|
||
|
|
|
||
|
|
// Search by name
|
||
|
|
const equinix = await client.facilities.searchByName('Equinix');
|
||
|
|
|
||
|
|
// Get facilities in a country
|
||
|
|
const usFacilities = await client.facilities.getByCountry('US');
|
||
|
|
|
||
|
|
// Get facilities in a specific city
|
||
|
|
const londonDCs = await client.facilities.getByCity('London');
|
||
|
|
```
|
||
|
|
|
||
|
|
### Working with Internet Exchanges
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// List internet exchanges
|
||
|
|
const exchanges = await client.exchanges.list({ limit: 10 });
|
||
|
|
|
||
|
|
// Get a specific exchange
|
||
|
|
const exchange = await client.exchanges.getById(1);
|
||
|
|
|
||
|
|
// Search by name
|
||
|
|
const amsix = await client.exchanges.searchByName('AMS-IX');
|
||
|
|
|
||
|
|
// Get exchanges by country
|
||
|
|
const usIXs = await client.exchanges.getByCountry('US');
|
||
|
|
|
||
|
|
// Get exchanges by region
|
||
|
|
const europeIXs = await client.exchanges.getByRegion('Europe');
|
||
|
|
```
|
||
|
|
|
||
|
|
### Network Connections & Peering Points
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Get network-to-IX connections (where a network peers)
|
||
|
|
const googlePeering = await client.netIxLans.getByAsn(15169);
|
||
|
|
|
||
|
|
// Get network-to-facility connections (where a network has presence)
|
||
|
|
const networkPresence = await client.netFacs.getByNetId(123);
|
||
|
|
|
||
|
|
// Get all networks present at a facility
|
||
|
|
const facilityNetworks = await client.netFacs.getByFacId(456);
|
||
|
|
|
||
|
|
// Get all networks at an exchange
|
||
|
|
const ixNetworks = await client.netIxLans.getByIxLanId(789);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Convenience Methods 🎁
|
||
|
|
|
||
|
|
Quick shortcuts for common operations:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Quick network lookup by ASN
|
||
|
|
const network = await client.convenience.getNetworkByAsn(15169);
|
||
|
|
|
||
|
|
// Search networks (wraps networks.searchByName)
|
||
|
|
const networks = await client.convenience.searchNetworks('Google');
|
||
|
|
|
||
|
|
// Search facilities (wraps facilities.searchByName)
|
||
|
|
const facilities = await client.convenience.searchFacilities('Equinix');
|
||
|
|
|
||
|
|
// Get all facilities where a network is present
|
||
|
|
const networkFacilities = await client.convenience.getNetworkFacilities(15169);
|
||
|
|
|
||
|
|
// Get all exchanges where a network peers
|
||
|
|
const networkExchanges = await client.convenience.getNetworkExchanges(15169);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Advanced Querying 🔍
|
||
|
|
|
||
|
|
### Query Options
|
||
|
|
|
||
|
|
All list and search methods support comprehensive query options:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const networks = await client.networks.list({
|
||
|
|
limit: 50, // Limit number of results
|
||
|
|
skip: 100, // Offset for pagination
|
||
|
|
fields: 'id,asn,name', // Select only specific fields
|
||
|
|
depth: 2, // Expand nested objects (0, 1, or 2)
|
||
|
|
since: 1640000000, // Unix timestamp - get only updates since
|
||
|
|
autoPaginate: false, // Auto-fetch all pages (default: false)
|
||
|
|
|
||
|
|
// Field filters using PeeringDB's powerful query syntax
|
||
|
|
name__contains: 'Google',
|
||
|
|
asn__in: [15169, 16509, 13335],
|
||
|
|
info_traffic__gte: '100Gbps',
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
### Field Filter Operators
|
||
|
|
|
||
|
|
PeeringDB supports a wide range of filter operators:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// String filters
|
||
|
|
name__contains: 'Google' // Contains substring (case-insensitive)
|
||
|
|
name__startswith: 'Google' // Starts with
|
||
|
|
name__in: ['Google', 'Amazon'] // Match any in list
|
||
|
|
|
||
|
|
// Number filters
|
||
|
|
asn__lt: 20000 // Less than
|
||
|
|
asn__lte: 20000 // Less than or equal to
|
||
|
|
asn__gt: 10000 // Greater than
|
||
|
|
asn__gte: 10000 // Greater than or equal to
|
||
|
|
asn__in: [15169, 16509] // Match any in list
|
||
|
|
|
||
|
|
// Date filters (Unix timestamps)
|
||
|
|
updated__gte: 1640000000 // Updated after timestamp
|
||
|
|
created__lt: 1650000000 // Created before timestamp
|
||
|
|
|
||
|
|
// Boolean filters
|
||
|
|
info_ipv6: true // Exact boolean match
|
||
|
|
```
|
||
|
|
|
||
|
|
### Depth Parameter
|
||
|
|
|
||
|
|
Control how much nested data is expanded in responses:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// depth: 0 - Only IDs for nested objects (default)
|
||
|
|
const network0 = await client.networks.getByAsn(15169, 0);
|
||
|
|
console.log(network0?.org_id); // Just the ID
|
||
|
|
|
||
|
|
// depth: 1 - Basic nested object data
|
||
|
|
const network1 = await client.networks.getByAsn(15169, 1);
|
||
|
|
console.log(network1?.org?.name); // Organization name included
|
||
|
|
|
||
|
|
// depth: 2 - Full nested object expansion
|
||
|
|
const network2 = await client.networks.getByAsn(15169, 2);
|
||
|
|
console.log(network2?.org?.address); // Full organization details
|
||
|
|
```
|
||
|
|
|
||
|
|
### Field Selection
|
||
|
|
|
||
|
|
Request only the fields you need to reduce bandwidth:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Get only specific fields
|
||
|
|
const networks = await client.networks.list({
|
||
|
|
fields: 'id,asn,name,info_type',
|
||
|
|
limit: 100
|
||
|
|
});
|
||
|
|
|
||
|
|
// Each network object will only contain: id, asn, name, info_type
|
||
|
|
```
|
||
|
|
|
||
|
|
## Authentication 🔐
|
||
|
|
|
||
|
|
For write operations (create, update, delete), you need a PeeringDB API key:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const client = new PeeringDbClient('your-api-key-here');
|
||
|
|
|
||
|
|
// Create a new organization
|
||
|
|
const newOrg = await client.organizations.create({
|
||
|
|
name: 'My Company',
|
||
|
|
website: 'https://example.com',
|
||
|
|
address1: '123 Main St',
|
||
|
|
city: 'San Francisco',
|
||
|
|
state: 'CA',
|
||
|
|
zipcode: '94102',
|
||
|
|
country: 'US',
|
||
|
|
});
|
||
|
|
|
||
|
|
// Update an organization
|
||
|
|
const updated = await client.organizations.update(123, {
|
||
|
|
website: 'https://newwebsite.com',
|
||
|
|
notes: 'Updated contact information'
|
||
|
|
});
|
||
|
|
|
||
|
|
// Delete an organization (careful!)
|
||
|
|
await client.organizations.delete(123);
|
||
|
|
```
|
||
|
|
|
||
|
|
> **Note:** Most use cases only need read access (anonymous), which doesn't require an API key.
|
||
|
|
|
||
|
|
## API Reference 📖
|
||
|
|
|
||
|
|
### Client
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
class PeeringDbClient {
|
||
|
|
constructor(apiKey?: string)
|
||
|
|
|
||
|
|
// Resource managers
|
||
|
|
organizations: OrganizationManager
|
||
|
|
networks: NetworkManager
|
||
|
|
facilities: FacilityManager
|
||
|
|
exchanges: ExchangeManager
|
||
|
|
netIxLans: NetIxLanManager
|
||
|
|
netFacs: NetFacManager
|
||
|
|
ixLans: IxLanManager
|
||
|
|
ixFacs: IxFacManager
|
||
|
|
ixPfxs: IxPfxManager
|
||
|
|
pocs: PocManager
|
||
|
|
|
||
|
|
// Convenience methods
|
||
|
|
convenience: {
|
||
|
|
getNetworkByAsn(asn: number): Promise<INetwork | null>
|
||
|
|
searchNetworks(name: string): Promise<INetwork[]>
|
||
|
|
searchFacilities(name: string): Promise<IFacility[]>
|
||
|
|
getNetworkFacilities(asn: number): Promise<IFacility[]>
|
||
|
|
getNetworkExchanges(asn: number): Promise<IExchange[]>
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Manager Methods
|
||
|
|
|
||
|
|
All resource managers provide these standard methods:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// List resources with optional filtering
|
||
|
|
list(options?: IQueryOptions): Promise<T[]>
|
||
|
|
|
||
|
|
// Get a single resource by ID
|
||
|
|
getById(id: number, depth?: 0 | 1 | 2): Promise<T | null>
|
||
|
|
|
||
|
|
// Create a new resource (requires API key)
|
||
|
|
create(data: Partial<T>): Promise<T>
|
||
|
|
|
||
|
|
// Update an existing resource (requires API key)
|
||
|
|
update(id: number, data: Partial<T>): Promise<T>
|
||
|
|
|
||
|
|
// Delete a resource (requires API key)
|
||
|
|
delete(id: number): Promise<void>
|
||
|
|
```
|
||
|
|
|
||
|
|
Plus specialized methods for each resource type (e.g., `getByAsn()`, `searchByName()`, `getByCountry()`).
|
||
|
|
|
||
|
|
### Available Resource Managers
|
||
|
|
|
||
|
|
| Manager | Endpoint | Description |
|
||
|
|
|---------|----------|-------------|
|
||
|
|
| `organizations` | `/org` | Companies and organizations |
|
||
|
|
| `networks` | `/net` | Autonomous systems and networks |
|
||
|
|
| `facilities` | `/fac` | Data centers and colocation facilities |
|
||
|
|
| `exchanges` | `/ix` | Internet exchange points |
|
||
|
|
| `netIxLans` | `/netixlan` | Network-to-exchange connections |
|
||
|
|
| `netFacs` | `/netfac` | Network-to-facility connections |
|
||
|
|
| `ixLans` | `/ixlan` | Exchange LAN information |
|
||
|
|
| `ixFacs` | `/ixfac` | Exchange-to-facility connections |
|
||
|
|
| `ixPfxs` | `/ixpfx` | Exchange IP prefixes |
|
||
|
|
| `pocs` | `/poc` | Points of contact |
|
||
|
|
|
||
|
|
## TypeScript Support 💙
|
||
|
|
|
||
|
|
Full TypeScript support with comprehensive interfaces:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import type {
|
||
|
|
INetwork,
|
||
|
|
IOrganization,
|
||
|
|
IFacility,
|
||
|
|
IExchange,
|
||
|
|
IQueryOptions
|
||
|
|
} from '@apiclient.xyz/peeringdb';
|
||
|
|
|
||
|
|
// Type-safe queries
|
||
|
|
const options: IQueryOptions = {
|
||
|
|
limit: 50,
|
||
|
|
depth: 2,
|
||
|
|
asn__gte: 10000
|
||
|
|
};
|
||
|
|
|
||
|
|
const networks: INetwork[] = await client.networks.list(options);
|
||
|
|
|
||
|
|
// Full intellisense for all properties
|
||
|
|
networks.forEach(network => {
|
||
|
|
console.log(network.asn); // number
|
||
|
|
console.log(network.name); // string
|
||
|
|
console.log(network.info_ipv6); // boolean
|
||
|
|
console.log(network.created); // string (ISO date)
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Rate Limiting & Retry 🔄
|
||
|
|
|
||
|
|
The client automatically handles PeeringDB's rate limits:
|
||
|
|
|
||
|
|
- **Automatic Retry**: Up to 3 retries with exponential backoff
|
||
|
|
- **429 Handling**: Smartly backs off when rate limited
|
||
|
|
- **Connection Pooling**: Efficient HTTP connection reuse via `@push.rocks/smartrequest`
|
||
|
|
|
||
|
|
No configuration needed - it just works! 🎉
|
||
|
|
|
||
|
|
## Error Handling ⚠️
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
try {
|
||
|
|
const network = await client.networks.getByAsn(15169);
|
||
|
|
if (!network) {
|
||
|
|
console.log('Network not found');
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error('API Error:', error.message);
|
||
|
|
}
|
||
|
|
|
||
|
|
// The client throws errors for:
|
||
|
|
// - Network failures
|
||
|
|
// - Invalid API responses
|
||
|
|
// - PeeringDB API errors (returned in meta.error)
|
||
|
|
// - Missing required User-Agent (403 Forbidden)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Important Notes 📝
|
||
|
|
|
||
|
|
### User-Agent Requirement
|
||
|
|
|
||
|
|
PeeringDB **requires** a proper User-Agent header or returns `403 Forbidden`. This client automatically sets:
|
||
|
|
|
||
|
|
```
|
||
|
|
User-Agent: @apiclient.xyz/peeringdb/1.0.1 (Node.js)
|
||
|
|
```
|
||
|
|
|
||
|
|
If you see 403 errors with other HTTP clients, make sure to set a User-Agent!
|
||
|
|
|
||
|
|
### Runtime Support
|
||
|
|
|
||
|
|
- ✅ **Node.js**: Fully supported and tested (18/18 tests passing)
|
||
|
|
- ⚠️ **Bun/Deno**: Limited support due to smartrequest compatibility
|
||
|
|
|
||
|
|
This package is designed primarily for Node.js environments.
|
||
|
|
|
||
|
|
## Resources 🔗
|
||
|
|
|
||
|
|
- [PeeringDB API Documentation](https://www.peeringdb.com/apidocs/)
|
||
|
|
- [PeeringDB Website](https://www.peeringdb.com/)
|
||
|
|
- [Source Code Repository](https://code.foss.global/apiclient.xyz/peeringdb)
|
||
|
|
- [Issue Tracker](https://code.foss.global/apiclient.xyz/peeringdb/issues)
|
||
|
|
|
||
|
|
## Real-World Use Cases 🌍
|
||
|
|
|
||
|
|
This client is perfect for:
|
||
|
|
|
||
|
|
- **Network Engineering Tools** - Build automation for peering management
|
||
|
|
- **Network Visualization** - Map internet topology and interconnections
|
||
|
|
- **Due Diligence** - Research networks and their peering policies
|
||
|
|
- **Capacity Planning** - Analyze where networks have presence
|
||
|
|
- **Monitoring Systems** - Track changes to network infrastructure
|
||
|
|
- **Research Projects** - Study internet topology and peering relationships
|
||
|
|
|
||
|
|
## Contributing 🤝
|
||
|
|
|
||
|
|
Found a bug? Have a feature request?
|
||
|
|
|
||
|
|
Please open an issue on our [issue tracker](https://code.foss.global/apiclient.xyz/peeringdb/issues).
|
||
|
|
|
||
|
|
## License and Legal Information
|
||
|
|
|
||
|
|
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||
|
|
|
||
|
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||
|
|
|
||
|
|
### Trademarks
|
||
|
|
|
||
|
|
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||
|
|
|
||
|
|
### Company Information
|
||
|
|
|
||
|
|
Task Venture Capital GmbH
|
||
|
|
Registered at District court Bremen HRB 35230 HB, Germany
|
||
|
|
|
||
|
|
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||
|
|
|
||
|
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|