import { sendCommand } from "./client"; import { normalizeFragment, type FragmentDto, type FragmentDtoRaw, } from "./fragments"; import { pickCase } from "./normalize"; export type ParsedSectionDto = { title: string; content: string[]; checkboxes: Record; }; export type JournalEntryDto = { date: string; fragments: FragmentDto[]; rawContent: string; sections: Record; }; export type EntryListItemDto = { fileName: string; filePath: string; }; export type EntryLoadResultDto = { fileName: string; filePath: string; entry: JournalEntryDto; }; export type EntrySaveResultDto = { filePath: string; }; export type EntrySearchRequestDto = { dataDirectory: string; query?: string; section?: string; startDate?: string; endDate?: string; tags?: string[]; types?: string[]; checked?: string[]; unchecked?: string[]; }; export type EntrySearchResultDto = { fileName: string; entry: JournalEntryDto; }; type ParsedSectionDtoRaw = { title?: string; content?: string[]; checkboxes?: Record; Title?: string; Content?: string[]; Checkboxes?: Record; }; type JournalEntryDtoRaw = { date?: string; fragments?: FragmentDtoRaw[]; rawContent?: string; sections?: Record; Date?: string; Fragments?: FragmentDtoRaw[]; RawContent?: string; Sections?: Record; }; type EntryListItemDtoRaw = { fileName?: string; filePath?: string; FileName?: string; FilePath?: string; }; type EntryLoadResultDtoRaw = { fileName?: string; filePath?: string; entry?: JournalEntryDtoRaw; date?: string; rawContent?: string; FileName?: string; FilePath?: string; Entry?: JournalEntryDtoRaw; Date?: string; RawContent?: string; }; type EntrySaveResultDtoRaw = { filePath?: string; FilePath?: string; }; type EntrySearchResultDtoRaw = { fileName?: string; entry?: JournalEntryDtoRaw; date?: string; rawContent?: string; FileName?: string; Entry?: JournalEntryDtoRaw; Date?: string; RawContent?: string; }; function normalizeSection(raw: ParsedSectionDtoRaw): ParsedSectionDto { return { title: pickCase(raw, "title", "Title", ""), content: pickCase(raw, "content", "Content", [] as string[]), checkboxes: pickCase( raw, "checkboxes", "Checkboxes", {} as Record, ), }; } function normalizeJournalEntry( raw: JournalEntryDtoRaw | undefined, ): JournalEntryDto { const fragments = pickCase( raw, "fragments", "Fragments", [] as FragmentDtoRaw[], ); const sections = pickCase( raw, "sections", "Sections", {} as Record, ); return { date: pickCase(raw, "date", "Date", ""), fragments: fragments.map(normalizeFragment), rawContent: pickCase(raw, "rawContent", "RawContent", ""), sections: Object.fromEntries( Object.entries(sections).map(([key, value]) => [ key, normalizeSection(value), ]), ), }; } function normalizeEntryListItem(raw: EntryListItemDtoRaw): EntryListItemDto { return { fileName: pickCase(raw, "fileName", "FileName", ""), filePath: pickCase(raw, "filePath", "FilePath", ""), }; } function normalizeEntryLoadResult( raw: EntryLoadResultDtoRaw, ): EntryLoadResultDto { const nestedEntry = pickCase( raw, "entry", "Entry", undefined as JournalEntryDtoRaw | undefined, ); const entry = nestedEntry ? normalizeJournalEntry(nestedEntry) : normalizeJournalEntry({ date: pickCase(raw, "date", "Date", undefined as string | undefined), rawContent: pickCase( raw, "rawContent", "RawContent", undefined as string | undefined, ), fragments: [], sections: {}, }); return { fileName: pickCase(raw, "fileName", "FileName", ""), filePath: pickCase(raw, "filePath", "FilePath", ""), entry, }; } function normalizeEntrySearchResult( raw: EntrySearchResultDtoRaw, ): EntrySearchResultDto { const nestedEntry = pickCase( raw, "entry", "Entry", undefined as JournalEntryDtoRaw | undefined, ); const entry = nestedEntry ? normalizeJournalEntry(nestedEntry) : normalizeJournalEntry({ date: pickCase(raw, "date", "Date", undefined as string | undefined), rawContent: pickCase( raw, "rawContent", "RawContent", undefined as string | undefined, ), fragments: [], sections: {}, }); return { fileName: pickCase(raw, "fileName", "FileName", ""), entry, }; } export async function listEntries( dataDirectory?: string, ): Promise { const data = await sendCommand({ action: "entries.list", payload: { dataDirectory }, }); return data .map(normalizeEntryListItem) .filter((item) => Boolean(item.filePath)); } export async function loadEntry(filePath: string): Promise { const data = await sendCommand({ action: "entries.load", payload: { filePath }, }); return normalizeEntryLoadResult(data); } export async function saveEntry(payload: { content: string; filePath?: string; mode?: string; fileName?: string; }): Promise { const data = await sendCommand({ action: "entries.save", payload, }); return { filePath: pickCase(data, "filePath", "FilePath", ""), }; } export async function deleteEntry(filePath: string): Promise { return sendCommand({ action: "entries.delete", payload: { filePath }, }); } export async function searchEntries( payload: EntrySearchRequestDto, ): Promise { const data = await sendCommand({ action: "search.entries", payload, }); return data .map(normalizeEntrySearchResult) .filter((item) => Boolean(item.fileName)); }