import fs from "node:fs/promises" import path from "node:path" import https from "node:https" const DEFAULT_SOURCE_URL = "https://www.bundesbank.de/resource/blob/602632/bec25ca5df1eb62fefadd8325dafe67c/472B63F073F071307366337C94F8C870/blz-aktuell-txt-data.txt" const OUTPUT_NAME_FILE = path.resolve("src/utils/deBankCodes.ts") const OUTPUT_BIC_FILE = path.resolve("src/utils/deBankBics.ts") function fetchBuffer(url: string): Promise { return new Promise((resolve, reject) => { https .get(url, (res) => { if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { return resolve(fetchBuffer(res.headers.location)) } if (res.statusCode !== 200) { return reject(new Error(`Download failed with status ${res.statusCode}`)) } const chunks: Buffer[] = [] res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))) res.on("end", () => resolve(Buffer.concat(chunks))) res.on("error", reject) }) .on("error", reject) }) } function escapeTsString(value: string) { return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') } async function main() { const source = process.env.BLZ_SOURCE_URL || DEFAULT_SOURCE_URL const sourceFile = process.env.BLZ_SOURCE_FILE let raw: Buffer if (sourceFile) { console.log(`Reading BLZ source file: ${sourceFile}`) raw = await fs.readFile(sourceFile) } else { console.log(`Downloading BLZ source: ${source}`) raw = await fetchBuffer(source) } const content = raw.toString("latin1") const lines = content.split(/\r?\n/) const nameMap = new Map() const bicMap = new Map() for (const line of lines) { if (!line || line.length < 150) continue const blz = line.slice(0, 8).trim() const name = line.slice(9, 67).trim() const bic = line.slice(139, 150).trim() if (!/^\d{8}$/.test(blz) || !name) continue if (!nameMap.has(blz)) nameMap.set(blz, name) if (bic && !bicMap.has(blz)) bicMap.set(blz, bic) } const sortedNames = [...nameMap.entries()].sort(([a], [b]) => a.localeCompare(b)) const sortedBics = [...bicMap.entries()].sort(([a], [b]) => a.localeCompare(b)) const nameOutputLines = [ "// Lokale Bankleitzahl-zu-Institut Zuordnung (DE).", "// Quelle: Deutsche Bundesbank, BLZ-Datei (vollstaendig).", "export const DE_BANK_CODE_TO_NAME: Record = {", ...sortedNames.map(([blz, name]) => ` "${blz}": "${escapeTsString(name)}",`), "}", "", ] const bicOutputLines = [ "// Lokale Bankleitzahl-zu-BIC Zuordnung (DE).", "// Quelle: Deutsche Bundesbank, BLZ-Datei (vollstaendig).", "export const DE_BANK_CODE_TO_BIC: Record = {", ...sortedBics.map(([blz, bic]) => ` "${blz}": "${escapeTsString(bic)}",`), "}", "", ] await fs.writeFile(OUTPUT_NAME_FILE, nameOutputLines.join("\n"), "utf8") await fs.writeFile(OUTPUT_BIC_FILE, bicOutputLines.join("\n"), "utf8") console.log(`Wrote ${sortedNames.length} bank names to ${OUTPUT_NAME_FILE}`) console.log(`Wrote ${sortedBics.length} bank BICs to ${OUTPUT_BIC_FILE}`) } main().catch((err) => { console.error(err) process.exit(1) })