import XLSX from "xlsx"; import { mkdir, readdir, writeFile } from "node:fs/promises"; import path from "node:path"; const INPUT_DIR = process.env.BIZMAX_OUTPUT_DIR ?? path.resolve(process.cwd(), "output"); const CSV_DIR = process.env.BIZMAX_CSV_DIR ?? path.join(INPUT_DIR, "csv"); const CSV_NAME = process.env.BIZMAX_CSV_NAME ?? "bizmax-all.csv"; function toText(value: unknown): string { if (value == null) { return ""; } return String(value); } function escapeCsv(value: string): string { if (/[",\n\r]/.test(value)) { return `"${value.replace(/"/g, "\"\"")}"`; } return value; } function rowToCsv(row: string[]): string { return row.map(escapeCsv).join(","); } async function main(): Promise { const entries = await readdir(INPUT_DIR, { withFileTypes: true }); const xlsxFiles = entries .filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".xlsx")) .map((entry) => path.join(INPUT_DIR, entry.name)) .sort(); if (xlsxFiles.length === 0) { throw new Error(`No .xlsx files found in ${INPUT_DIR}`); } const outputRows: string[] = []; let wroteHeader = false; for (const xlsxFile of xlsxFiles) { const workbook = XLSX.readFile(xlsxFile, { cellDates: false }); for (const sheetName of workbook.SheetNames) { const worksheet = workbook.Sheets[sheetName]; const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, raw: false, defval: "", }); if (rows.length === 0) { continue; } const headerRow = (rows[0] ?? []).map(toText); if (!wroteHeader) { outputRows.push( rowToCsv(["source_file", "source_sheet", ...headerRow]), ); wroteHeader = true; } for (const row of rows.slice(1)) { const values = (row as unknown[]).map(toText); outputRows.push( rowToCsv([ path.basename(xlsxFile), sheetName, ...values, ]), ); } } } if (!wroteHeader) { throw new Error(`No worksheet rows found in ${INPUT_DIR}`); } await mkdir(CSV_DIR, { recursive: true }); const outputPath = path.join(CSV_DIR, CSV_NAME); await writeFile(outputPath, `${outputRows.join("\n")}\n`, "utf8"); process.stdout.write(`${outputPath}\n`); } main().catch((error: unknown) => { const message = error instanceof Error ? error.message : String(error); process.stderr.write(`${message}\n`); process.exitCode = 1; });