feat(import): restore MindSift data and import Obsidian vaults
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m28s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m28s
- Two separate paths: POST /import/mindsift (JSON backup or the Markdown archive) and POST /import/obsidian (vault ZIP into a folder named after it) - Everything is planned and validated first; ?preview=1 returns what would be created and what is skipped (with reason), nothing is written - MindSift data round-trips: folders, note structure, task lists with subtasks/due dates/priorities/notes, lists with quantity/category/done, triage thoughts from the JSON backup - Markdown to outliner: nested lists, heading sections, callouts, code, paragraphs; front matter tags become hashtags; .obsidian/attachments skipped - Limits against zip bombs and path tricks (100 MB upload, 10 MB per note, 500 MB unpacked, 20k files, no .. escapes) - Settings: two import cards with drag & drop, preview, confirm, result; touch-sized buttons; mobile download/upload verified Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d8a16c6775
commit
1601a6a2d5
9 files changed
+1314
-1
No files matched your search
@@ -19,6 +19,7 @@ import {
|
||||
SystemSettings,
|
||||
SharingMode,
|
||||
UserTheme,
|
||||
ImportSummary,
|
||||
Team,
|
||||
TaskList,
|
||||
TaskListShare,
|
||||
@@ -1076,6 +1077,22 @@ export const api = {
|
||||
return request<any>('/api/v1/export');
|
||||
},
|
||||
|
||||
// Import of MindSift data (JSON backup or Markdown archive) or an Obsidian vault (ZIP).
|
||||
// preview = true only reports what would be created.
|
||||
async importData(source: 'mindsift' | 'obsidian', file: File, preview: boolean): Promise<ImportSummary> {
|
||||
const token = getToken();
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const res = await fetch(`/api/v1/import/${source}${preview ? '?preview=1' : ''}`, {
|
||||
method: 'POST',
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
body: form,
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(data.error || `Import fehlgeschlagen (HTTP ${res.status})`);
|
||||
return data as ImportSummary;
|
||||
},
|
||||
|
||||
// Obsidian-compatible ZIP of the workspace; binary and possibly large, so no JSON helper and no timeout
|
||||
async exportMarkdownVault(): Promise<Blob> {
|
||||
const token = getToken();
|
||||
|
||||
Reference in new issue
Block a user