96 lines
3.5 KiB
TypeScript
96 lines
3.5 KiB
TypeScript
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<Buffer> {
|
|
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<string, string>()
|
|
const bicMap = new Map<string, string>()
|
|
|
|
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<string, string> = {",
|
|
...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<string, string> = {",
|
|
...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)
|
|
})
|