rspace-online/modules/rnotes/converters/index.ts

99 lines
2.7 KiB
TypeScript

/**
* Converter registry and shared types for rNotes import/export.
*
* All source-specific converters implement NoteConverter.
* ConvertedNote is the intermediate format between external sources and NoteItem.
*/
import type { NoteItem, SourceRef } from '../schemas';
// ── Shared types ──
export interface ConvertedNote {
title: string;
content: string; // TipTap JSON string
contentPlain: string; // Plain text for search
markdown: string; // Original/generated markdown (for canvas shapes)
tags: string[];
sourceRef: SourceRef;
/** Optional note type override */
type?: NoteItem['type'];
}
export interface ImportResult {
notes: ConvertedNote[];
notebookTitle: string;
warnings: string[];
}
export interface ExportResult {
data: Uint8Array;
filename: string;
mimeType: string;
}
export interface NoteConverter {
id: string;
name: string;
requiresAuth: boolean;
/** Import from external source into ConvertedNote[] */
import(input: ImportInput): Promise<ImportResult>;
/** Export NoteItems to external format */
export(notes: NoteItem[], opts: ExportOptions): Promise<ExportResult>;
}
export interface ImportInput {
/** ZIP file data for file-based sources (Logseq, Obsidian) */
fileData?: Uint8Array;
/** Page/doc IDs for API-based sources (Notion, Google Docs) */
pageIds?: string[];
/** Whether to import recursively (sub-pages) */
recursive?: boolean;
/** Access token for authenticated sources */
accessToken?: string;
}
export interface ExportOptions {
/** Notebook title for the export */
notebookTitle?: string;
/** Access token for authenticated sources */
accessToken?: string;
/** Target parent page/folder ID for API-based exports */
parentId?: string;
}
// ── Converter registry ──
const converters = new Map<string, NoteConverter>();
export function registerConverter(converter: NoteConverter): void {
converters.set(converter.id, converter);
}
export function getConverter(id: string): NoteConverter | undefined {
ensureConvertersLoaded();
return converters.get(id);
}
export function getAllConverters(): NoteConverter[] {
ensureConvertersLoaded();
return Array.from(converters.values());
}
// ── Lazy-load converters to avoid circular init ──
// Each converter imports registerConverter from this file; importing them
// synchronously at the module level causes a "Cannot access before
// initialization" error in Bun because the converters Map hasn't been
// assigned yet when the circular import triggers registerConverter().
let _loaded = false;
export function ensureConvertersLoaded(): void {
if (_loaded) return;
_loaded = true;
require('./obsidian');
require('./logseq');
require('./notion');
require('./google-docs');
}