@uruhalushia/rule-converter-napi
v0.3.2
Published
Node.js bindings for converting mihomo, sing-box, Egern, and generic rule sets.
Readme
@uruhalushia/rule-converter-napi
Node.js bindings for the Rust rule converter. Inputs are auto-detected from payload/file content by default, and can be overridden with input options when needed.
Build
pnpm --dir napi install
pnpm --dir napi buildUsage
import { writeFileSync } from 'node:fs'
import {
fileToBuf,
detectFile,
listAsnNumbers,
listGeoipCountries,
listGeoipDatCountries,
listGeositeCodes,
matchFile,
strToBuf,
strToStr,
} from '@uruhalushia/rule-converter-napi'
const payload = `
payload:
- DOMAIN,example.com
- DOMAIN-SUFFIX,example.net
- IP-CIDR,192.168.1.0/24,no-resolve
`
const mrs = strToBuf(payload, {
inputTarget: 'mihomo',
inputFormat: 'yaml',
inputBehavior: 'classical',
outputTarget: 'mihomo',
outputFormat: 'mrs',
outputBehavior: 'domain',
})
writeFileSync('domain.mrs', mrs.outputs.domain)
const text = strToStr(payload, {
inputTarget: 'mihomo',
inputFormat: 'yaml',
inputBehavior: 'classical',
outputTarget: 'general',
outputFormat: 'ruleset',
outputBehavior: 'classical',
})
console.log(text.outputs.classical)
const srs = fileToBuf('rules.yaml', {
outputTarget: 'sing-box',
outputFormat: 'srs',
outputBehavior: 'classical',
})
writeFileSync('classical.srs', srs.outputs.classical)
const geoip = fileToBuf('country.mmdb', {
inputTarget: 'geoip',
outputTarget: 'general',
outputFormat: 'ipset',
countries: ['cn'],
})
writeFileSync('cn.list', geoip.outputs.cn)
const singDb = fileToBuf('country.mmdb', {
inputTarget: 'geoip',
outputTarget: 'geoip',
outputFormat: 'sing-db',
})
writeFileSync('country.sing.db', singDb.outputs.db)
console.log(listGeoipCountries('country.mmdb'))
console.log(listGeoipDatCountries('geoip.dat'))
console.log(listGeositeCodes('geosite.dat'))
console.log(listAsnNumbers('GeoLite2-ASN.mmdb'))
console.log(detectFile('geosite.dat'))const match = matchFile('rules.list', 'ads.example.com', {
inputTarget: 'general',
inputFormat: 'text',
inputBehavior: 'classical',
})
console.log(match.matched, match.rules)
const route = matchFile('config.yaml', 'github.com')
console.log(route.matched, route.rules)outputs is a name-keyed object. Rule output keys are usually behavior names such as domain, ip, or classical. DB export keys are country codes, ASN numbers, or db for a generated database.
API
bufToBuf(input, options?): converts aUint8Arraypayload and returns byte outputs.strToBuf(input, options?): converts a string payload and returns byte outputs.fileToBuf(input, options?): converts one input file path and returns byte outputs.bufToStr(input, options?): converts aUint8Arraypayload and returns UTF-8 text outputs.strToStr(input, options?): converts a string payload and returns UTF-8 text outputs.fileToStr(input, options?): converts one input file path and returns UTF-8 text outputs.detectBuf(input)/detectStr(input)/detectFile(input): returns{ kind, target, format, behavior }without converting input.listGeoipCountries(input): reads a GeoIP MMDB file path and returns sorted country codes.listGeoipCountriesFromBuffer(input): reads GeoIP MMDB bytes and returns sorted country codes.listGeoipDatCountries(input)/listGeoipDatCountriesFromBuffer(input): reads V2Raygeoip.datand returns sorted country codes.listGeositeCodes(input)/listGeositeCodesFromBuffer(input): reads V2Raygeosite.dator sing-geosite DB and returns sorted site codes.listAsnNumbers(input): reads an ASN MMDB file path and returns sorted ASN numbers.listAsnNumbersFromBuffer(input): reads ASN MMDB bytes and returns sorted ASN numbers.matchBuf(input, query, options?)/matchStr(input, query, options?)/matchFile(input, query, options?): matches a domain or IP against rules and returns{ matched, query, kind, rules }. Mihomo config input is supported for providerpath,file://, and HTTP(S)url. HTTP providers are downloaded into memory for matching.
interface AnyConvertOptions {
inputTarget?: 'mihomo' | 'general' | 'egern' | 'sing-box' | 'geoip' | 'geosite' | 'asn'
inputFormat?: 'yaml' | 'mrs' | 'text' | 'adguard' | 'json' | 'srs' | 'domainset' | 'ruleset' | 'ipset' | 'mmdb' | 'sing-db' | 'metadb' | 'dat' | 'sing-geosite'
inputBehavior?: 'auto' | 'domain' | 'ip' | 'classical'
outputTarget?: 'mihomo' | 'general' | 'egern' | 'sing-box' | 'geoip' | 'geosite' | 'asn'
outputFormat?: 'mrs' | 'text' | 'adguard' | 'yaml' | 'json' | 'srs' | 'domainset' | 'ruleset' | 'ipset' | 'mmdb' | 'sing-db' | 'metadb' | 'dat' | 'sing-geosite'
outputBehavior?: 'auto' | 'domain' | 'ip' | 'classical'
countries?: string[]
codes?: string[]
asns?: number[]
split?: boolean
country?: string
code?: string
asn?: number
}
interface AnyBufferResult {
kind: 'rules' | 'db'
outputs: Record<string, Uint8Array>
info: Record<string, AnyOutputInfo>
skipped: SkippedRule[]
}
interface AnyStringResult {
kind: 'rules' | 'db'
outputs: Record<string, string>
info: Record<string, AnyOutputInfo>
skipped: SkippedRule[]
}Defaults:
inputTarget: auto-detected rule input unless set togeoip,geosite, orasninputFormat: auto-detectedinputBehavior:autooutputTarget:mihomofor rule input,generalfor DB-to-rules export, or the same DB target for DB conversionoutputFormat:mrsfor rule input,ipsetfor DB-to-rules export, ormmdbfor DB conversionoutputBehavior: selected from the target/format defaultsplit:truefor DB-to-rules export
DB conversions use the same functions as rule conversions:
inputTarget: 'geoip',outputTarget: 'general' | 'mihomo' | 'egern' | 'sing-box'exports GeoIP contents as rule sets.inputTarget: 'asn',outputTarget: 'general' | 'mihomo' | 'egern' | 'sing-box'exports ASN contents as rule sets.inputTarget: 'geoip',outputTarget: 'geoip'converts GeoIP DB bytes betweenmmdb,sing-db,metadb, and V2Raydat.inputTarget: 'geosite',outputTarget: 'general' | 'mihomo' | 'egern' | 'sing-box'exports V2Raygeosite.dator sing-geosite DB as rule sets.inputTarget: 'geosite',outputTarget: 'geosite'converts and filters geosite DB betweendatandsing-geosite.inputTarget: 'asn',outputTarget: 'asn'normalizes ASN MMDB bytes. ASN DB output only supportsmmdb.- Rule input can build DB output with
outputTarget: 'geoip'pluscountry,outputTarget: 'geosite'pluscode, oroutputTarget: 'asn'plusasn.
mihomo + text/yaml + domain uses mihomo/Clash domain wildcard syntax such as +.example.com; general + domainset + domain uses domain-set syntax where .example.com means the domain itself and all subdomains.
no-resolve is preserved only between mixed text, mihomo YAML, and Egern ruleset YAML. MRS, sing-box JSON/SRS, and domain-set output do not have a field for it.
