Array of match results to export.
Export format (json, csv, markdown).
Optionalfilters: ExportFilterOptionsOptional filters to apply before export.
Promise resolving to filename of exported file.
export async function exportMatchResults(
matches: MangaMatchResult[],
format: ExportFormat,
filters?: ExportFilterOptions,
): Promise<string> {
console.info(
`[Export] 📤 Exporting ${matches.length} match results as ${format}`,
);
// Apply filters if provided
const filteredMatches = filters
? filterMatchResults(matches, filters)
: matches;
console.info(`[Export] 🔍 Filtered to ${filteredMatches.length} matches`);
const metadata = buildExportMetadata(format, filteredMatches.length, filters);
let filename: string;
switch (format) {
case "json": {
let payload: unknown;
// Apply field projection if fields are provided
if (filters?.fields && filters.fields.length > 0) {
const fields = filters.fields;
const projectedMatches = filteredMatches.map((match) => {
const flattened = flattenMatchResult(match);
const projected: Record<string, unknown> = {};
for (const fieldId of fields) {
projected[fieldId] = flattened[fieldId];
}
return projected;
});
payload = {
metadata,
matches: projectedMatches,
};
} else {
// Full payload
payload = {
metadata,
matches: filteredMatches,
};
}
filename = await exportToJson(
payload as Record<string, unknown>,
"match-results",
);
break;
}
case "csv": {
const flattened = filteredMatches.map(flattenMatchResult);
// Project to selected fields if provided
let projectedData: Record<string, unknown>[];
if (filters?.fields && filters.fields.length > 0) {
const fields = filters.fields;
projectedData = flattened.map((row) => {
const projected: Record<string, unknown> = {};
for (const fieldId of fields) {
projected[fieldId] = row[fieldId];
}
return projected;
});
} else {
projectedData = flattened as unknown as Record<string, unknown>[];
}
// Add metadata as comment rows at top of CSV
const withMetadata = [
{ comment: `Exported: ${metadata.exportedAt}` },
{ comment: `App Version: v${metadata.appVersion}` },
{ comment: `Total Entries: ${metadata.totalEntries}` },
{ comment: "" }, // Empty row separator
...projectedData,
];
filename = await exportToCSV(
withMetadata as unknown as Record<string, unknown>[],
"match-results",
);
break;
}
case "markdown": {
const flattened = filteredMatches.map(flattenMatchResult);
// Project to selected fields if provided
let projectedData: Record<string, unknown>[];
if (filters?.fields && filters.fields.length > 0) {
const fields = filters.fields;
projectedData = flattened.map((row) => {
const projected: Record<string, unknown> = {};
for (const fieldId of fields) {
projected[fieldId] = row[fieldId];
}
return projected;
});
} else {
projectedData = flattened as unknown as Record<string, unknown>[];
}
filename = exportToMarkdown(
projectedData as unknown as Record<string, unknown>[],
"match-results",
metadata,
);
break;
}
default:
throw new Error(`Unsupported export format: ${format}`);
}
console.info(`[Export] ✅ Successfully exported to ${filename}`);
return filename;
}
Exports match results in specified format with optional filtering; triggers browser download.