Skip to content

API Overview

Subnetter provides a programmatic API that allows you to use its functionality in your own Node.js applications. This overview documents the available packages, key components, and usage patterns.

Packages

Subnetter is organized as a monorepo with multiple packages:

@subnetter/core

Core CIDR allocation engine, configuration loading, and output utilities. This is the main package for programmatic use.

@subnetter/cli

Command-line interface for generate, validate, analyze, and export operations.

@subnetter/netbox

NetBox IPAM integration for exporting allocations to NetBox.

@subnetter/cidr-utils

Low-level CIDR utilities for validation, parsing, and calculation.

Installation

Terminal window
# Core package (for programmatic use)
npm install @subnetter/core
# NetBox integration
npm install @subnetter/netbox
# CIDR utilities only
npm install @subnetter/cidr-utils

Quick Start

import {
loadConfig,
CidrAllocator,
writeAllocationsToCsv
} from '@subnetter/core';
async function main() {
// Load and validate configuration
const config = await loadConfig('./config.json');
// Generate allocations
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
// Write to CSV
await writeAllocationsToCsv(allocations, './allocations.csv');
console.log(`Generated ${allocations.length} subnet allocations`);
}
main();

@subnetter/core

The core package provides the main functionality for CIDR allocation.

Key Exports

ExportTypeDescription
CidrAllocatorClassMain class for hierarchical CIDR allocation
loadConfigFunctionLoad and validate configuration files (JSON/YAML)
validateConfigFunctionValidate configuration objects programmatically
writeAllocationsToCsvFunctionWrite allocations to CSV file
filterAllocationsByProviderFunctionFilter allocations by cloud provider
validateNoOverlappingCidrsFunctionValidate allocations for CIDR overlaps

Types and Interfaces

import type {
Config, // Main configuration interface
Allocation, // Output allocation record
Account, // Account configuration
CloudConfig, // Cloud-specific configuration
SubnetTypesMap, // Subnet type definitions
RawConfig, // Raw config before normalization
} from '@subnetter/core';

Configuration Loading

import { loadConfig } from '@subnetter/core';
// Load from JSON or YAML file
const config = await loadConfig('./config.json');
const yamlConfig = await loadConfig('./config.yaml');

CIDR Allocation

import { CidrAllocator } from '@subnetter/core';
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
// Each allocation contains:
allocations.forEach(alloc => {
console.log({
account: alloc.accountName,
provider: alloc.cloudProvider,
region: alloc.regionName,
az: alloc.availabilityZone,
subnet: alloc.subnetCidr,
role: alloc.subnetRole,
usableIps: alloc.usableIps
});
});

Error Handling

Subnetter provides a comprehensive error hierarchy:

import {
SubnetterError, // Base error class
ConfigurationError, // Configuration validation errors
AllocationError, // CIDR allocation failures
IOError, // File I/O errors
ValidationError, // General validation errors
CloudProviderError, // Cloud provider specific errors
ErrorCode // Error code enum
} from '@subnetter/core';
try {
const config = await loadConfig('./config.json');
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
} catch (error) {
if (error instanceof ConfigurationError) {
console.error(`Config error [${error.code}]: ${error.message}`);
console.log('Help:', error.getHelpText());
} else if (error instanceof AllocationError) {
console.error('Allocation failed:', error.message);
}
}

Logging

import {
createLogger,
configureLogger,
LogLevel,
parseLogLevel
} from '@subnetter/core';
// Configure global logging
configureLogger({
level: LogLevel.DEBUG,
useColor: true,
timestamps: true
});
// Create a named logger
const logger = createLogger('MyApp');
logger.info('Starting allocation...');
logger.debug('Config loaded:', config);

CIDR Utilities (from core)

The core package re-exports common CIDR utilities:

import {
isValidIpv4Cidr,
calculateUsableIps,
doCidrsOverlap,
subdivideIpv4Cidr,
calculateOptimalPrefixLength,
calculateRequiredPrefixLength,
ContiguousAllocator,
HierarchicalAllocator
} from '@subnetter/core';
// Validate CIDR format
isValidIpv4Cidr('10.0.0.0/24'); // true
// Calculate usable IPs
calculateUsableIps('10.0.0.0/24'); // 254
// Check for overlap
doCidrsOverlap('10.0.0.0/24', '10.0.0.128/25'); // true
// Subdivide a CIDR
subdivideIpv4Cidr('10.0.0.0/24', 26);
// ['10.0.0.0/26', '10.0.0.64/26', '10.0.0.128/26', '10.0.0.192/26']

@subnetter/netbox

The NetBox package provides integration with NetBox IPAM.

Key Exports

ExportTypeDescription
NetBoxClientClassREST API client for NetBox
NetBoxExporterClassExport allocations to NetBox
NetBoxApiErrorClassAPI error with status code

NetBox Client

import { NetBoxClient } from '@subnetter/netbox';
const client = new NetBoxClient({
url: 'https://netbox.example.com',
token: process.env.NETBOX_TOKEN!,
timeout: 30000, // optional
});
// Test connection
const connected = await client.testConnection();
// List prefixes
const prefixes = await client.prefixes.listAll();
// Create a prefix
const prefix = await client.prefixes.create({
prefix: '10.1.0.0/16',
status: 'reserved',
description: 'Production VPC',
});
// Other resources: sites, tenants, roles, tags, locations, aggregates

Exporting to NetBox

import { CidrAllocator, loadConfig } from '@subnetter/core';
import { NetBoxClient, NetBoxExporter } from '@subnetter/netbox';
// Generate allocations
const config = await loadConfig('./config.json');
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
// Create client and exporter
const client = new NetBoxClient({
url: 'https://netbox.example.com',
token: process.env.NETBOX_TOKEN!,
});
const exporter = new NetBoxExporter(client);
// Dry run first
const preview = await exporter.export(allocations, {
dryRun: true,
baseCidr: config.baseCidr,
});
console.log(`Would create: ${preview.summary.created}`);
console.log(`Would update: ${preview.summary.updated}`);
// Apply changes
const result = await exporter.export(allocations, {
dryRun: false,
baseCidr: config.baseCidr,
status: 'reserved', // Prefix status
prune: false, // Delete orphaned prefixes
});

NetBox Object Mapping

Subnetter maps cloud concepts to NetBox objects:

SubnetterNetBoxDescription
Base CIDRAggregateTop-level IP block
Cloud ProviderSite GroupAWS, Azure, GCP
Cloud RegionSiteus-east-1, eastus
Availability ZoneLocationus-east-1a
AccountTenantOwnership boundary
Subnet TypeRolepublic, private
Subnet CIDRPrefixActual allocation

@subnetter/cidr-utils

Low-level CIDR utilities for validation, parsing, and calculation.

IP Address Utilities

import {
ipv4ToNumber,
numberToIpv4,
createIpAddress,
getNetworkAddress,
getBroadcastAddress,
calculateSubnetMask
} from '@subnetter/cidr-utils';
// Convert between formats
const num = ipv4ToNumber('192.168.1.1'); // 3232235777
const ip = numberToIpv4(3232235777); // '192.168.1.1'
// Create IP address object
const ipObj = createIpAddress('192.168.1.1');
console.log(ipObj.asNumber); // 3232235777
console.log(ipObj.asString); // '192.168.1.1'
console.log(ipObj.octets); // [192, 168, 1, 1]
// Network calculations
getNetworkAddress('10.0.0.15/24'); // IpAddress for '10.0.0.0'
getBroadcastAddress('10.0.0.0/24'); // IpAddress for '10.0.0.255'
calculateSubnetMask(24); // 4294967040 (0xFFFFFF00)

CIDR Validation

import {
isValidIpv4Cidr,
validateIpv4Cidr,
CidrError
} from '@subnetter/cidr-utils';
// Simple validation
isValidIpv4Cidr('10.0.0.0/24'); // true
isValidIpv4Cidr('10.0.0.0/33'); // false
// Validation with error details
try {
validateIpv4Cidr('10.0.0.0/33');
} catch (error) {
if (error instanceof CidrError) {
console.error(error.message); // 'Invalid prefix length...'
console.error(error.type); // 'INVALID_PREFIX_LENGTH'
}
}

CIDR Parsing

import {
parseIpv4Cidr,
normalizeCidr
} from '@subnetter/cidr-utils';
// Parse CIDR into components
const parsed = parseIpv4Cidr('10.0.0.0/24');
console.log(parsed.address); // '10.0.0.0'
console.log(parsed.prefixLength); // 24
// Normalize CIDR to network address
normalizeCidr('10.0.0.15/24'); // '10.0.0.0/24'

Subnet Calculations

import {
calculateSubnetInfo,
getCidrRange,
checkCidrOverlap,
subdivideCidr,
calculateSupernet
} from '@subnetter/cidr-utils';
// Get subnet information
const info = calculateSubnetInfo('10.0.0.0/24');
console.log(info.totalIps); // 256
console.log(info.usableIps); // 254
// Get IP range
const range = getCidrRange('10.0.0.0/24');
console.log(range.start.asString); // '10.0.0.0'
console.log(range.end.asString); // '10.0.0.255'
// Check for overlap
checkCidrOverlap('10.0.0.0/24', '10.0.0.128/25'); // true
// Subdivide a CIDR (by prefix delta)
const result = subdivideCidr('10.0.0.0/24', 2); // Add 2 bits
console.log(result.subnets); // ['10.0.0.0/26', '10.0.0.64/26', ...]
console.log(result.bitsAdded); // 2
// Calculate supernet
calculateSupernet('10.0.1.0/24', 8); // '10.0.0.0/16'

TypeScript Support

All packages are written in TypeScript and provide full type definitions:

import type {
Config,
Allocation,
Account,
CloudConfig
} from '@subnetter/core';
import type {
NetBoxConfig,
Prefix,
ExportResult
} from '@subnetter/netbox';
import type {
IpAddress,
SubnetInfo,
IpRange
} from '@subnetter/cidr-utils';

Complete Example

import {
loadConfig,
CidrAllocator,
writeAllocationsToCsv,
filterAllocationsByProvider,
validateNoOverlappingCidrs,
SubnetterError,
ConfigurationError
} from '@subnetter/core';
async function main() {
try {
// Load configuration
const config = await loadConfig('./config.json');
console.log(`Loaded config with ${config.accounts.length} accounts`);
// Generate allocations
const allocator = new CidrAllocator(config);
const allocations = allocator.generateAllocations();
console.log(`Generated ${allocations.length} allocations`);
// Validate for overlaps
const validation = validateNoOverlappingCidrs(allocations);
if (!validation.valid) {
console.error(`Found ${validation.overlaps.length} overlaps!`);
process.exit(1);
}
// Filter by provider if needed
const awsOnly = filterAllocationsByProvider(allocations, 'aws');
console.log(`AWS allocations: ${awsOnly.length}`);
// Write to CSV
await writeAllocationsToCsv(allocations, './allocations.csv');
console.log('Written to allocations.csv');
} catch (error) {
if (error instanceof ConfigurationError) {
console.error(`Configuration error: ${error.message}`);
console.log('Hint:', error.getHelpText());
} else if (error instanceof SubnetterError) {
console.error(`Error [${error.code}]: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
process.exit(1);
}
}
main();