80 lines
2.1 KiB
JavaScript
80 lines
2.1 KiB
JavaScript
// @flow
|
|
import fs from "fs";
|
|
import JSZip from "jszip";
|
|
import tmp from "tmp";
|
|
import * as Sentry from "@sentry/node";
|
|
import { Attachment, Collection, Document } from "../models";
|
|
import { getImageByKey } from "./s3";
|
|
|
|
async function addToArchive(zip, documents) {
|
|
for (const doc of documents) {
|
|
const document = await Document.findByPk(doc.id);
|
|
let text = document.toMarkdown();
|
|
|
|
const attachments = await Attachment.findAll({
|
|
where: { documentId: document.id },
|
|
});
|
|
|
|
for (const attachment of attachments) {
|
|
await addImageToArchive(zip, attachment.key);
|
|
text = text.replace(attachment.redirectUrl, encodeURI(attachment.key));
|
|
}
|
|
|
|
zip.file(`${document.title || "Untitled"}.md`, text);
|
|
|
|
if (doc.children && doc.children.length) {
|
|
const folder = zip.folder(document.title);
|
|
await addToArchive(folder, doc.children);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function addImageToArchive(zip, key) {
|
|
try {
|
|
const img = await getImageByKey(key);
|
|
zip.file(key, img, { createFolders: true });
|
|
} catch (err) {
|
|
if (process.env.SENTRY_DSN) {
|
|
Sentry.captureException(err);
|
|
}
|
|
// error during file retrieval
|
|
console.error(err);
|
|
}
|
|
}
|
|
|
|
async function archiveToPath(zip) {
|
|
return new Promise((resolve, reject) => {
|
|
tmp.file({ prefix: "export-", postfix: ".zip" }, (err, path) => {
|
|
if (err) return reject(err);
|
|
|
|
zip
|
|
.generateNodeStream({ type: "nodebuffer", streamFiles: true })
|
|
.pipe(fs.createWriteStream(path))
|
|
.on("finish", () => resolve(path))
|
|
.on("error", reject);
|
|
});
|
|
});
|
|
}
|
|
|
|
export async function archiveCollection(collection: Collection) {
|
|
const zip = new JSZip();
|
|
|
|
if (collection.documentStructure) {
|
|
await addToArchive(zip, collection.documentStructure);
|
|
}
|
|
|
|
return archiveToPath(zip);
|
|
}
|
|
|
|
export async function archiveCollections(collections: Collection[]) {
|
|
const zip = new JSZip();
|
|
|
|
for (const collection of collections) {
|
|
if (collection.documentStructure) {
|
|
const folder = zip.folder(collection.name);
|
|
await addToArchive(folder, collection.documentStructure);
|
|
}
|
|
}
|
|
return archiveToPath(zip);
|
|
}
|