Core-API
API-Dokumentation für das Paket @mindwtr/core.
Installation
Das Core-Paket wird intern von den Desktop- und Mobilgeräte-Apps verwendet:
import {
useTaskStore,
setStorageAdapter,
parseQuickAdd,
mergeAppData
} from '@mindwtr/core';Typen
Die folgenden Ausschnitte zeigen häufig verwendete Felder und sind nicht vollständig. Importieren Sie die exportierten Typen aus @mindwtr/core oder verwenden Sie packages/core/src/types.ts als maßgebliche Definition.
Task
type RelativeStartOffsetUnit = 'minute' | 'hour' | 'day' | 'week';
interface RelativeStartOffset {
amount: number; // Offset <= 0, e.g. -3 days before due; 0 = on the due date
unit: RelativeStartOffsetUnit;
}
interface Task {
id: string; // UUID
title: string; // Task title
status: TaskStatus; // Current status
taskMode?: 'task' | 'list'; // 'list' = checklist-first task
priority?: TaskPriority; // 'low' | 'medium' | 'high' | 'urgent'
energyLevel?: TaskEnergyLevel; // 'low' | 'medium' | 'high'
assignedTo?: string; // Waiting-for person
startTime?: string; // ISO date string
relativeStartOffset?: RelativeStartOffset; // Recomputes startTime from dueDate
dueDate?: string; // ISO date string
recurrence?: Recurrence | RecurrenceRule;
showFutureRecurrence?: boolean; // Calendar-only preview of the next recurring occurrence
tags: string[]; // e.g., ['#focused']
contexts: string[]; // e.g., ['@home', '@work']
checklist?: ChecklistItem[]; // Sub-items
description?: string; // Notes
attachments?: Attachment[]; // Files/Links
location?: string; // Physical location
projectId?: string; // Parent project ID
sectionId?: string; // Parent section ID
areaId?: string; // Parent area ID (optional direct grouping)
isFocusedToday?: boolean; // Today's priority
pushCount?: number; // Number of times due date was pushed later
repeatReminderMinutes?: number; // Due-time repeat reminder preset: 5, 10, 15, 30, or 60
textDirection?: 'auto' | 'ltr' | 'rtl';
timeEstimate?: TimeEstimate; // Vorgaben bis '4hr+' oder `custom:${number}` Minuten
reviewAt?: string; // Tickler date
completedAt?: string; // When completed
rev?: number; // Monotonic revision counter for sync
revBy?: string; // Device ID that issued `rev`
createdAt: string; // Creation timestamp
updatedAt: string; // Last update timestamp
deletedAt?: string; // Soft-delete timestamp
purgedAt?: string; // Permanently deleted (tombstone only)
order?: number; // Manuelle Sortierung innerhalb eines Projekts
orderNum?: number; // Veralteter Alias für ältere Nutzdaten
}TaskStatus
type TaskStatus =
| 'inbox'
| 'next'
| 'waiting'
| 'someday'
| 'reference'
| 'done'
| 'archived';Recurrence
type RecurrenceRule = 'daily' | 'weekly' | 'monthly' | 'yearly';
type RecurrenceStrategy = 'strict' | 'fluid';
type RecurrenceWeekday = 'MO' | 'TU' | 'WE' | 'TH' | 'FR' | 'SA' | 'SU';
type RecurrenceByDay = RecurrenceWeekday | `${'1' | '2' | '3' | '4' | '-1'}${RecurrenceWeekday}`;
interface Recurrence {
rule: RecurrenceRule;
seriesId?: string; // Stabile Identität der Wiederholungsserie
strategy?: RecurrenceStrategy; // Defaults to 'strict'
byDay?: RecurrenceByDay[]; // Weekly/monthly weekday pattern
count?: number; // Total occurrences in the series, including the current task
until?: string; // ISO date/datetime when the series should stop
completedOccurrences?: number; // Internal counter used to preserve COUNT across generated tasks
rrule?: string; // Optional RFC 5545 fragment
}strategy: 'strict'hält den geplanten Rhythmus am Zeitplan verankert.strategy: 'fluid'bedeutet „nach Abschluss wiederholen“.countbeendet die Serie, nachdem die Gesamtzahl der Vorkommen erstellt wurde.untilbeendet die Serie, wenn die nächste erzeugte Aufgabe nach dem angegebenen Datum/der angegebenen Uhrzeit liegen würde.completedOccurrencessind interne, synchronisierungssichere Metadaten; Clients sollten sie beim Roundtrip von Wiederholungsobjekten beibehalten.- Clients müssen beim Roundtrip von Wiederholungsobjekten auch
seriesIdund sämtliche Ankermetadaten beibehalten. showFutureRecurrencegehört zur Aufgabe, nicht zum Wiederholungsobjekt. Das Feld weist den Kalender an, ein einzelnes, nur zur Planung dienendes nächstes Vorkommen anzuzeigen; Clients sollten den booleschen Wert beim Roundtrip von Aufgaben beibehalten.
Project
interface Project {
id: string;
title: string;
status: 'active' | 'someday' | 'waiting' | 'archived';
color: string; // Hex color code
areaId?: string; // Parent Area ID
tagIds: string[]; // Associated tags
order: number; // Sort order within area
isSequential?: boolean; // Show only first task in Next Actions
isFocused?: boolean; // Priority project (max 5)
supportNotes?: string; // Planning notes
attachments?: Attachment[]; // Files/Links
reviewAt?: string; // Tickler date
rev?: number; // Monotonic revision counter for sync
revBy?: string; // Device ID that issued `rev`
createdAt: string;
updatedAt: string;
deletedAt?: string;
}Section
interface Section {
id: string;
projectId: string;
title: string;
description?: string;
order: number; // Sort order within project
isCollapsed?: boolean; // UI collapsed state
rev?: number; // Monotonic revision counter for sync
revBy?: string; // Device ID that issued `rev`
createdAt: string;
updatedAt: string;
deletedAt?: string; // Soft-delete timestamp
}Area
interface Area {
id: string;
name: string;
color?: string;
icon?: string;
order: number;
rev?: number;
revBy?: string;
createdAt: string;
updatedAt: string;
deletedAt?: string; // Soft-delete tombstone for sync
}Person
interface Person {
id: string;
name: string;
note?: string;
referenceLink?: string;
rev?: number; // Monotonic revision counter for sync
revBy?: string; // Device ID that issued `rev`
createdAt: string;
updatedAt: string;
deletedAt?: string; // Soft-delete tombstone for sync
}Attachment
interface Attachment {
id: string;
kind: 'file' | 'link';
title: string;
uri: string;
mimeType?: string;
size?: number;
createdAt: string;
updatedAt: string;
deletedAt?: string;
}AppData
interface AppData {
tasks: Task[];
projects: Project[];
sections: Section[];
areas: Area[];
people?: Person[];
settings: {
theme?: 'light' | 'dark' | 'system';
language?: 'en' | 'vi' | 'zh' | 'zh-Hant' | 'es' | 'hi' | 'ar' | 'de' | 'ru' | 'ja' | 'fr' | 'pt' | 'pl' | 'ko' | 'cs' | 'it' | 'tr' | 'nl' | 'fa' | 'sv' | 'system';
weekStart?: 'system' | 'monday' | 'sunday' | 'saturday'; // absent or 'system' = follow the device locale
dateFormat?: string;
timeFormat?: string;
filters?: { areaId?: string };
syncPreferences?: SettingsSyncPreferences;
attachments?: {
lastCleanupAt?: string;
pendingRemoteDeletes?: PendingRemoteAttachmentDelete[];
};
externalCalendars?: ExternalCalendarSubscription[];
calendar?: { viewMode?: 'month' | 'day' | 'week' | 'schedule' };
gtd?: {
defaultScheduleTime?: string;
inboxProcessing?: InboxProcessingSettings;
weeklyReview?: { includeContextStep?: boolean };
dailyReview?: { includeFocusStep?: boolean };
pomodoro?: PomodoroSettings;
};
ai?: {
enabled?: boolean;
provider?: 'gemini' | 'openai' | 'anthropic';
model?: string;
reasoningEffort?: 'low' | 'medium' | 'high';
speechToText?: SpeechToTextSettings;
};
};
}Store
useTaskStore
Zustand-Store-Hook für den Zugriff auf Zustand und Aktionen.
import { useTaskStore } from '@mindwtr/core';
function MyComponent() {
const { tasks, projects, addTask, updateTask } = useTaskStore();
// ...
}Store-Zustand
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
tasks | Task[] | Alle sichtbaren (nicht gelöschten) Aufgaben |
projects | Project[] | Alle sichtbaren Projekte |
areas | Area[] | Alle Bereiche |
people | Person[] | Alle sichtbaren verwalteten Personen |
settings | AppData['settings'] | App-Einstellungen |
isLoading | boolean | Ladezustand |
error | string | null | Fehlermeldung |
Store-Aktionen
Die meisten verändernden Store-Aktionen geben bei gewöhnlichen Validierungsfehlern ein strukturiertes Ergebnis zurück, statt eine Ausnahme auszulösen:
type StoreActionResult = {
success: boolean;
error?: string;
id?: string;
};Aufgabenoperationen
// Create
addTask(title: string, initialProps?: Partial<Task>): Promise<StoreActionResult>;
// Update
updateTask(id: string, updates: Partial<Task>): Promise<StoreActionResult>;
// Move
moveTask(id: string, newStatus: TaskStatus): Promise<StoreActionResult>;
// Delete (Soft)
deleteTask(id: string): Promise<StoreActionResult>;
// Restore
restoreTask(id: string): Promise<StoreActionResult>;
// Duplicate
duplicateTask(id: string, asNextAction?: boolean): Promise<StoreActionResult>;
// Reset Checklist
resetTaskChecklist(id: string): Promise<StoreActionResult>;
// Batch Operations
batchUpdateTasks(updates: Array<{ id: string; updates: Partial<Task> }>): Promise<StoreActionResult>;
batchMoveTasks(ids: string[], newStatus: TaskStatus): Promise<StoreActionResult>;
batchDeleteTasks(ids: string[]): Promise<StoreActionResult>;Projektoperationen
// Create
addProject(title: string, color: string, initialProps?: Partial<Project>): Promise<Project | null>;
// Update
updateProject(id: string, updates: Partial<Project>): Promise<StoreActionResult>;
// Delete
deleteProject(id: string): Promise<StoreActionResult>;
// Restore
restoreProject(id: string): Promise<StoreActionResult>;
// Toggle Focus
toggleProjectFocus(id: string): Promise<void>;
// Reorder
reorderProjects(orderedIds: string[], areaId?: string): Promise<void>;
reorderProjectTasks(projectId: string, orderedIds: string[], sectionId?: string | null): Promise<void>;Bereichsoperationen
// Create
addArea(name: string, initialProps?: Partial<Area>): Promise<Area | null>;
// Update
updateArea(id: string, updates: Partial<Area>): Promise<StoreActionResult>;
// Delete (soft, detaches linked projects/tasks)
deleteArea(id: string): Promise<StoreActionResult>;
// Restore (restores the area tombstone only)
restoreArea(id: string): Promise<StoreActionResult>;
// Reorder
reorderAreas(orderedIds: string[]): Promise<void>;Beim Löschen/Wiederherstellen eines Bereichs werden absichtlich keine Tombstones kaskadiert. Das Löschen eines Bereichs entfernt areaId und areaTitle aus verknüpften Projekten sowie direkte areaId-Werte von Aufgaben; Abschnitte und Projektaufgaben bleiben ihren Projekten zugeordnet. Beim Wiederherstellen eines Bereichs werden untergeordnete Elemente, deren Zuordnung während der Löschung aufgehoben wurde, nicht erneut zugewiesen.
Personenoperationen
// Create
addPerson(name: string, initialProps?: Partial<Person>): Promise<Person | null>;
// Update metadata
updatePerson(id: string, updates: Partial<Person>): Promise<StoreActionResult>;
// Rename and optionally update exact task assignments
renamePerson(id: string, name: string, options?: { updateTasks?: boolean }): Promise<StoreActionResult>;
// Delete (soft, does not clear task assignments)
deletePerson(id: string): Promise<StoreActionResult>;Abschnittsoperationen
// Create
addSection(projectId: string, title: string, initialProps?: Partial<Section>): Promise<Section | null>;
// Update
updateSection(id: string, updates: Partial<Section>): Promise<StoreActionResult>;
// Delete
deleteSection(id: string): Promise<StoreActionResult>;
// Restore
restoreSection(id: string): Promise<StoreActionResult>;Tag-Operationen
// Delete (from all tasks and projects)
deleteTag(tagId: string): Promise<void>;Datenoperationen
// Load
fetchData(): Promise<void>;
// Settings
updateSettings(updates: Partial<AppData['settings']>): Promise<void>;Speicheradapter
setStorageAdapter
Konfiguriert das Speicher-Backend.
import { setStorageAdapter } from '@mindwtr/core';
// Must be called before using the store
setStorageAdapter(myStorageAdapter);StorageAdapter-Schnittstelle
interface StorageAdapter {
getData: () => Promise<AppData>;
saveData: (data: AppData) => Promise<void>;
saveTask?: (task: Task, snapshot?: AppData) => Promise<void>;
queryTasks?: (options: TaskQueryOptions) => Promise<Task[]>;
searchAll?: (query: string) => Promise<SearchResults>;
}Parser für „Schnell hinzufügen“
parseQuickAdd
Analysiert Aufgabeneingaben in natürlicher Sprache.
import { parseQuickAdd } from '@mindwtr/core';
const result: QuickAddResult = parseQuickAdd(input, projects, now, areas, options);Gängige Syntax
| Token | Beispiel | Ergebnis |
|---|---|---|
@context | @home | contexts: ['@home'] |
#tag | #focused | tags: ['#focused'] |
+Project | +HomeReno | projectId: 'matching-id' |
!Area | !Work | areaId: 'matching-id' |
/area:<name> | /area:Personal | areaId: 'matching-id' |
%Person | %Jim oder %"Jim Smith" | assignedTo: 'Jim' (bekannte Namen werden über knownPeople auch als mehrteilige Namen ohne Anführungszeichen erkannt) |
/due:date | /due:friday | dueDate: 'ISO string' |
/energy:<level> | /energy:high | energyLevel: 'high' (unterstützt low, medium, high) |
/note:text | /note:remember X | description: 'remember X' |
/status | /next | status: 'next' (unterstützt /inbox, /waiting, /someday, /done, /archived) |
Synchronisierung
performSyncCycle
Führt einen vollständigen Synchronisierungszyklus aus (lokal lesen -> entfernt lesen -> zusammenführen -> zurückschreiben).
import { performSyncCycle } from '@mindwtr/core';
const result = await performSyncCycle({
readLocal: () => Promise<AppData>,
readRemote: () => Promise<AppData | null>,
writeLocal: (data) => Promise<void>,
writeRemote: (data) => Promise<void>
});mergeAppData
Führt zwei AppData-Objekte mithilfe von Last-Write-Wins zusammen.
import { mergeAppData } from '@mindwtr/core';
const merged = mergeAppData(localData: AppData, remoteData: AppData);Internationalisierung
loadTranslations
Lädt die Übersetzungszeichenfolgen einer Sprache. Wörterbücher werden bei Bedarf geladen, daher liefert getTranslationsSync die englischen Zeichenfolgen, bis diese Sprache einmal geladen wurde.
import { loadTranslations, getTranslationsSync } from '@mindwtr/core';
const zh = await loadTranslations('zh');
zh['nav.inbox']; // '收集箱'
getTranslationsSync('zh')['nav.inbox']; // '收集箱' once loaded