+14
-32
| //#region index.d.ts | ||
| type DnszDnsRecord = { | ||
| /**The lowercase DNS name without a trailing dot, e.g. `"example.com"`. */ | ||
| name: string; | ||
| /** The TTL in seconds, e.g. `60`. */ | ||
| ttl: number; | ||
| /** The DNS class, e.g. `"IN"`. */ | ||
| class: string; | ||
| /** The record type, e.g. `"A"`. */ | ||
| type: string; | ||
| /** The record content, e.g. `"2001:db8::1"` or `"example.com."`. */ | ||
| content: string; | ||
| /** A comment, e.g. `"a comment"`, `null` if absent. */ | ||
| /**The lowercase DNS name without a trailing dot, e.g. `"example.com"`. */name: string; /** The TTL in seconds, e.g. `60`. */ | ||
| ttl: number; /** The DNS class, e.g. `"IN"`. */ | ||
| class: string; /** The record type, e.g. `"A"`. */ | ||
| type: string; /** The record content, e.g. `"2001:db8::1"` or `"example.com."`. */ | ||
| content: string; /** A comment, e.g. `"a comment"`, `null` if absent. */ | ||
| comment: string | null; | ||
| }; | ||
| type DnszDnsData = { | ||
| /** Array of `record` */ | ||
| records: Array<DnszDnsRecord>; | ||
| /** The value of `$ORIGIN` in the zone file. */ | ||
| origin?: string; | ||
| /** The value of `$TTL` in the zone file. */ | ||
| ttl?: number; | ||
| /** An optional header at the start of the file. Can be multiline. Does not include comment markers. */ | ||
| /** Array of `record` */records: Array<DnszDnsRecord>; /** The value of `$ORIGIN` in the zone file. */ | ||
| origin?: string; /** The value of `$TTL` in the zone file. */ | ||
| ttl?: number; /** An optional header at the start of the file. Can be multiline. Does not include comment markers. */ | ||
| header?: string; | ||
| }; | ||
| type DnszParseOptions = { | ||
| /** When specified, replaces any `@` in `name` or `content` with it. */ | ||
| replaceOrigin?: string | null; | ||
| /** When true, emit `\r\n` instead of `\n` in `header`. */ | ||
| crlf?: boolean; | ||
| /** Default class when absent. */ | ||
| defaultClass?: string; | ||
| /** Default TTL when absent and `$TTL` is not present. */ | ||
| defaultTTL?: number; | ||
| /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. */ | ||
| /** When specified, replaces any `@` in `name` or `content` with it. */replaceOrigin?: string | null; /** When true, emit `\r\n` instead of `\n` in `header`. */ | ||
| crlf?: boolean; /** Default class when absent. */ | ||
| defaultClass?: string; /** Default TTL when absent and `$TTL` is not present. */ | ||
| defaultTTL?: number; /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. */ | ||
| dots?: boolean; | ||
| }; | ||
| type DnszStringifyOptions = { | ||
| /** Whether to group records into sections. */ | ||
| sections?: boolean; | ||
| /** When `true`, emit `\r\n` instead of `\n` for the resulting zone file. */ | ||
| crlf?: boolean; | ||
| /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. Default: `false`. */ | ||
| /** Whether to group records into sections. */sections?: boolean; /** When `true`, emit `\r\n` instead of `\n` for the resulting zone file. */ | ||
| crlf?: boolean; /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. Default: `false`. */ | ||
| dots?: boolean; | ||
@@ -45,0 +27,0 @@ }; |
+34
-7
@@ -46,9 +46,9 @@ //#region index.ts | ||
| const next = () => string[++i]; | ||
| const append = (value$1) => { | ||
| state.value = value$1; | ||
| if (value$1) state.block.stash[state.block.stash.length - 1] += value$1; | ||
| const append = (value) => { | ||
| state.value = value; | ||
| if (value) state.block.stash[state.block.stash.length - 1] += value; | ||
| }; | ||
| const closeIndex = (value$1, startIdx) => { | ||
| let idx = string.indexOf(value$1, startIdx); | ||
| if (idx > -1 && string[idx - 1] === "\\") idx = closeIndex(value$1, idx + 1); | ||
| const closeIndex = (value, startIdx) => { | ||
| let idx = string.indexOf(value, startIdx); | ||
| if (idx > -1 && string[idx - 1] === "\\") idx = closeIndex(value, idx + 1); | ||
| return idx; | ||
@@ -169,4 +169,31 @@ }; | ||
| const rawLines = str.split(/\r?\n/).map((l) => l.trim()); | ||
| const lines = rawLines.filter((l) => Boolean(l) && !l.startsWith(";")); | ||
| let lines = rawLines.filter((l) => Boolean(l) && !l.startsWith(";")); | ||
| const newline = crlf ? "\r\n" : "\n"; | ||
| const combinedLines = []; | ||
| let i = 0; | ||
| while (i < lines.length) { | ||
| const line = lines[i]; | ||
| if (line.includes("(") && !line.includes(")")) { | ||
| const [firstLineContent] = splitContentAndComment(line); | ||
| let combined = firstLineContent || ""; | ||
| let foundClosing = false; | ||
| i++; | ||
| while (i < lines.length) { | ||
| const [cleanedContent] = splitContentAndComment(lines[i]); | ||
| const cleanedLine = (cleanedContent || "").trim(); | ||
| if (cleanedLine) combined += ` ${cleanedLine}`; | ||
| i++; | ||
| if (cleanedLine.includes(")")) { | ||
| foundClosing = true; | ||
| break; | ||
| } | ||
| } | ||
| combined = combined.replace(foundClosing ? /[()]/g : /\(/g, "").replace(/\s+/g, " ").trim(); | ||
| combinedLines.push(combined); | ||
| } else { | ||
| combinedLines.push(line); | ||
| i++; | ||
| } | ||
| } | ||
| lines = combinedLines; | ||
| const headerLines = []; | ||
@@ -173,0 +200,0 @@ let valid = false; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","names":["value: string","node: any","state: Record<string, any>","value","indexes: Array<number>","parts: Array<string>","data: Partial<DnszDnsData>","headerLines: Array<string>","valid: boolean","recordsByType: Record<string, Array<DnszDnsRecord>>","vars: Array<string>"],"sources":["../index.ts"],"sourcesContent":["export type DnszDnsRecord = {\n /**The lowercase DNS name without a trailing dot, e.g. `\"example.com\"`. */\n name: string;\n /** The TTL in seconds, e.g. `60`. */\n ttl: number;\n /** The DNS class, e.g. `\"IN\"`. */\n class: string;\n /** The record type, e.g. `\"A\"`. */\n type: string;\n /** The record content, e.g. `\"2001:db8::1\"` or `\"example.com.\"`. */\n content: string;\n /** A comment, e.g. `\"a comment\"`, `null` if absent. */\n comment: string | null;\n};\n\nexport type DnszDnsData = {\n /** Array of `record` */\n records: Array<DnszDnsRecord>;\n /** The value of `$ORIGIN` in the zone file. */\n origin?: string;\n /** The value of `$TTL` in the zone file. */\n ttl?: number;\n /** An optional header at the start of the file. Can be multiline. Does not include comment markers. */\n header?: string;\n};\n\nexport type DnszParseOptions = {\n /** When specified, replaces any `@` in `name` or `content` with it. */\n replaceOrigin?: string | null;\n /** When true, emit `\\r\\n` instead of `\\n` in `header`. */\n crlf?: boolean;\n /** Default class when absent. */\n defaultClass?: string;\n /** Default TTL when absent and `$TTL` is not present. */\n defaultTTL?: number;\n /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. */\n dots?: boolean;\n};\n\nexport type DnszStringifyOptions = {\n /** Whether to group records into sections. */\n sections?: boolean;\n /** When `true`, emit `\\r\\n` instead of `\\n` for the resulting zone file. */\n crlf?: boolean;\n /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. Default: `false`. */\n dots?: boolean;\n};\n\n// List of types and places where they have name-like content, used on the `dot` option.\nconst nameLike = {\n ALIAS: [0],\n ANAME: [0],\n CNAME: [0],\n DNAME: [0],\n MX: [1],\n NAPTR: [5],\n NS: [0],\n NSEC: [0],\n PTR: [0],\n RP: [0, 1],\n RRSIG: [7],\n SIG: [7],\n SOA: [0, 1],\n SRV: [3],\n TKEY: [0],\n TSIG: [0],\n};\n\nfunction normalize(name: string) {\n name = (name || \"\").toLowerCase();\n if (name.endsWith(\".\") && name.length > 1) {\n name = name.substring(0, name.length - 1);\n }\n return name.replace(/\\.{2,}/g, \".\").replace(/@\\./, \"@\");\n}\n\nfunction splitString(input: string, {separator = \" \", quotes = []}: {separator?: string, quotes?: Array<string>} = {}) {\n const ast = {type: \"root\", nodes: [], stash: [\"\"]};\n const stack = [ast];\n const string = input;\n let value: string;\n let node: any;\n let i = -1;\n const state: Record<string, any> = {\n input,\n separator,\n stack,\n prev: () => string[i - 1],\n next: () => string[i + 1],\n };\n\n const block = () => (state.block = stack[stack.length - 1]);\n const peek = () => string[i + 1];\n const next = () => string[++i];\n const append = (value: string) => {\n state.value = value;\n if (value) {\n state.block.stash[state.block.stash.length - 1] += value;\n }\n };\n\n const closeIndex = (value: string, startIdx: number) => {\n let idx = string.indexOf(value, startIdx);\n if (idx > -1 && string[idx - 1] === \"\\\\\") {\n idx = closeIndex(value, idx + 1);\n }\n return idx;\n };\n\n while (i < string.length - 1) {\n state.value = value = next();\n state.index = i;\n block();\n\n if (value === \"\\\\\") {\n if (peek() === \"\\\\\") {\n append(value + next());\n } else {\n append(value);\n append(next());\n }\n continue;\n }\n\n if (quotes.includes(value)) {\n const pos = i + 1;\n const idx = closeIndex(value, pos);\n\n if (idx > -1) {\n append(value);\n append(string.slice(pos, idx));\n append(string[idx]);\n i = idx;\n continue;\n }\n\n append(value);\n continue;\n }\n\n if (value === separator && state.block.type === \"root\") {\n state.block.stash.push(\"\");\n continue;\n }\n\n append(value);\n }\n\n node = stack.pop();\n while (node !== ast) {\n value = (node.parent.stash.pop() + node.stash.join(\".\"));\n node.parent.stash = node.parent.stash.concat(value.split(\".\"));\n node = stack.pop();\n }\n\n return node.stash;\n}\n\nfunction denormalize(name: string) {\n if (!name.endsWith(\".\") && name.length > 1) {\n name = `${name}.`;\n }\n return name.replace(/\\.{2,}/g, \".\").replace(/@\\./, \"@\");\n}\n\nfunction esc(str: string) {\n return str.replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\");\n}\n\nfunction addDots(content: string, indexes: Array<number>): string {\n const parts = splitString(content, {\n quotes: [`\"`],\n separator: \" \",\n }).map((s: string) => s.trim()).filter(Boolean);\n for (const index of indexes) {\n if (!parts[index].endsWith(\".\")) {\n parts[index] += \".\";\n }\n }\n return parts.join(\" \");\n}\n\nfunction parseTTL(ttl: string | number, def?: number): number {\n if (typeof ttl === \"number\") {\n return ttl;\n }\n\n if (def && !ttl) {\n return def;\n }\n\n if (/s$/i.test(ttl)) {\n ttl = parseInt(ttl);\n } else if (/m$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60;\n } else if (/h$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60;\n } else if (/d$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60 * 24;\n } else if (/w$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60 * 24 * 7;\n } else {\n ttl = parseInt(ttl);\n }\n\n return ttl;\n}\n\ntype FormatOpts = {\n origin: string,\n newline: string,\n sections: boolean,\n dots: boolean,\n};\n\nfunction format(records: Array<DnszDnsRecord | undefined>, type: string | null, {origin, newline, sections, dots}: FormatOpts) {\n let str = ``;\n\n if (sections && type) {\n str += `;; ${type} Records${newline}`;\n }\n\n for (const record of records || []) {\n if (!record) continue;\n let name = normalize(record.name || \"\");\n\n if (origin) {\n if (name === origin) {\n name = \"@\";\n } else if (name.endsWith(origin)) {\n // subdomain, remove origin and trailing dots\n name = normalize(name.replace(new RegExp(`${esc(`${origin}.`)}?$`, \"gm\"), \"\"));\n } else {\n // assume it's a subdomain, remove trailing dots\n name = normalize(name);\n }\n } else {\n if (name.includes(\".\")) {\n // assume it's a fqdn, add trailing dots\n name = denormalize(name);\n } else {\n name = normalize(name);\n }\n }\n\n let content = record.content;\n if (dots && Object.keys(nameLike).includes(record.type)) {\n const indexes: Array<number> = nameLike[record.type as keyof typeof nameLike];\n content = addDots(content, indexes);\n }\n\n const fields = [\n name,\n record.ttl,\n record.class,\n record.type,\n content,\n ];\n\n if (record.comment) {\n fields.push(`; ${record.comment}`);\n }\n\n str += `${fields.join(\"\\t\")}${newline}`;\n }\n return `${str}${sections ? newline : \"\"}`;\n}\n\nfunction splitContentAndComment(str?: string): [content: string | null, comment: string | null | undefined] {\n if (!str) return [null, null];\n const splitted = splitString(str, {\n quotes: [`\"`],\n separator: \";\",\n });\n\n let parts: Array<string>;\n if (splitted.length > 2) { // more than one semicolon\n parts = [splitted[0], splitted.slice(1).join(\";\")];\n } else {\n parts = splitted;\n }\n\n parts = parts.map((part: string) => (part || \"\").trim()).filter(Boolean);\n\n if (parts.length <= 2) {\n return [parts[0] || null, parts[1] || null];\n } else {\n const comment = parts.pop();\n const content = parts.join(\"; \");\n return [content, comment];\n }\n}\n\n/** Parse a string of a DNS zone file and returns a `data` object. */\nexport function parseZone(str: string, {replaceOrigin = null, crlf = false, defaultTTL = 60, defaultClass = \"IN\", dots = false}: DnszParseOptions = {}): DnszDnsData {\n const data: Partial<DnszDnsData> = {};\n const rawLines = str.split(/\\r?\\n/).map(l => l.trim());\n const lines = rawLines.filter(l => Boolean(l) && !l.startsWith(\";\"));\n const newline = crlf ? \"\\r\\n\" : \"\\n\";\n\n // search for header\n const headerLines: Array<string> = [];\n let valid: boolean = false;\n for (const [index, line] of rawLines.entries()) {\n if (line.startsWith(\";;\")) {\n headerLines.push(line.substring(2).trim());\n } else {\n const prev = rawLines[index - 1];\n if (line === \"\" && index > 1 && prev.startsWith(\";;\")) {\n valid = true;\n break;\n }\n }\n }\n if (valid && headerLines.length) {\n data.header = headerLines.join(newline);\n }\n\n // https://regex101.com/r/aKuGyZ/3\n const reLine = /^([a-z0-9_.\\-@*]+)?\\s*([0-9]+[smhdw]?)?\\s*([a-z]+)?\\s+([a-z]+[0-9]*)?\\s+(.+)$/i;\n\n // create records\n data.records = [];\n for (const line of lines) {\n const parsedOrigin = (/\\$ORIGIN\\s+(\\S+)/.exec(line) || [])[1];\n if (parsedOrigin && !data.origin) {\n data.origin = normalize(parsedOrigin);\n }\n\n const parsedTtl = (/\\$TTL\\s+(\\S+)/.exec(line) || [])[1];\n if (line.startsWith(\"$TTL \") && !data.ttl) {\n data.ttl = parseTTL(normalize(parsedTtl));\n }\n\n let [, name, ttl, cls, type, contentAndComment] = reLine.exec(line) || [];\n if (!ttl && name && /[0-9]+/.test(name)) { // no name\n ttl = name;\n name = \"\";\n }\n if (cls && !type) { // class is optional\n type = cls;\n cls = \"\";\n }\n if (!cls) {\n cls = defaultClass;\n }\n let [content, comment] = splitContentAndComment(contentAndComment);\n\n if (!name) {\n name = \"\";\n }\n\n if (!cls || !type || !content) {\n continue;\n }\n\n type = type.toUpperCase();\n content = (content || \"\").trim();\n if (dots && Object.keys(nameLike).includes(type)) {\n content = addDots(content, nameLike[type as keyof typeof nameLike]);\n }\n\n data.records.push({\n name: normalize(([\"\", \"@\"].includes(name) && data.origin) ? data.origin : name),\n ttl: parseTTL(ttl, data.ttl !== undefined ? data.ttl : defaultTTL),\n class: cls.toUpperCase(),\n type,\n content,\n comment: (comment || \"\").trim() || null,\n });\n }\n\n if (replaceOrigin) {\n data.origin = replaceOrigin;\n }\n\n return data as DnszDnsData;\n}\n\n/** Parse a `data` object and return a string with the zone file contents. */\nexport function stringifyZone(data: DnszDnsData, {crlf = false, sections = true, dots = false}: DnszStringifyOptions = {}): string {\n const recordsByType: Record<string, Array<DnszDnsRecord>> = {};\n const newline = crlf ? \"\\r\\n\" : \"\\n\";\n\n if (sections) {\n for (const record of data.records) {\n if (!recordsByType[record.type]) recordsByType[record.type] = [];\n recordsByType[record.type].push(record);\n }\n }\n\n let output = \"\";\n if (data.header) {\n output += `${data.header\n .split(/\\r?\\n/)\n .map(l => l.trim())\n .map(l => l ? `;; ${l}` : \";;\")\n .join(newline)\n .trim()}${newline}${newline}`;\n }\n\n const vars: Array<string> = [];\n if (data.origin) vars.push(`$ORIGIN ${denormalize(data.origin)}`);\n if (data.ttl) vars.push(`$TTL ${data.ttl}`);\n if (vars.length) output += `${vars.join(newline)}${newline}${newline}`;\n\n const origin = normalize(data.origin || \"\");\n if (sections) {\n if (recordsByType.SOA) {\n output += format(recordsByType.SOA, \"SOA\", {origin, newline, sections, dots});\n delete recordsByType.SOA;\n }\n\n for (const type of Object.keys(recordsByType).sort()) {\n output += format(recordsByType[type], type, {origin, newline, sections, dots});\n }\n } else {\n const recordsSOA = data.records.filter(r => r.type === \"SOA\");\n const recordsMinusSOA = data.records.filter(r => r.type !== \"SOA\");\n\n output += format(recordsSOA, null, {origin, newline, sections, dots});\n output += format(recordsMinusSOA, null, {origin, newline, sections, dots});\n }\n\n return `${output.trim()}${newline}`;\n}\n"],"mappings":"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"} | ||
| {"version":3,"file":"index.js","names":[],"sources":["../index.ts"],"sourcesContent":["export type DnszDnsRecord = {\n /**The lowercase DNS name without a trailing dot, e.g. `\"example.com\"`. */\n name: string;\n /** The TTL in seconds, e.g. `60`. */\n ttl: number;\n /** The DNS class, e.g. `\"IN\"`. */\n class: string;\n /** The record type, e.g. `\"A\"`. */\n type: string;\n /** The record content, e.g. `\"2001:db8::1\"` or `\"example.com.\"`. */\n content: string;\n /** A comment, e.g. `\"a comment\"`, `null` if absent. */\n comment: string | null;\n};\n\nexport type DnszDnsData = {\n /** Array of `record` */\n records: Array<DnszDnsRecord>;\n /** The value of `$ORIGIN` in the zone file. */\n origin?: string;\n /** The value of `$TTL` in the zone file. */\n ttl?: number;\n /** An optional header at the start of the file. Can be multiline. Does not include comment markers. */\n header?: string;\n};\n\nexport type DnszParseOptions = {\n /** When specified, replaces any `@` in `name` or `content` with it. */\n replaceOrigin?: string | null;\n /** When true, emit `\\r\\n` instead of `\\n` in `header`. */\n crlf?: boolean;\n /** Default class when absent. */\n defaultClass?: string;\n /** Default TTL when absent and `$TTL` is not present. */\n defaultTTL?: number;\n /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. */\n dots?: boolean;\n};\n\nexport type DnszStringifyOptions = {\n /** Whether to group records into sections. */\n sections?: boolean;\n /** When `true`, emit `\\r\\n` instead of `\\n` for the resulting zone file. */\n crlf?: boolean;\n /** Ensure trailing dots on FQDNs in content. Supports a limited amount of record types. Default: `false`. */\n dots?: boolean;\n};\n\n// List of types and places where they have name-like content, used on the `dot` option.\nconst nameLike = {\n ALIAS: [0],\n ANAME: [0],\n CNAME: [0],\n DNAME: [0],\n MX: [1],\n NAPTR: [5],\n NS: [0],\n NSEC: [0],\n PTR: [0],\n RP: [0, 1],\n RRSIG: [7],\n SIG: [7],\n SOA: [0, 1],\n SRV: [3],\n TKEY: [0],\n TSIG: [0],\n};\n\nfunction normalize(name: string) {\n name = (name || \"\").toLowerCase();\n if (name.endsWith(\".\") && name.length > 1) {\n name = name.substring(0, name.length - 1);\n }\n return name.replace(/\\.{2,}/g, \".\").replace(/@\\./, \"@\");\n}\n\nfunction splitString(input: string, {separator = \" \", quotes = []}: {separator?: string, quotes?: Array<string>} = {}) {\n const ast = {type: \"root\", nodes: [], stash: [\"\"]};\n const stack = [ast];\n const string = input;\n let value: string;\n let node: any;\n let i = -1;\n const state: Record<string, any> = {\n input,\n separator,\n stack,\n prev: () => string[i - 1],\n next: () => string[i + 1],\n };\n\n const block = () => (state.block = stack[stack.length - 1]);\n const peek = () => string[i + 1];\n const next = () => string[++i];\n const append = (value: string) => {\n state.value = value;\n if (value) {\n state.block.stash[state.block.stash.length - 1] += value;\n }\n };\n\n const closeIndex = (value: string, startIdx: number) => {\n let idx = string.indexOf(value, startIdx);\n if (idx > -1 && string[idx - 1] === \"\\\\\") {\n idx = closeIndex(value, idx + 1);\n }\n return idx;\n };\n\n while (i < string.length - 1) {\n state.value = value = next();\n state.index = i;\n block();\n\n if (value === \"\\\\\") {\n if (peek() === \"\\\\\") {\n append(value + next());\n } else {\n append(value);\n append(next());\n }\n continue;\n }\n\n if (quotes.includes(value)) {\n const pos = i + 1;\n const idx = closeIndex(value, pos);\n\n if (idx > -1) {\n append(value);\n append(string.slice(pos, idx));\n append(string[idx]);\n i = idx;\n continue;\n }\n\n append(value);\n continue;\n }\n\n if (value === separator && state.block.type === \"root\") {\n state.block.stash.push(\"\");\n continue;\n }\n\n append(value);\n }\n\n node = stack.pop();\n while (node !== ast) {\n value = (node.parent.stash.pop() + node.stash.join(\".\"));\n node.parent.stash = node.parent.stash.concat(value.split(\".\"));\n node = stack.pop();\n }\n\n return node.stash;\n}\n\nfunction denormalize(name: string) {\n if (!name.endsWith(\".\") && name.length > 1) {\n name = `${name}.`;\n }\n return name.replace(/\\.{2,}/g, \".\").replace(/@\\./, \"@\");\n}\n\nfunction esc(str: string) {\n return str.replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\");\n}\n\nfunction addDots(content: string, indexes: Array<number>): string {\n const parts = splitString(content, {\n quotes: [`\"`],\n separator: \" \",\n }).map((s: string) => s.trim()).filter(Boolean);\n for (const index of indexes) {\n if (!parts[index].endsWith(\".\")) {\n parts[index] += \".\";\n }\n }\n return parts.join(\" \");\n}\n\nfunction parseTTL(ttl: string | number, def?: number): number {\n if (typeof ttl === \"number\") {\n return ttl;\n }\n\n if (def && !ttl) {\n return def;\n }\n\n if (/s$/i.test(ttl)) {\n ttl = parseInt(ttl);\n } else if (/m$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60;\n } else if (/h$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60;\n } else if (/d$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60 * 24;\n } else if (/w$/i.test(ttl)) {\n ttl = parseInt(ttl) * 60 * 60 * 24 * 7;\n } else {\n ttl = parseInt(ttl);\n }\n\n return ttl;\n}\n\ntype FormatOpts = {\n origin: string,\n newline: string,\n sections: boolean,\n dots: boolean,\n};\n\nfunction format(records: Array<DnszDnsRecord | undefined>, type: string | null, {origin, newline, sections, dots}: FormatOpts) {\n let str = ``;\n\n if (sections && type) {\n str += `;; ${type} Records${newline}`;\n }\n\n for (const record of records || []) {\n if (!record) continue;\n let name = normalize(record.name || \"\");\n\n if (origin) {\n if (name === origin) {\n name = \"@\";\n } else if (name.endsWith(origin)) {\n // subdomain, remove origin and trailing dots\n name = normalize(name.replace(new RegExp(`${esc(`${origin}.`)}?$`, \"gm\"), \"\"));\n } else {\n // assume it's a subdomain, remove trailing dots\n name = normalize(name);\n }\n } else {\n if (name.includes(\".\")) {\n // assume it's a fqdn, add trailing dots\n name = denormalize(name);\n } else {\n name = normalize(name);\n }\n }\n\n let content = record.content;\n if (dots && Object.keys(nameLike).includes(record.type)) {\n const indexes: Array<number> = nameLike[record.type as keyof typeof nameLike];\n content = addDots(content, indexes);\n }\n\n const fields = [\n name,\n record.ttl,\n record.class,\n record.type,\n content,\n ];\n\n if (record.comment) {\n fields.push(`; ${record.comment}`);\n }\n\n str += `${fields.join(\"\\t\")}${newline}`;\n }\n return `${str}${sections ? newline : \"\"}`;\n}\n\nfunction splitContentAndComment(str?: string): [content: string | null, comment: string | null | undefined] {\n if (!str) return [null, null];\n const splitted = splitString(str, {\n quotes: [`\"`],\n separator: \";\",\n });\n\n let parts: Array<string>;\n if (splitted.length > 2) { // more than one semicolon\n parts = [splitted[0], splitted.slice(1).join(\";\")];\n } else {\n parts = splitted;\n }\n\n parts = parts.map((part: string) => (part || \"\").trim()).filter(Boolean);\n\n if (parts.length <= 2) {\n return [parts[0] || null, parts[1] || null];\n } else {\n const comment = parts.pop();\n const content = parts.join(\"; \");\n return [content, comment];\n }\n}\n\n/** Parse a string of a DNS zone file and returns a `data` object. */\nexport function parseZone(str: string, {replaceOrigin = null, crlf = false, defaultTTL = 60, defaultClass = \"IN\", dots = false}: DnszParseOptions = {}): DnszDnsData {\n const data: Partial<DnszDnsData> = {};\n const rawLines = str.split(/\\r?\\n/).map(l => l.trim());\n let lines = rawLines.filter(l => Boolean(l) && !l.startsWith(\";\"));\n const newline = crlf ? \"\\r\\n\" : \"\\n\";\n\n // mulitline SOA support\n const combinedLines: Array<string> = [];\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n if (line.includes(\"(\") && !line.includes(\")\")) {\n const [firstLineContent] = splitContentAndComment(line);\n let combined = firstLineContent || \"\";\n let foundClosing = false;\n i++;\n while (i < lines.length) {\n const [cleanedContent] = splitContentAndComment(lines[i]);\n const cleanedLine = (cleanedContent || \"\").trim();\n if (cleanedLine) combined += ` ${cleanedLine}`;\n i++;\n if (cleanedLine.includes(\")\")) {\n foundClosing = true;\n break;\n }\n }\n combined = combined.replace(foundClosing ? /[()]/g : /\\(/g, \"\").replace(/\\s+/g, \" \").trim();\n combinedLines.push(combined);\n } else {\n combinedLines.push(line);\n i++;\n }\n }\n lines = combinedLines;\n\n // search for header\n const headerLines: Array<string> = [];\n let valid: boolean = false;\n for (const [index, line] of rawLines.entries()) {\n if (line.startsWith(\";;\")) {\n headerLines.push(line.substring(2).trim());\n } else {\n const prev = rawLines[index - 1];\n if (line === \"\" && index > 1 && prev.startsWith(\";;\")) {\n valid = true;\n break;\n }\n }\n }\n if (valid && headerLines.length) {\n data.header = headerLines.join(newline);\n }\n\n // https://regex101.com/r/aKuGyZ/3\n const reLine = /^([a-z0-9_.\\-@*]+)?\\s*([0-9]+[smhdw]?)?\\s*([a-z]+)?\\s+([a-z]+[0-9]*)?\\s+(.+)$/i;\n\n // create records\n data.records = [];\n for (const line of lines) {\n const parsedOrigin = (/\\$ORIGIN\\s+(\\S+)/.exec(line) || [])[1];\n if (parsedOrigin && !data.origin) {\n data.origin = normalize(parsedOrigin);\n }\n\n const parsedTtl = (/\\$TTL\\s+(\\S+)/.exec(line) || [])[1];\n if (line.startsWith(\"$TTL \") && !data.ttl) {\n data.ttl = parseTTL(normalize(parsedTtl));\n }\n\n let [, name, ttl, cls, type, contentAndComment] = reLine.exec(line) || [];\n if (!ttl && name && /[0-9]+/.test(name)) { // no name\n ttl = name;\n name = \"\";\n }\n if (cls && !type) { // class is optional\n type = cls;\n cls = \"\";\n }\n if (!cls) {\n cls = defaultClass;\n }\n let [content, comment] = splitContentAndComment(contentAndComment);\n\n if (!name) {\n name = \"\";\n }\n\n if (!cls || !type || !content) {\n continue;\n }\n\n type = type.toUpperCase();\n content = (content || \"\").trim();\n if (dots && Object.keys(nameLike).includes(type)) {\n content = addDots(content, nameLike[type as keyof typeof nameLike]);\n }\n\n data.records.push({\n name: normalize(([\"\", \"@\"].includes(name) && data.origin) ? data.origin : name),\n ttl: parseTTL(ttl, data.ttl !== undefined ? data.ttl : defaultTTL),\n class: cls.toUpperCase(),\n type,\n content,\n comment: (comment || \"\").trim() || null,\n });\n }\n\n if (replaceOrigin) {\n data.origin = replaceOrigin;\n }\n\n return data as DnszDnsData;\n}\n\n/** Parse a `data` object and return a string with the zone file contents. */\nexport function stringifyZone(data: DnszDnsData, {crlf = false, sections = true, dots = false}: DnszStringifyOptions = {}): string {\n const recordsByType: Record<string, Array<DnszDnsRecord>> = {};\n const newline = crlf ? \"\\r\\n\" : \"\\n\";\n\n if (sections) {\n for (const record of data.records) {\n if (!recordsByType[record.type]) recordsByType[record.type] = [];\n recordsByType[record.type].push(record);\n }\n }\n\n let output = \"\";\n if (data.header) {\n output += `${data.header\n .split(/\\r?\\n/)\n .map(l => l.trim())\n .map(l => l ? `;; ${l}` : \";;\")\n .join(newline)\n .trim()}${newline}${newline}`;\n }\n\n const vars: Array<string> = [];\n if (data.origin) vars.push(`$ORIGIN ${denormalize(data.origin)}`);\n if (data.ttl) vars.push(`$TTL ${data.ttl}`);\n if (vars.length) output += `${vars.join(newline)}${newline}${newline}`;\n\n const origin = normalize(data.origin || \"\");\n if (sections) {\n if (recordsByType.SOA) {\n output += format(recordsByType.SOA, \"SOA\", {origin, newline, sections, dots});\n delete recordsByType.SOA;\n }\n\n for (const type of Object.keys(recordsByType).sort()) {\n output += format(recordsByType[type], type, {origin, newline, sections, dots});\n }\n } else {\n const recordsSOA = data.records.filter(r => r.type === \"SOA\");\n const recordsMinusSOA = data.records.filter(r => r.type !== \"SOA\");\n\n output += format(recordsSOA, null, {origin, newline, sections, dots});\n output += format(recordsMinusSOA, null, {origin, newline, sections, dots});\n }\n\n return `${output.trim()}${newline}`;\n}\n"],"mappings":"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"} |
+12
-11
| { | ||
| "name": "dnsz", | ||
| "version": "4.3.4", | ||
| "version": "4.4.0", | ||
| "description": "Generic DNS zone file parser and stringifier", | ||
@@ -17,14 +17,15 @@ "author": "silverwind <me@silverwind.io>", | ||
| "devDependencies": { | ||
| "@types/node": "24.10.1", | ||
| "eslint": "9.39.1", | ||
| "eslint-config-silverwind": "112.0.1", | ||
| "tsdown": "0.16.7", | ||
| "tsdown-config-silverwind": "1.5.3", | ||
| "@types/node": "25.1.0", | ||
| "dedent": "1.7.1", | ||
| "eslint": "9.39.2", | ||
| "eslint-config-silverwind": "118.0.1", | ||
| "tsdown": "0.20.1", | ||
| "tsdown-config-silverwind": "1.7.3", | ||
| "typescript-config-silverwind": "14.0.0", | ||
| "updates": "16.9.1", | ||
| "versions": "14.0.3", | ||
| "vite-config-silverwind": "6.0.5", | ||
| "vitest": "4.0.14", | ||
| "vitest-config-silverwind": "10.4.2" | ||
| "updates": "17.0.9", | ||
| "versions": "14.0.4", | ||
| "vite-config-silverwind": "6.0.9", | ||
| "vitest": "4.0.18", | ||
| "vitest-config-silverwind": "10.6.1" | ||
| } | ||
| } |
+1
-1
| # dnsz | ||
| [](https://www.npmjs.org/package/dnsz) [](https://www.npmjs.org/package/dnsz) [](https://bundlephobia.com/package/dnsz) [](https://packagephobia.com/result?p=dnsz) | ||
| [](https://www.npmjs.org/package/dnsz) [](https://www.npmjs.org/package/dnsz) [](https://bundlephobia.com/package/dnsz) [](https://packagephobia.com/result?p=dnsz) [](https://depx.co/pkg/dnsz) | ||
@@ -4,0 +4,0 @@ > Generic DNS zone file parser and stringifier |
37689
5.67%336
2.75%12
9.09%