274 lines
6.0 KiB
TypeScript
274 lines
6.0 KiB
TypeScript
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<string, boolean>;
|
|
};
|
|
|
|
export type JournalEntryDto = {
|
|
date: string;
|
|
fragments: FragmentDto[];
|
|
rawContent: string;
|
|
sections: Record<string, ParsedSectionDto>;
|
|
};
|
|
|
|
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<string, boolean>;
|
|
Title?: string;
|
|
Content?: string[];
|
|
Checkboxes?: Record<string, boolean>;
|
|
};
|
|
|
|
type JournalEntryDtoRaw = {
|
|
date?: string;
|
|
fragments?: FragmentDtoRaw[];
|
|
rawContent?: string;
|
|
sections?: Record<string, ParsedSectionDtoRaw>;
|
|
Date?: string;
|
|
Fragments?: FragmentDtoRaw[];
|
|
RawContent?: string;
|
|
Sections?: Record<string, ParsedSectionDtoRaw>;
|
|
};
|
|
|
|
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<string, boolean>,
|
|
),
|
|
};
|
|
}
|
|
|
|
function normalizeJournalEntry(
|
|
raw: JournalEntryDtoRaw | undefined,
|
|
): JournalEntryDto {
|
|
const fragments = pickCase(
|
|
raw,
|
|
"fragments",
|
|
"Fragments",
|
|
[] as FragmentDtoRaw[],
|
|
);
|
|
const sections = pickCase(
|
|
raw,
|
|
"sections",
|
|
"Sections",
|
|
{} as Record<string, ParsedSectionDtoRaw>,
|
|
);
|
|
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<EntryListItemDto[]> {
|
|
const data = await sendCommand<EntryListItemDtoRaw[]>({
|
|
action: "entries.list",
|
|
payload: { dataDirectory },
|
|
});
|
|
|
|
return data
|
|
.map(normalizeEntryListItem)
|
|
.filter((item) => Boolean(item.filePath));
|
|
}
|
|
|
|
export async function loadEntry(filePath: string): Promise<EntryLoadResultDto> {
|
|
const data = await sendCommand<EntryLoadResultDtoRaw>({
|
|
action: "entries.load",
|
|
payload: { filePath },
|
|
});
|
|
|
|
return normalizeEntryLoadResult(data);
|
|
}
|
|
|
|
export async function saveEntry(payload: {
|
|
content: string;
|
|
filePath?: string;
|
|
mode?: string;
|
|
fileName?: string;
|
|
}): Promise<EntrySaveResultDto> {
|
|
const data = await sendCommand<EntrySaveResultDtoRaw>({
|
|
action: "entries.save",
|
|
payload,
|
|
});
|
|
|
|
return {
|
|
filePath: pickCase(data, "filePath", "FilePath", ""),
|
|
};
|
|
}
|
|
|
|
export async function deleteEntry(filePath: string): Promise<boolean> {
|
|
return sendCommand<boolean>({
|
|
action: "entries.delete",
|
|
payload: { filePath },
|
|
});
|
|
}
|
|
|
|
export async function searchEntries(
|
|
payload: EntrySearchRequestDto,
|
|
): Promise<EntrySearchResultDto[]> {
|
|
const data = await sendCommand<EntrySearchResultDtoRaw[]>({
|
|
action: "search.entries",
|
|
payload,
|
|
});
|
|
|
|
return data
|
|
.map(normalizeEntrySearchResult)
|
|
.filter((item) => Boolean(item.fileName));
|
|
}
|