SPB Git
3.9 KB · 46 lines typescript
1/** Import dispatcher: kind detection + `runImport` (used inline by /api/import for small files and by the worker for big ones). */2import { importMarkdown } from "./markdown";3import { importZip } from "./zip";4import { importDocx } from "./docx";5import { importPdf } from "./pdf";6import { importCsv } from "./csv";7import { importBibtexRefs } from "./bibtex";8import { restoreJson } from "./restore";9import { newCtx, ImportError, type ImportCtx } from "./pages";1011export type ImportKind = "markdown" | "zip" | "docx" | "pdf" | "csv" | "bibtex" | "json";12export const KINDS: ImportKind[] = ["markdown", "zip", "docx", "pdf", "csv", "bibtex", "json"];13export const ACCEPT = ".md,.markdown,.txt,.zip,.docx,.pdf,.csv,.bib,.json";14/** Files up to this size are imported synchronously in the request; larger ones go to the worker. */15export const INLINE_MAX = 2 * 1024 * 1024;1617export function detectKind(filename: string, mime = ""): ImportKind {18  const ext = filename.toLowerCase().match(/\.([a-z0-9]+)$/)?.[1] ?? "";19  if (ext === "md" || ext === "markdown" || ext === "txt" || mime === "text/markdown") return "markdown";20  if (ext === "zip" || mime === "application/zip" || mime === "application/x-zip-compressed") return "zip";21  if (ext === "docx" || mime.includes("wordprocessingml")) return "docx";22  if (ext === "pdf" || mime === "application/pdf") return "pdf";23  if (ext === "csv" || mime === "text/csv") return "csv";24  if (ext === "bib" || ext === "bibtex" || mime === "application/x-bibtex") return "bibtex";25  if (ext === "json" || mime === "application/json") return "json";26  throw new ImportError(`Unsupported file type: .${ext || "?"} (${ACCEPT})`, 415);27}2829export interface ImportResult { kind: ImportKind; pageId: string | null; title?: string; stats: ImportCtx["stats"]; detail?: Record<string, unknown> }30export async function runImport(input: { workspaceId: string; kind: ImportKind; buffer: Buffer; filename: string; parentId?: string | null; progress?: ImportCtx["progress"] }): Promise<ImportResult> {31  const ctx = await newCtx(input.workspaceId, input.progress);32  const name = input.filename.replace(/^.*[\\/]/, "");33  const base = name.replace(/\.[^.]+$/, "");34  const text = () => input.buffer.toString("utf8");35  switch (input.kind) {36    case "markdown": { const p = await importMarkdown(ctx, text(), { filename: name, parentId: input.parentId }); return { kind: "markdown", pageId: p.id, title: p.title, stats: ctx.stats }; }37    case "zip": { const r = await importZip(ctx, input.buffer, { parentId: input.parentId, filename: name }); return { kind: "zip", pageId: r.pageId, stats: ctx.stats, detail: { notion: r.notion, pages: r.pages, databases: r.databases } }; }38    case "docx": { const r = await importDocx(ctx, input.buffer, { filename: name, parentId: input.parentId }); return { kind: "docx", pageId: r.page.id, title: r.page.title, stats: ctx.stats, detail: { images: r.images } }; }39    case "pdf": { const r = await importPdf(ctx, input.buffer, { filename: name, parentId: input.parentId }); return { kind: "pdf", pageId: r.page.id, title: r.page.title, stats: ctx.stats, detail: { pages: r.pages } }; }40    case "csv": { const r = await importCsv(ctx, text(), { name: base, parentId: input.parentId }); return { kind: "csv", pageId: r.page.id, title: r.page.title, stats: ctx.stats, detail: { rows: r.rows, properties: r.properties.map((p) => ({ name: p.name, type: p.type })) } }; }41    case "bibtex": { const r = await importBibtexRefs(ctx, text(), input.parentId ?? null); return { kind: "bibtex", pageId: input.parentId ?? null, stats: ctx.stats, detail: r }; }42    case "json": { let data: unknown; try { data = JSON.parse(text()); } catch { throw new ImportError("Invalid JSON"); } const r = await restoreJson(ctx, data); return { kind: "json", pageId: null, stats: ctx.stats, detail: r }; }43  }44}45export { ImportError, newCtx, setImportProgress, getImportProgress, type ImportProgress } from "./pages";46
Files · main
Menu

Theme