This commit is contained in:
2025-11-18 20:47:48 +00:00
commit 747fb787e1
38 changed files with 18518 additions and 0 deletions

25
ts/index.ts Normal file
View File

@@ -0,0 +1,25 @@
/**
* @apiclient.xyz/peeringdb
* PeeringDB API Client for Node.js
*/
// Export main client
export { PeeringDbClient } from './peeringdb.classes.client.js';
// Export all manager classes
export { OrganizationManager } from './peeringdb.classes.organizationmanager.js';
export { NetworkManager } from './peeringdb.classes.networkmanager.js';
export { FacilityManager } from './peeringdb.classes.facilitymanager.js';
export { ExchangeManager } from './peeringdb.classes.exchangemanager.js';
export { NetIxLanManager } from './peeringdb.classes.netixlanmanager.js';
export { NetFacManager } from './peeringdb.classes.netfacmanager.js';
export { IxLanManager } from './peeringdb.classes.ixlanmanager.js';
export { IxFacManager } from './peeringdb.classes.ixfacmanager.js';
export { IxPfxManager } from './peeringdb.classes.ixpfxmanager.js';
export { PocManager } from './peeringdb.classes.pocmanager.js';
// Export types
export * from './peeringdb.types.js';
// Export interfaces
export * from './interfaces/index.js';

15
ts/interfaces/index.ts Normal file
View File

@@ -0,0 +1,15 @@
/**
* PeeringDB API Interfaces
* Export all interface definitions for PeeringDB API resources
*/
export * from './peeringdb.api.organization.js';
export * from './peeringdb.api.network.js';
export * from './peeringdb.api.facility.js';
export * from './peeringdb.api.exchange.js';
export * from './peeringdb.api.netixlan.js';
export * from './peeringdb.api.netfac.js';
export * from './peeringdb.api.ixlan.js';
export * from './peeringdb.api.ixfac.js';
export * from './peeringdb.api.ixpfx.js';
export * from './peeringdb.api.poc.js';

View File

@@ -0,0 +1,79 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Internet Exchange object from PeeringDB API
* Represents an Internet Exchange Point (IXP)
*/
export interface IExchange extends IPeeringDbBaseObject {
/** Exchange ID */
id: number;
/** Organization ID */
org_id: number;
/** Organization object (when depth > 0) */
org?: any;
/** Exchange name */
name: string;
/** Also known as (alternate names) */
aka: string;
/** Name long */
name_long: string;
/** Website */
website: string;
/** City */
city: string;
/** Country code (ISO 3166-1 alpha-2) */
country: string;
/** Region/continent */
region_continent: string;
/** Media type (Ethernet, ATM, etc.) */
media: string;
/** Notes (markdown) */
notes: string;
/** Proto unicast */
proto_unicast: boolean;
/** Proto multicast */
proto_multicast: boolean;
/** Proto IPv6 */
proto_ipv6: boolean;
/** URL stats */
url_stats: string;
/** Tech email */
tech_email: string;
/** Tech phone */
tech_phone: string;
/** Policy email */
policy_email: string;
/** Policy phone */
policy_phone: string;
/** Sales email */
sales_email: string;
/** Sales phone */
sales_phone: string;
/** Related IX LANs */
ixlan_set?: number[] | any[];
/** Related IX-facility connections */
ixfac_set?: number[] | any[];
}

View File

@@ -0,0 +1,88 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Facility object from PeeringDB API
* Represents a colocation facility or data center
*/
export interface IFacility extends IPeeringDbBaseObject {
/** Facility ID */
id: number;
/** Organization ID */
org_id: number;
/** Organization object (when depth > 0) */
org?: any;
/** Facility name */
name: string;
/** Also known as (alternate names) */
aka: string;
/** Website */
website: string;
/** CLLI code */
clli: string;
/** Renater code */
renater: string;
/** NPL code */
npanxx: string;
/** Notes (markdown) */
notes: string;
/** Address line 1 */
address1: string;
/** Address line 2 */
address2: string;
/** City */
city: string;
/** State/Province */
state: string;
/** Zip/Postal code */
zipcode: string;
/** Country code (ISO 3166-1 alpha-2) */
country: string;
/** Latitude */
latitude: number | null;
/** Longitude */
longitude: number | null;
/** Floor area (sqm) */
floor_area: number | null;
/** Available voltage services */
available_voltage_services: string;
/** Power redundancy */
power_redundancy: string;
/** Diverse serving substations */
diverse_serving_substations: boolean;
/** Property */
property: string;
/** Campus ID */
campus_id: number | null;
/** Campus object (when depth > 0) */
campus?: any;
/** Related network-facility connections */
netfac_set?: number[] | any[];
/** Related IX-facility connections */
ixfac_set?: number[] | any[];
}

View File

@@ -0,0 +1,22 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* IX Facility object from PeeringDB API
* Represents the connection between an Internet Exchange and a facility
*/
export interface IIxFac extends IPeeringDbBaseObject {
/** IxFac ID */
id: number;
/** Exchange ID */
ix_id: number;
/** Exchange object (when depth > 0) */
ix?: any;
/** Facility ID */
fac_id: number;
/** Facility object (when depth > 0) */
fac?: any;
}

View File

@@ -0,0 +1,43 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* IX LAN object from PeeringDB API
* Represents a LAN at an Internet Exchange
*/
export interface IIxLan extends IPeeringDbBaseObject {
/** IxLan ID */
id: number;
/** Exchange ID */
ix_id: number;
/** Exchange object (when depth > 0) */
ix?: any;
/** LAN name */
name: string;
/** Description */
descr: string;
/** MTU size */
mtu: number;
/** VLANs */
vlan: number | null;
/** Dot1q support */
dot1q_support: boolean;
/** Route server ASN */
rs_asn: number | null;
/** ARP sponge */
arp_sponge: string | null;
/** Related IX prefixes */
ixpfx_set?: number[] | any[];
/** Related network IX LANs */
netixlan_set?: number[] | any[];
}

View File

@@ -0,0 +1,25 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* IX Prefix object from PeeringDB API
* Represents an IP prefix used by an Internet Exchange
*/
export interface IIxPfx extends IPeeringDbBaseObject {
/** IxPfx ID */
id: number;
/** IX LAN ID */
ixlan_id: number;
/** IX LAN object (when depth > 0) */
ixlan?: any;
/** IP prefix */
prefix: string;
/** Protocol (IPv4 or IPv6) */
protocol: string;
/** Peering point */
in_dfz: boolean;
}

View File

@@ -0,0 +1,34 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Network Facility object from PeeringDB API
* Represents a network's presence at a colocation facility
*/
export interface INetFac extends IPeeringDbBaseObject {
/** NetFac ID */
id: number;
/** Network ID */
net_id: number;
/** Network object (when depth > 0) */
net?: any;
/** Facility ID */
fac_id: number;
/** Facility object (when depth > 0) */
fac?: any;
/** Availability percentage */
avail_sonet: boolean;
/** Availability percentage */
avail_ethernet: boolean;
/** Availability percentage */
avail_atm: boolean;
/** Local ASN */
local_asn: number | null;
}

View File

@@ -0,0 +1,43 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Network IX LAN object from PeeringDB API
* Represents a network's presence at an Internet Exchange
*/
export interface INetIxLan extends IPeeringDbBaseObject {
/** NetIxLan ID */
id: number;
/** Network ID */
net_id: number;
/** Network object (when depth > 0) */
net?: any;
/** IX LAN ID */
ixlan_id: number;
/** IX LAN object (when depth > 0) */
ixlan?: any;
/** Notes (markdown) */
notes: string;
/** Speed in Mbps */
speed: number;
/** Autonomous System Number (ASN) */
asn: number;
/** IPv4 address */
ipaddr4: string | null;
/** IPv6 address */
ipaddr6: string | null;
/** Is route server */
is_rs_peer: boolean;
/** Operational status */
operational: boolean;
}

View File

@@ -0,0 +1,91 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Network object from PeeringDB API
* Represents an autonomous system (AS) and its peering information
*/
export interface INetwork extends IPeeringDbBaseObject {
/** Network ID */
id: number;
/** Organization ID */
org_id: number;
/** Organization object (when depth > 0) */
org?: any;
/** Network name */
name: string;
/** Also known as (alternate names) */
aka: string;
/** Website */
website: string;
/** Autonomous System Number (ASN) */
asn: number;
/** Looking glass URL */
looking_glass: string;
/** Route server URL */
route_server: string;
/** IRR as-set/route-set */
irr_as_set: string;
/** Network information (markdown) */
info_type: string;
/** Network traffic levels */
info_traffic: string;
/** Network ratios */
info_ratio: string;
/** Network scope */
info_scope: string;
/** Network types (NSP, Content, etc.) */
info_types: string;
/** Peering policy */
policy_url: string;
/** General policy (Open, Selective, etc.) */
policy_general: string;
/** Location requirements for peering */
policy_locations: string;
/** Ratio requirement */
policy_ratio: boolean;
/** Contract requirement */
policy_contracts: string;
/** Notes (markdown) */
notes: string;
/** Number of unicast IPv4 prefixes */
info_unicast: boolean;
/** Number of unicast IPv6 prefixes */
info_ipv6: boolean;
/** Number of multicast prefixes */
info_multicast: boolean;
/** Is never via route servers */
info_never_via_route_servers: boolean;
/** Related network contacts */
poc_set?: number[] | any[];
/** Related network-facility connections */
netfac_set?: number[] | any[];
/** Related network-IX connections */
netixlan_set?: number[] | any[];
}

View File

@@ -0,0 +1,55 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Organization object from PeeringDB API
* Organizations are the root object in PeeringDB and represent companies or entities
*/
export interface IOrganization extends IPeeringDbBaseObject {
/** Organization ID */
id: number;
/** Organization name */
name: string;
/** Organization website */
website: string;
/** Organization notes (markdown) */
notes: string;
/** Address line 1 */
address1: string;
/** Address line 2 */
address2: string;
/** City */
city: string;
/** State/Province */
state: string;
/** Zip/Postal code */
zipcode: string;
/** Country code (ISO 3166-1 alpha-2) */
country: string;
/** Latitude */
latitude: number | null;
/** Longitude */
longitude: number | null;
/** Floor area (sqm) */
floor_area: number | null;
/** Related networks */
net_set?: number[] | any[];
/** Related facilities */
fac_set?: number[] | any[];
/** Related internet exchanges */
ix_set?: number[] | any[];
}

View File

@@ -0,0 +1,34 @@
import type { IPeeringDbBaseObject } from '../peeringdb.types.js';
/**
* Point of Contact object from PeeringDB API
* Represents a contact person for a network
*/
export interface IPointOfContact extends IPeeringDbBaseObject {
/** POC ID */
id: number;
/** Network ID */
net_id: number;
/** Network object (when depth > 0) */
net?: any;
/** Role/Position */
role: string;
/** Visible (public/private/users) */
visible: string;
/** Contact name */
name: string;
/** Phone number */
phone: string;
/** Email address */
email: string;
/** URL */
url: string;
}

View File

@@ -0,0 +1,296 @@
import { smartlog, smartrequest } from './plugins.js';
import {
type IPeeringDbResponse,
type THttpMethod,
type IQueryOptions,
} from './peeringdb.types.js';
// Import manager classes (will be created next)
import { OrganizationManager } from './peeringdb.classes.organizationmanager.js';
import { NetworkManager } from './peeringdb.classes.networkmanager.js';
import { FacilityManager } from './peeringdb.classes.facilitymanager.js';
import { ExchangeManager } from './peeringdb.classes.exchangemanager.js';
import { NetIxLanManager } from './peeringdb.classes.netixlanmanager.js';
import { NetFacManager } from './peeringdb.classes.netfacmanager.js';
import { IxLanManager } from './peeringdb.classes.ixlanmanager.js';
import { IxFacManager } from './peeringdb.classes.ixfacmanager.js';
import { IxPfxManager } from './peeringdb.classes.ixpfxmanager.js';
import { PocManager } from './peeringdb.classes.pocmanager.js';
/**
* PeeringDB API Client
* Provides access to the PeeringDB API using native fetch
*/
export class PeeringDbClient {
private apiKey: string | null = null;
private baseUrl: string = 'https://www.peeringdb.com/api';
private logger: smartlog.Smartlog;
// Manager instances
public organizations: OrganizationManager;
public networks: NetworkManager;
public facilities: FacilityManager;
public exchanges: ExchangeManager;
public netIxLans: NetIxLanManager;
public netFacs: NetFacManager;
public ixLans: IxLanManager;
public ixFacs: IxFacManager;
public ixPfxs: IxPfxManager;
public pocs: PocManager;
/**
* Create a new PeeringDB API client
* @param apiKey Optional API key for authenticated requests
*/
constructor(apiKey?: string) {
this.apiKey = apiKey || null;
this.logger = new smartlog.Smartlog({
logContext: {
company: 'Task Venture Capital',
companyunit: '@apiclient.xyz/peeringdb',
containerName: 'PeeringDbClient',
},
});
// Initialize managers
this.organizations = new OrganizationManager(this);
this.networks = new NetworkManager(this);
this.facilities = new FacilityManager(this);
this.exchanges = new ExchangeManager(this);
this.netIxLans = new NetIxLanManager(this);
this.netFacs = new NetFacManager(this);
this.ixLans = new IxLanManager(this);
this.ixFacs = new IxFacManager(this);
this.ixPfxs = new IxPfxManager(this);
this.pocs = new PocManager(this);
}
/**
* Make a request to the PeeringDB API
* @param endpoint API endpoint (e.g., 'net', 'org', 'fac')
* @param method HTTP method
* @param options Query options and parameters
* @param body Request body for POST/PUT/PATCH
* @returns Array of results (unwrapped from meta wrapper)
*/
public async request<T = any>(
endpoint: string,
method: THttpMethod = 'GET',
options: IQueryOptions = {},
body?: any
): Promise<T[]> {
const url = this.buildUrl(endpoint, options);
this.logger.log('info', `${method} ${url}`);
// Build request using fluent API
let requestClient = smartrequest.SmartRequestClient.create()
.url(url)
.header('Accept', 'application/json')
.header('User-Agent', '@apiclient.xyz/peeringdb/1.0.1 (Node.js)')
.retry(3); // Retry up to 3 times (handles 429)
// Add API key if available
if (this.apiKey) {
requestClient = requestClient.header('Authorization', `Api-Key ${this.apiKey}`);
}
// Add body for POST/PUT/PATCH requests
if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
requestClient = requestClient.json(body);
}
try {
// Execute the appropriate HTTP method
let response;
switch (method) {
case 'GET':
response = await requestClient.get();
break;
case 'POST':
response = await requestClient.post();
break;
case 'PUT':
response = await requestClient.put();
break;
case 'DELETE':
response = await requestClient.delete();
break;
case 'PATCH':
response = await requestClient.patch();
break;
default:
throw new Error(`Unsupported HTTP method: ${method}`);
}
// Response body is automatically parsed as JSON by smartrequest
const data: IPeeringDbResponse<T> = response.body;
// Check meta status
if (data?.meta?.status === 'error') {
this.logger.log('error', `API returned error: ${data.meta.message}`);
throw new Error(`PeeringDB API error: ${data.meta.message}`);
}
// Handle pagination if autoPaginate is enabled
if (options.autoPaginate && data.data.length === (options.limit || 0)) {
const allResults = [...data.data];
let currentSkip = (options.skip || 0) + data.data.length;
while (true) {
const nextOptions = { ...options, skip: currentSkip };
const nextUrl = this.buildUrl(endpoint, nextOptions);
const nextResponse = await smartrequest.SmartRequestClient.create()
.url(nextUrl)
.header('Accept', 'application/json')
.header('User-Agent', '@apiclient.xyz/peeringdb/1.0.1 (Node.js)')
.header('Authorization', this.apiKey ? `Api-Key ${this.apiKey}` : '')
.retry(3)
.get();
const nextData: IPeeringDbResponse<T> = nextResponse.body;
if (nextData.data.length === 0) {
break;
}
allResults.push(...nextData.data);
currentSkip += nextData.data.length;
// Safety check to prevent infinite loops
if (nextData.data.length < (options.limit || 0)) {
break;
}
}
return allResults;
}
// Return unwrapped data array
return data.data;
} catch (error) {
this.logger.log('error', `Request failed: ${error.message}`);
throw error;
}
}
/**
* Build API URL with query parameters
*/
private buildUrl(endpoint: string, options: IQueryOptions = {}): string {
const url = new URL(`${this.baseUrl}/${endpoint}`);
// Add standard query parameters
if (options.limit !== undefined) {
url.searchParams.set('limit', options.limit.toString());
}
if (options.skip !== undefined) {
url.searchParams.set('skip', options.skip.toString());
}
if (options.fields) {
url.searchParams.set('fields', options.fields);
}
if (options.depth !== undefined) {
url.searchParams.set('depth', options.depth.toString());
}
if (options.since !== undefined) {
url.searchParams.set('since', options.since.toString());
}
// Add any additional query parameters (field filters, etc.)
Object.keys(options).forEach((key) => {
if (
!['limit', 'skip', 'fields', 'depth', 'since', 'autoPaginate'].includes(key)
) {
const value = options[key];
if (value !== undefined && value !== null) {
url.searchParams.set(key, value.toString());
}
}
});
return url.toString();
}
/**
* Convenience methods for common operations
*/
public convenience = {
/**
* Get a network by ASN
*/
getNetworkByAsn: async (asn: number) => {
const results = await this.request('net', 'GET', { asn });
return results[0] || null;
},
/**
* Get an organization by ID
*/
getOrganizationById: async (id: number) => {
return this.organizations.getById(id);
},
/**
* Get a facility by ID
*/
getFacilityById: async (id: number) => {
return this.facilities.getById(id);
},
/**
* Get an exchange by ID
*/
getExchangeById: async (id: number) => {
return this.exchanges.getById(id);
},
/**
* Search networks by name
*/
searchNetworks: async (query: string) => {
return this.request('net', 'GET', { name__contains: query });
},
/**
* Search facilities by name
*/
searchFacilities: async (query: string) => {
return this.request('fac', 'GET', { name__contains: query });
},
/**
* Get all facilities where a network is present
*/
getNetworkFacilities: async (asn: number) => {
const network = await this.convenience.getNetworkByAsn(asn);
if (!network) {
return [];
}
return this.request('netfac', 'GET', { net_id: network.id, depth: 2 });
},
/**
* Get all exchanges where a network peers
*/
getNetworkExchanges: async (asn: number) => {
const network = await this.convenience.getNetworkByAsn(asn);
if (!network) {
return [];
}
return this.request('netixlan', 'GET', { net_id: network.id, depth: 2 });
},
/**
* Get all networks present at a facility
*/
getFacilityNetworks: async (facId: number) => {
return this.request('netfac', 'GET', { fac_id: facId, depth: 2 });
},
};
}

View File

@@ -0,0 +1,102 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IExchange } from './interfaces/peeringdb.api.exchange.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for Internet Exchange resources
*/
export class ExchangeManager {
constructor(private client: PeeringDbClient) {}
/**
* List exchanges with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', options);
}
/**
* Get a single exchange by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IExchange | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IExchange>('ix', 'GET', options);
return results[0] || null;
}
/**
* Search exchanges by name
*/
async searchByName(name: string, options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', {
...options,
name__contains: name,
});
}
/**
* Get exchanges by country
*/
async getByCountry(country: string, options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', {
...options,
country,
});
}
/**
* Get exchanges by city
*/
async getByCity(city: string, options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', {
...options,
city__contains: city,
});
}
/**
* Get exchanges by region/continent
*/
async getByRegion(region: string, options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', {
...options,
region_continent: region,
});
}
/**
* Get exchanges by organization ID
*/
async getByOrgId(orgId: number, options: IQueryOptions = {}): Promise<IExchange[]> {
return this.client.request<IExchange>('ix', 'GET', {
...options,
org_id: orgId,
});
}
/**
* Create a new exchange (requires authentication)
*/
async create(data: Partial<IExchange>): Promise<IExchange> {
const results = await this.client.request<IExchange>('ix', 'POST', {}, data);
return results[0];
}
/**
* Update an exchange (requires authentication)
*/
async update(id: number, data: Partial<IExchange>): Promise<IExchange> {
const results = await this.client.request<IExchange>(`ix/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete an exchange (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('ix', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,92 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IFacility } from './interfaces/peeringdb.api.facility.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for Facility resources
*/
export class FacilityManager {
constructor(private client: PeeringDbClient) {}
/**
* List facilities with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IFacility[]> {
return this.client.request<IFacility>('fac', 'GET', options);
}
/**
* Get a single facility by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IFacility | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IFacility>('fac', 'GET', options);
return results[0] || null;
}
/**
* Search facilities by name
*/
async searchByName(name: string, options: IQueryOptions = {}): Promise<IFacility[]> {
return this.client.request<IFacility>('fac', 'GET', {
...options,
name__contains: name,
});
}
/**
* Get facilities by country
*/
async getByCountry(country: string, options: IQueryOptions = {}): Promise<IFacility[]> {
return this.client.request<IFacility>('fac', 'GET', {
...options,
country,
});
}
/**
* Get facilities by city
*/
async getByCity(city: string, options: IQueryOptions = {}): Promise<IFacility[]> {
return this.client.request<IFacility>('fac', 'GET', {
...options,
city__contains: city,
});
}
/**
* Get facilities by organization ID
*/
async getByOrgId(orgId: number, options: IQueryOptions = {}): Promise<IFacility[]> {
return this.client.request<IFacility>('fac', 'GET', {
...options,
org_id: orgId,
});
}
/**
* Create a new facility (requires authentication)
*/
async create(data: Partial<IFacility>): Promise<IFacility> {
const results = await this.client.request<IFacility>('fac', 'POST', {}, data);
return results[0];
}
/**
* Update a facility (requires authentication)
*/
async update(id: number, data: Partial<IFacility>): Promise<IFacility> {
const results = await this.client.request<IFacility>(`fac/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete a facility (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('fac', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,72 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IIxFac } from './interfaces/peeringdb.api.ixfac.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for IxFac resources (IX-facility connections)
*/
export class IxFacManager {
constructor(private client: PeeringDbClient) {}
/**
* List IX-facility connections with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IIxFac[]> {
return this.client.request<IIxFac>('ixfac', 'GET', options);
}
/**
* Get a single IX-facility connection by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IIxFac | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IIxFac>('ixfac', 'GET', options);
return results[0] || null;
}
/**
* Get IX-facility connections by exchange ID
*/
async getByIxId(ixId: number, options: IQueryOptions = {}): Promise<IIxFac[]> {
return this.client.request<IIxFac>('ixfac', 'GET', {
...options,
ix_id: ixId,
});
}
/**
* Get IX-facility connections by facility ID
*/
async getByFacId(facId: number, options: IQueryOptions = {}): Promise<IIxFac[]> {
return this.client.request<IIxFac>('ixfac', 'GET', {
...options,
fac_id: facId,
});
}
/**
* Create a new IX-facility connection (requires authentication)
*/
async create(data: Partial<IIxFac>): Promise<IIxFac> {
const results = await this.client.request<IIxFac>('ixfac', 'POST', {}, data);
return results[0];
}
/**
* Update an IX-facility connection (requires authentication)
*/
async update(id: number, data: Partial<IIxFac>): Promise<IIxFac> {
const results = await this.client.request<IIxFac>(`ixfac/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete an IX-facility connection (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('ixfac', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,62 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IIxLan } from './interfaces/peeringdb.api.ixlan.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for IxLan resources (IX LAN information)
*/
export class IxLanManager {
constructor(private client: PeeringDbClient) {}
/**
* List IX LANs with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IIxLan[]> {
return this.client.request<IIxLan>('ixlan', 'GET', options);
}
/**
* Get a single IX LAN by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IIxLan | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IIxLan>('ixlan', 'GET', options);
return results[0] || null;
}
/**
* Get IX LANs by exchange ID
*/
async getByIxId(ixId: number, options: IQueryOptions = {}): Promise<IIxLan[]> {
return this.client.request<IIxLan>('ixlan', 'GET', {
...options,
ix_id: ixId,
});
}
/**
* Create a new IX LAN (requires authentication)
*/
async create(data: Partial<IIxLan>): Promise<IIxLan> {
const results = await this.client.request<IIxLan>('ixlan', 'POST', {}, data);
return results[0];
}
/**
* Update an IX LAN (requires authentication)
*/
async update(id: number, data: Partial<IIxLan>): Promise<IIxLan> {
const results = await this.client.request<IIxLan>(`ixlan/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete an IX LAN (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('ixlan', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,72 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IIxPfx } from './interfaces/peeringdb.api.ixpfx.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for IxPfx resources (IX IP prefixes)
*/
export class IxPfxManager {
constructor(private client: PeeringDbClient) {}
/**
* List IX prefixes with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IIxPfx[]> {
return this.client.request<IIxPfx>('ixpfx', 'GET', options);
}
/**
* Get a single IX prefix by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IIxPfx | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IIxPfx>('ixpfx', 'GET', options);
return results[0] || null;
}
/**
* Get IX prefixes by IX LAN ID
*/
async getByIxLanId(ixlanId: number, options: IQueryOptions = {}): Promise<IIxPfx[]> {
return this.client.request<IIxPfx>('ixpfx', 'GET', {
...options,
ixlan_id: ixlanId,
});
}
/**
* Get IX prefixes by protocol (IPv4/IPv6)
*/
async getByProtocol(protocol: string, options: IQueryOptions = {}): Promise<IIxPfx[]> {
return this.client.request<IIxPfx>('ixpfx', 'GET', {
...options,
protocol,
});
}
/**
* Create a new IX prefix (requires authentication)
*/
async create(data: Partial<IIxPfx>): Promise<IIxPfx> {
const results = await this.client.request<IIxPfx>('ixpfx', 'POST', {}, data);
return results[0];
}
/**
* Update an IX prefix (requires authentication)
*/
async update(id: number, data: Partial<IIxPfx>): Promise<IIxPfx> {
const results = await this.client.request<IIxPfx>(`ixpfx/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete an IX prefix (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('ixpfx', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,72 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { INetFac } from './interfaces/peeringdb.api.netfac.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for NetFac resources (network presence at facility)
*/
export class NetFacManager {
constructor(private client: PeeringDbClient) {}
/**
* List network-facility connections with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<INetFac[]> {
return this.client.request<INetFac>('netfac', 'GET', options);
}
/**
* Get a single network-facility connection by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<INetFac | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<INetFac>('netfac', 'GET', options);
return results[0] || null;
}
/**
* Get network-facility connections by network ID
*/
async getByNetId(netId: number, options: IQueryOptions = {}): Promise<INetFac[]> {
return this.client.request<INetFac>('netfac', 'GET', {
...options,
net_id: netId,
});
}
/**
* Get network-facility connections by facility ID
*/
async getByFacId(facId: number, options: IQueryOptions = {}): Promise<INetFac[]> {
return this.client.request<INetFac>('netfac', 'GET', {
...options,
fac_id: facId,
});
}
/**
* Create a new network-facility connection (requires authentication)
*/
async create(data: Partial<INetFac>): Promise<INetFac> {
const results = await this.client.request<INetFac>('netfac', 'POST', {}, data);
return results[0];
}
/**
* Update a network-facility connection (requires authentication)
*/
async update(id: number, data: Partial<INetFac>): Promise<INetFac> {
const results = await this.client.request<INetFac>(`netfac/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete a network-facility connection (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('netfac', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,82 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { INetIxLan } from './interfaces/peeringdb.api.netixlan.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for NetIxLan resources (network presence at IX)
*/
export class NetIxLanManager {
constructor(private client: PeeringDbClient) {}
/**
* List network-IX connections with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<INetIxLan[]> {
return this.client.request<INetIxLan>('netixlan', 'GET', options);
}
/**
* Get a single network-IX connection by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<INetIxLan | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<INetIxLan>('netixlan', 'GET', options);
return results[0] || null;
}
/**
* Get network-IX connections by network ID
*/
async getByNetId(netId: number, options: IQueryOptions = {}): Promise<INetIxLan[]> {
return this.client.request<INetIxLan>('netixlan', 'GET', {
...options,
net_id: netId,
});
}
/**
* Get network-IX connections by IX LAN ID
*/
async getByIxLanId(ixlanId: number, options: IQueryOptions = {}): Promise<INetIxLan[]> {
return this.client.request<INetIxLan>('netixlan', 'GET', {
...options,
ixlan_id: ixlanId,
});
}
/**
* Get network-IX connections by ASN
*/
async getByAsn(asn: number, options: IQueryOptions = {}): Promise<INetIxLan[]> {
return this.client.request<INetIxLan>('netixlan', 'GET', {
...options,
asn,
});
}
/**
* Create a new network-IX connection (requires authentication)
*/
async create(data: Partial<INetIxLan>): Promise<INetIxLan> {
const results = await this.client.request<INetIxLan>('netixlan', 'POST', {}, data);
return results[0];
}
/**
* Update a network-IX connection (requires authentication)
*/
async update(id: number, data: Partial<INetIxLan>): Promise<INetIxLan> {
const results = await this.client.request<INetIxLan>(`netixlan/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete a network-IX connection (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('netixlan', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,104 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { INetwork } from './interfaces/peeringdb.api.network.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for Network resources
*/
export class NetworkManager {
constructor(private client: PeeringDbClient) {}
/**
* List networks with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<INetwork[]> {
return this.client.request<INetwork>('net', 'GET', options);
}
/**
* Get a single network by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<INetwork | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<INetwork>('net', 'GET', options);
return results[0] || null;
}
/**
* Get a network by ASN
*/
async getByAsn(asn: number, depth?: 0 | 1 | 2): Promise<INetwork | null> {
const options: IQueryOptions = { asn };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<INetwork>('net', 'GET', options);
return results[0] || null;
}
/**
* Search networks by name
*/
async searchByName(name: string, options: IQueryOptions = {}): Promise<INetwork[]> {
return this.client.request<INetwork>('net', 'GET', {
...options,
name__contains: name,
});
}
/**
* Get networks by organization ID
*/
async getByOrgId(orgId: number, options: IQueryOptions = {}): Promise<INetwork[]> {
return this.client.request<INetwork>('net', 'GET', {
...options,
org_id: orgId,
});
}
/**
* Search networks by IRR as-set
*/
async searchByIrrAsSet(irrAsSet: string, options: IQueryOptions = {}): Promise<INetwork[]> {
return this.client.request<INetwork>('net', 'GET', {
...options,
irr_as_set__contains: irrAsSet,
});
}
/**
* Get networks by peering policy
*/
async getByPolicy(policy: string, options: IQueryOptions = {}): Promise<INetwork[]> {
return this.client.request<INetwork>('net', 'GET', {
...options,
policy_general: policy,
});
}
/**
* Create a new network (requires authentication)
*/
async create(data: Partial<INetwork>): Promise<INetwork> {
const results = await this.client.request<INetwork>('net', 'POST', {}, data);
return results[0];
}
/**
* Update a network (requires authentication)
*/
async update(id: number, data: Partial<INetwork>): Promise<INetwork> {
const results = await this.client.request<INetwork>(`net/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete a network (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('net', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,72 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IOrganization } from './interfaces/peeringdb.api.organization.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for Organization resources
*/
export class OrganizationManager {
constructor(private client: PeeringDbClient) {}
/**
* List organizations with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IOrganization[]> {
return this.client.request<IOrganization>('org', 'GET', options);
}
/**
* Get a single organization by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IOrganization | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IOrganization>('org', 'GET', options);
return results[0] || null;
}
/**
* Search organizations by name
*/
async searchByName(name: string, options: IQueryOptions = {}): Promise<IOrganization[]> {
return this.client.request<IOrganization>('org', 'GET', {
...options,
name__contains: name,
});
}
/**
* Get organizations by country
*/
async getByCountry(country: string, options: IQueryOptions = {}): Promise<IOrganization[]> {
return this.client.request<IOrganization>('org', 'GET', {
...options,
country,
});
}
/**
* Create a new organization (requires authentication)
*/
async create(data: Partial<IOrganization>): Promise<IOrganization> {
const results = await this.client.request<IOrganization>('org', 'POST', {}, data);
return results[0];
}
/**
* Update an organization (requires authentication)
*/
async update(id: number, data: Partial<IOrganization>): Promise<IOrganization> {
const results = await this.client.request<IOrganization>(`org/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete an organization (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('org', 'DELETE', { id });
}
}

View File

@@ -0,0 +1,72 @@
import type { PeeringDbClient } from './peeringdb.classes.client.js';
import type { IPointOfContact } from './interfaces/peeringdb.api.poc.js';
import type { IQueryOptions } from './peeringdb.types.js';
/**
* Manager for Point of Contact resources
*/
export class PocManager {
constructor(private client: PeeringDbClient) {}
/**
* List points of contact with optional filtering
*/
async list(options: IQueryOptions = {}): Promise<IPointOfContact[]> {
return this.client.request<IPointOfContact>('poc', 'GET', options);
}
/**
* Get a single point of contact by ID
*/
async getById(id: number, depth?: 0 | 1 | 2): Promise<IPointOfContact | null> {
const options: IQueryOptions = { id };
if (depth !== undefined) {
options.depth = depth;
}
const results = await this.client.request<IPointOfContact>('poc', 'GET', options);
return results[0] || null;
}
/**
* Get points of contact by network ID
*/
async getByNetId(netId: number, options: IQueryOptions = {}): Promise<IPointOfContact[]> {
return this.client.request<IPointOfContact>('poc', 'GET', {
...options,
net_id: netId,
});
}
/**
* Get points of contact by role
*/
async getByRole(role: string, options: IQueryOptions = {}): Promise<IPointOfContact[]> {
return this.client.request<IPointOfContact>('poc', 'GET', {
...options,
role__contains: role,
});
}
/**
* Create a new point of contact (requires authentication)
*/
async create(data: Partial<IPointOfContact>): Promise<IPointOfContact> {
const results = await this.client.request<IPointOfContact>('poc', 'POST', {}, data);
return results[0];
}
/**
* Update a point of contact (requires authentication)
*/
async update(id: number, data: Partial<IPointOfContact>): Promise<IPointOfContact> {
const results = await this.client.request<IPointOfContact>(`poc/${id}`, 'PUT', {}, data);
return results[0];
}
/**
* Delete a point of contact (requires authentication)
*/
async delete(id: number): Promise<void> {
await this.client.request('poc', 'DELETE', { id });
}
}

108
ts/peeringdb.types.ts Normal file
View File

@@ -0,0 +1,108 @@
/**
* Core types for PeeringDB API client
*/
/**
* HTTP methods supported by the API
*/
export type THttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
/**
* Depth levels for nested object expansion
* - 0: No expansion (IDs only)
* - 1: Expand to IDs for related objects
* - 2: Full object expansion for related objects
*/
export type TDepth = 0 | 1 | 2;
/**
* Meta information returned by the PeeringDB API
*/
export interface IPeeringDbMeta {
status: 'ok' | 'error';
message?: string;
generated?: number;
}
/**
* Standard API response wrapper from PeeringDB
*/
export interface IPeeringDbResponse<T> {
meta: IPeeringDbMeta;
data: T[];
}
/**
* Query options for API requests
*/
export interface IQueryOptions {
/** Limit the number of results */
limit?: number;
/** Skip/offset for pagination */
skip?: number;
/** Comma-separated list of fields to return */
fields?: string;
/** Depth of nested object expansion (0, 1, or 2) */
depth?: TDepth;
/** Unix timestamp - only return objects updated since this time */
since?: number;
/** Auto-paginate through all results (default: false) */
autoPaginate?: boolean;
/** Additional query parameters (field filters, etc.) */
[key: string]: any;
}
/**
* Field filter operators for string fields
*/
export interface IStringFilters {
/** Field contains value */
__contains?: string;
/** Field starts with value */
__startswith?: string;
/** Field is in list of values */
__in?: string[];
}
/**
* Field filter operators for number fields
*/
export interface INumberFilters {
/** Field is less than value */
__lt?: number;
/** Field is less than or equal to value */
__lte?: number;
/** Field is greater than value */
__gt?: number;
/** Field is greater than or equal to value */
__gte?: number;
/** Field is in list of values */
__in?: number[];
}
/**
* Base fields present in all PeeringDB objects
*/
export interface IPeeringDbBaseObject {
id: number;
status: string;
created: string;
updated: string;
}
/**
* Common status values for PeeringDB objects
*/
export type TStatus = 'ok' | 'pending' | 'deleted';

5
ts/plugins.ts Normal file
View File

@@ -0,0 +1,5 @@
// push.rocks scope
import * as smartlog from '@push.rocks/smartlog';
import * as smartrequest from '@push.rocks/smartrequest';
export { smartlog, smartrequest };