• Internal

    Exports data as JSON file with automatic timestamp and sanitized filename; triggers browser download.

    Parameters

    • data: Record<string, unknown> | unknown[]

      The data to export (object or array for JSON stringification).

    • baseFilename: string

      Base filename (without extension); will be sanitized for filesystem safety.

    Returns Promise<string>

    Promise resolving to full filename used for download (including timestamp and extension).

    If JSON stringification fails or document.body unavailable.

    export async function exportToJson(
    data: Record<string, unknown> | unknown[],
    baseFilename: string,
    ): Promise<string> {
    // Serialize using worker pool for performance
    const pool = getJSONSerializationWorkerPool();
    const { json, sizeBytes } = await pool.serialize(data, { space: 2 });

    console.info(
    `[Export] 📦 Serialized JSON: ${sizeBytes} bytes using worker pool`,
    );

    // Create blob and download link
    const blob = new Blob([json], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    let appended = false;

    try {
    // Sanitize and generate timestamped filename
    const sanitized = sanitizeFilename(baseFilename);
    const timestamp = generateExportTimestamp();
    const filename = `${sanitized}-${timestamp}.json`;

    // Trigger download
    link.href = url;
    link.download = filename;

    // Guard against non-DOM contexts where document.body is unavailable
    if (!document.body) {
    throw new Error(
    "Cannot export: document.body is unavailable. " +
    "This export utility requires the Electron renderer process with access to DOM APIs. " +
    "Ensure this function is called from a React component in the renderer process.",
    );
    }

    document.body.appendChild(link);
    appended = true;
    link.click();

    return filename;
    } finally {
    // Ensure cleanup always runs
    if (appended) {
    link.remove();
    }
    URL.revokeObjectURL(url);
    }
    }