{"version":3,"file":"index.cjs","sources":["../../../src/validate.ts","../../../src/uniformly-distributed-subnets.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { Cidr, IpAddress } from 'cidr-calc';\nimport { UniformlyDistributedSubnetsArguments } from './types.js';\n\nexport function validate({\n  neededSubnets,\n  cidr,\n}: UniformlyDistributedSubnetsArguments): {\n  parentCidr: Cidr;\n} {\n  let parentCidr: Cidr;\n  let availableSpace: number;\n  try {\n    const [ipRaw, cidrNumberRaw] = cidr.split('/');\n    assert(typeof ipRaw === 'string');\n    assert(\n      typeof cidrNumberRaw === 'string' &&\n        Number.isInteger(Number(cidrNumberRaw)),\n    );\n    parentCidr = new Cidr(IpAddress.of(ipRaw), Number(cidrNumberRaw));\n    availableSpace = 32 - parentCidr.prefixLen;\n  } catch {\n    throw new TypeError(`Invalid CIDR provided: ${cidr}`);\n  }\n\n  if (\n    typeof availableSpace !== 'number' ||\n    Number.isNaN(availableSpace) ||\n    !Number.isInteger(availableSpace) ||\n    availableSpace < 0 ||\n    availableSpace > 32\n  ) {\n    throw new TypeError(\n      'Expected `cidr` number to be a positive integer between 1 and 32, representing the number of available bits in the parent CIDR block',\n    );\n  }\n\n  if (\n    typeof neededSubnets !== 'number' ||\n    Number.isNaN(neededSubnets) ||\n    !Number.isInteger(neededSubnets) ||\n    neededSubnets < 1\n  ) {\n    throw new TypeError(`Expected \"neededSubnets\" to be a positive integer.`);\n  }\n\n  if (neededSubnets > 2 ** availableSpace) {\n    throw new TypeError(\n      `The number of subnets needed (${neededSubnets.toLocaleString()}) exceeds the available space in the parent CIDR block (${(2 ** availableSpace).toLocaleString()})`,\n    );\n  }\n  return {\n    parentCidr,\n  };\n}\n","import { Cidr, IpRange } from 'cidr-calc';\nimport { UniformlyDistributedSubnetsArguments } from './types.js';\nimport { validate } from './validate.js';\n\n/**\n * Allocate subnet CIDRs as uniformly as possible across the available space.\n */\nexport function uniformlyDistributedSubnets({\n  neededSubnets,\n  cidr,\n}: UniformlyDistributedSubnetsArguments): {\n  subnetCidrs: Cidr[];\n  optimalSubnetCidrPrefixLength: number;\n  maxIpsPerSubnet: number;\n  parentCidr: Cidr;\n} {\n  const { parentCidr } = validate({ neededSubnets, cidr });\n\n  /**\n   * Where x is the optimal subnet CIDR number\n   *       y is parentCidrNumber\n   *       z is neededSubnets\n   *\n   * Theoretical max IPs = 2^(32-y) / z\n   * Optimal CIDR number IP space = 2^(32-x)\n   *\n   * 2^(32-x) = 2^(32-y) / z\n   *        x = 32 - log2(2^(32-y) / z)\n   *\n   * but we can only do the closest power of 2, so we need to round up `x` to get the CIDR number closest to the theoretical max.\n   *\n   * x = ceil(32 - log2(2^(32-y) / z))\n   */\n  const optimalSubnetCidrPrefixLength = Math.ceil(\n    32 - Math.log2(2 ** (32 - parentCidr.prefixLen) / neededSubnets),\n  );\n\n  // Get the actual subnet CIDR blocks needed\n  const subnetCidrs: Cidr[] = [];\n  let currentCidr: Cidr;\n  let currentRange: IpRange;\n  let nextStartIpAddr = parentCidr.toIpRange().startIpAddr;\n  for (let index = 0; index < neededSubnets; index++) {\n    currentCidr = new Cidr(nextStartIpAddr, optimalSubnetCidrPrefixLength);\n    currentRange = currentCidr.toIpRange();\n    subnetCidrs.push(currentCidr);\n    nextStartIpAddr = currentRange.endIpAddr.next();\n  }\n\n  const maxIpsPerSubnet = 2 ** (32 - optimalSubnetCidrPrefixLength);\n\n  return {\n    subnetCidrs,\n    optimalSubnetCidrPrefixLength,\n    maxIpsPerSubnet,\n    parentCidr,\n  };\n}\n"],"names":["Cidr","IpAddress"],"mappings":";;;;;SAIgB,QAAQ,CAAC,EACvB,aAAa,EACb,IAAI,GACiC,EAAA;AAGrC,IAAA,IAAI,UAAgB;AACpB,IAAA,IAAI,cAAsB;AAC1B,IAAA,IAAI;AACF,QAAA,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC9C,QAAA,MAAM,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AACjC,QAAA,MAAM,CACJ,OAAO,aAAa,KAAK,QAAQ;YAC/B,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAC1C;AACD,QAAA,UAAU,GAAG,IAAIA,aAAI,CAACC,kBAAS,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;AACjE,QAAA,cAAc,GAAG,EAAE,GAAG,UAAU,CAAC,SAAS;;AAC1C,IAAA,MAAM;AACN,QAAA,MAAM,IAAI,SAAS,CAAC,0BAA0B,IAAI,CAAA,CAAE,CAAC;;IAGvD,IACE,OAAO,cAAc,KAAK,QAAQ;AAClC,QAAA,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;AAC5B,QAAA,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;AACjC,QAAA,cAAc,GAAG,CAAC;QAClB,cAAc,GAAG,EAAE,EACnB;AACA,QAAA,MAAM,IAAI,SAAS,CACjB,sIAAsI,CACvI;;IAGH,IACE,OAAO,aAAa,KAAK,QAAQ;AACjC,QAAA,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;AAC3B,QAAA,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC;QAChC,aAAa,GAAG,CAAC,EACjB;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,CAAA,kDAAA,CAAoD,CAAC;;AAG3E,IAAA,IAAI,aAAa,GAAG,CAAC,IAAI,cAAc,EAAE;AACvC,QAAA,MAAM,IAAI,SAAS,CACjB,iCAAiC,aAAa,CAAC,cAAc,EAAE,CAAA,wDAAA,EAA2D,CAAC,CAAC,IAAI,cAAc,EAAE,cAAc,EAAE,CAAA,CAAA,CAAG,CACpK;;IAEH,OAAO;QACL,UAAU;KACX;AACH;;AClDA;;AAEG;SACa,2BAA2B,CAAC,EAC1C,aAAa,EACb,IAAI,GACiC,EAAA;AAMrC,IAAA,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAExD;;;;;;;;;;;;;;AAcG;IACH,MAAM,6BAA6B,GAAG,IAAI,CAAC,IAAI,CAC7C,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,CACjE;;IAGD,MAAM,WAAW,GAAW,EAAE;AAC9B,IAAA,IAAI,WAAiB;AACrB,IAAA,IAAI,YAAqB;IACzB,IAAI,eAAe,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC,WAAW;AACxD,IAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,aAAa,EAAE,KAAK,EAAE,EAAE;QAClD,WAAW,GAAG,IAAID,aAAI,CAAC,eAAe,EAAE,6BAA6B,CAAC;AACtE,QAAA,YAAY,GAAG,WAAW,CAAC,SAAS,EAAE;AACtC,QAAA,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;AAC7B,QAAA,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE;;IAGjD,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,GAAG,6BAA6B,CAAC;IAEjE,OAAO;QACL,WAAW;QACX,6BAA6B;QAC7B,eAAe;QACf,UAAU;KACX;AACH;;;;"}