echos-ocr/src/lib/integrations/providers/csv-export.ts

124 lines
2.7 KiB
TypeScript
Raw Normal View History

import type {
IntegrationProvider,
CardData,
TestResult,
PushResult,
JsonValue,
} from "../types";
const DEFAULT_COLUMNS = [
"name",
"email",
"cellPhone",
"homePhone",
"address",
"city",
"state",
"zip",
"gender",
"dateOfBirth",
"maritalStatus",
"visitType",
"prayerRequests",
"followUp",
"notes",
"serviceAttended",
"firstTimeGuestDate",
"salvationDate",
];
interface CsvConfig {
format: "csv" | "tsv";
columns: string[];
includeHeaders: boolean;
}
function parseConfig(config: JsonValue): CsvConfig {
const c = config as Record<string, unknown>;
return {
format: (c.format as "csv" | "tsv") || "csv",
columns: (c.columns as string[]) || DEFAULT_COLUMNS,
includeHeaders: c.includeHeaders !== false,
};
}
function escapeCell(val: string, delimiter: string): string {
if (
val.includes(delimiter) ||
val.includes('"') ||
val.includes("\n")
) {
return `"${val.replace(/"/g, '""')}"`;
}
return val;
}
export function cardToCsvRow(
card: CardData,
columns: string[],
delimiter: string
): string {
return columns
.map((col) => {
const val = card[col];
if (val === null || val === undefined) return "";
if (val instanceof Date) return val.toISOString().split("T")[0];
if (typeof val === "object") return escapeCell(JSON.stringify(val), delimiter);
return escapeCell(String(val), delimiter);
})
.join(delimiter);
}
export const csvExportProvider: IntegrationProvider = {
id: "csv_export",
name: "CSV / Excel Export",
description: "Generate CSV or TSV files from processed cards",
icon: "csv_export",
category: "export",
supportsFieldMapping: false,
supportsOAuth: false,
configFields: [
{
key: "format",
label: "Format",
type: "select",
options: [
{ value: "csv", label: "CSV (comma-separated)" },
{ value: "tsv", label: "TSV (tab-separated, Excel-friendly)" },
],
},
{
key: "includeHeaders",
label: "Include column headers",
type: "boolean",
},
],
async testConnection(): Promise<TestResult> {
return {
success: true,
message: "CSV export is always available — no external connection needed",
};
},
async pushCard(
card: CardData,
config: JsonValue,
): Promise<PushResult> {
try {
const { format, columns } = parseConfig(config);
const delimiter = format === "tsv" ? "\t" : ",";
const row = cardToCsvRow(card, columns, delimiter);
return {
success: true,
message: `Generated ${format.toUpperCase()} row (${row.length} chars)`,
};
} catch (err) {
return {
success: false,
message: err instanceof Error ? err.message : "Export failed",
};
}
},
};