Repository: Mintplex-Labs/anything-llm
File: server/utils/helpers/chat/convertTo.js (JavaScript)

Code before:
// Helpers that convert workspace chats to some supported format
// for external use by the user.

const { Workspace } = require("../../../models/workspace");
const { WorkspaceChats } = require("../../../models/workspaceChats");

// Todo: make this more useful for export by adding other columns about workspace, user, time, etc for post-filtering.
async function convertToCSV(preparedData) {
  const rows = ["id,username,workspace,prompt,response,sent_at"];
  for (const item of preparedData) {
    // Escape double quotes and wrap content in double quotes
    const escapedPrompt = `"${item.prompt
      .replace(/"/g, '""')
      .replace(/\n/g, " ")}"`;
    const escapedResponse = `"${item.response
      .replace(/"/g, '""')
      .replace(/\n/g, " ")}"`;
    const row = `"${item.id}","${item.username}","${item.workspace}",${escapedPrompt},${escapedResponse},"${item.sent_at}"`;
    rows.push(row);
  }
  return rows.join("\n");
}

async function convertToJSON(workspaceChatsMap) {
  const allMessages = [].concat.apply(
    [],
    Object.values(workspaceChatsMap).map((workspace) => workspace.messages)
  );
  return JSON.stringify(allMessages);
}

async function convertToJSONL(workspaceChatsMap) {
  return Object.values(workspaceChatsMap)
    .map((workspaceChats) => JSON.stringify(workspaceChats))
    .join("\n");
}

async function prepareWorkspaceChatsForExport(type = "jsonl") {
  const chats = await WorkspaceChats.whereWithData({}, null, null, {
    id: "asc",
  });

  if (type === "csv") {
    const preparedData = chats.map((chat) => {

Review comment (security):
It would probably be more readable to define a data array that then makes the string
```javascript
const record = [
item.id,
escape(item.username), // we dont validate this to not contain quotes and better safe??
escape(item.workspace), // this needs to be escape because we dont validate this on backend.
escape(item.prompt)
escape(item.response)
item.sent_at
].join(',')

row.push(record)
```

Code after:
// Helpers that convert workspace chats to some supported format
// for external use by the user.

const { Workspace } = require("../../../models/workspace");
const { WorkspaceChats } = require("../../../models/workspaceChats");

// Todo: add RLHF feedbackScore field support
async function convertToCSV(preparedData) {
  const rows = ["id,username,workspace,prompt,response,sent_at"];
  for (const item of preparedData) {
    const record = [
      item.id,
      escapeCsv(item.username),
      escapeCsv(item.workspace),
      escapeCsv(item.prompt),
      escapeCsv(item.response),
      item.sent_at,
    ].join(",");
    rows.push(record);
  }
  return rows.join("\n");
}

async function convertToJSON(workspaceChatsMap) {
  const allMessages = [].concat.apply(
    [],
    Object.values(workspaceChatsMap).map((workspace) => workspace.messages)
  );
  return JSON.stringify(allMessages);
}

async function convertToJSONL(workspaceChatsMap) {
  return Object.values(workspaceChatsMap)
    .map((workspaceChats) => JSON.stringify(workspaceChats))
    .join("\n");
}

async function prepareWorkspaceChatsForExport(format = "jsonl") {
  if (!exportMap.hasOwnProperty(format))
    throw new Error("Invalid export type.");

  const chats = await WorkspaceChats.whereWithData({}, null, null, {
    id: "asc",
  });