focus-flow/lib/src/persistence_contract.dart

361 lines
10 KiB
Dart

// MongoDB-oriented persistence contract helpers.
//
// This file defines stable names and conventions that future document mapping
// code should use. It deliberately does not serialize domain models or import a
// MongoDB client.
import 'time_contracts.dart';
/// DateTime storage convention for future document persistence.
abstract final class PersistenceDateTimeConvention {
/// Human-readable convention kept close to the helper for tests and docs.
static const description =
'Store DateTime values as UTC ISO-8601 strings and compare as UTC instants.';
/// Convert a DateTime into the persisted string convention.
static String toStoredString(DateTime value) {
return value.toUtc().toIso8601String();
}
/// Parse a persisted DateTime string back into a UTC DateTime.
static DateTime fromStoredString(String value) {
return DateTime.parse(value).toUtc();
}
/// Compare two DateTime values by their UTC instant.
static int compare(DateTime left, DateTime right) {
return left.toUtc().compareTo(right.toUtc());
}
}
/// Civil-date storage convention for future document persistence.
abstract final class PersistenceCivilDateConvention {
/// Human-readable convention kept close to the helper for tests and docs.
static const description =
'Store CivilDate values as YYYY-MM-DD strings without timezone conversion.';
/// Convert a CivilDate into the persisted string convention.
static String toStoredString(CivilDate value) {
return value.toIsoString();
}
/// Parse a persisted CivilDate string without applying a timezone.
static CivilDate fromStoredString(String value) {
return CivilDate.fromIsoString(value);
}
}
/// Wall-time storage convention for future document persistence.
abstract final class PersistenceWallTimeConvention {
/// Human-readable convention kept close to the helper for tests and docs.
static const description =
'Store WallTime values as HH:MM strings without date or timezone data.';
/// Convert a WallTime into the persisted string convention.
static String toStoredString(WallTime value) {
return value.toIsoString();
}
/// Parse a persisted WallTime string without applying a date or timezone.
static WallTime fromStoredString(String value) {
return WallTime.fromIsoString(value);
}
}
/// Stable enum-name mapping plan for future document persistence.
extension PersistenceEnumName on Enum {
/// Persist enum values by their Dart enum name.
String get persistenceName => name;
}
/// Shared MongoDB document field names.
abstract final class DocumentFields {
/// MongoDB primary id field.
static const id = '_id';
}
/// Document field names for [Task] documents.
abstract final class TaskDocumentFields {
static const id = DocumentFields.id;
static const title = 'title';
static const projectId = 'projectId';
static const type = 'type';
static const status = 'status';
static const priority = 'priority';
static const reward = 'reward';
static const difficulty = 'difficulty';
static const durationMinutes = 'durationMinutes';
static const scheduledStart = 'scheduledStart';
static const scheduledEnd = 'scheduledEnd';
static const actualStart = 'actualStart';
static const actualEnd = 'actualEnd';
static const parentTaskId = 'parentTaskId';
static const backlogTags = 'backlogTags';
static const reminderOverride = 'reminderOverride';
static const createdAt = 'createdAt';
static const updatedAt = 'updatedAt';
static const stats = 'stats';
static const all = <String>{
id,
title,
projectId,
type,
status,
priority,
reward,
difficulty,
durationMinutes,
scheduledStart,
scheduledEnd,
actualStart,
actualEnd,
parentTaskId,
backlogTags,
reminderOverride,
createdAt,
updatedAt,
stats,
};
}
/// Document field names for [TaskStatistics] embedded documents.
abstract final class TaskStatisticsDocumentFields {
static const skippedDuringBurnoutCount = 'skippedDuringBurnoutCount';
static const manuallyPushedCount = 'manuallyPushedCount';
static const autoPushedCount = 'autoPushedCount';
static const movedToBacklogCount = 'movedToBacklogCount';
static const restoredFromBacklogCount = 'restoredFromBacklogCount';
static const missedCount = 'missedCount';
static const cancelledCount = 'cancelledCount';
static const completedLateCount = 'completedLateCount';
static const completedDuringLockedHoursCount =
'completedDuringLockedHoursCount';
static const completedDuringLockedHoursMinutes =
'completedDuringLockedHoursMinutes';
static const all = <String>{
skippedDuringBurnoutCount,
manuallyPushedCount,
autoPushedCount,
movedToBacklogCount,
restoredFromBacklogCount,
missedCount,
cancelledCount,
completedLateCount,
completedDuringLockedHoursCount,
completedDuringLockedHoursMinutes,
};
}
/// Document field names for [ProjectProfile] documents.
abstract final class ProjectDocumentFields {
static const id = DocumentFields.id;
static const name = 'name';
static const colorKey = 'colorKey';
static const defaultPriority = 'defaultPriority';
static const defaultReward = 'defaultReward';
static const defaultDifficulty = 'defaultDifficulty';
static const defaultReminderProfile = 'defaultReminderProfile';
static const defaultDurationMinutes = 'defaultDurationMinutes';
static const all = <String>{
id,
name,
colorKey,
defaultPriority,
defaultReward,
defaultDifficulty,
defaultReminderProfile,
defaultDurationMinutes,
};
}
/// Document field names for [ClockTime] embedded documents.
abstract final class ClockTimeDocumentFields {
static const hour = 'hour';
static const minute = 'minute';
static const all = <String>{
hour,
minute,
};
}
/// Document field names for [LockedBlockRecurrence] embedded documents.
abstract final class LockedBlockRecurrenceDocumentFields {
static const weekdays = 'weekdays';
static const all = <String>{
weekdays,
};
}
/// Document field names for [LockedBlock] documents.
abstract final class LockedBlockDocumentFields {
static const id = DocumentFields.id;
static const name = 'name';
static const startTime = 'startTime';
static const endTime = 'endTime';
static const date = 'date';
static const recurrence = 'recurrence';
static const hiddenByDefault = 'hiddenByDefault';
static const projectId = 'projectId';
static const createdAt = 'createdAt';
static const updatedAt = 'updatedAt';
static const all = <String>{
id,
name,
startTime,
endTime,
date,
recurrence,
hiddenByDefault,
projectId,
createdAt,
updatedAt,
};
}
/// Document field names for [LockedBlockOverride] documents.
abstract final class LockedBlockOverrideDocumentFields {
static const id = DocumentFields.id;
static const lockedBlockId = 'lockedBlockId';
static const date = 'date';
static const type = 'type';
static const name = 'name';
static const startTime = 'startTime';
static const endTime = 'endTime';
static const hiddenByDefault = 'hiddenByDefault';
static const projectId = 'projectId';
static const createdAt = 'createdAt';
static const updatedAt = 'updatedAt';
static const all = <String>{
id,
lockedBlockId,
date,
type,
name,
startTime,
endTime,
hiddenByDefault,
projectId,
createdAt,
updatedAt,
};
}
/// Document field names for [SchedulingStateSnapshot] documents.
abstract final class SchedulingSnapshotDocumentFields {
static const id = DocumentFields.id;
static const capturedAt = 'capturedAt';
static const window = 'window';
static const tasks = 'tasks';
static const lockedIntervals = 'lockedIntervals';
static const requiredVisibleIntervals = 'requiredVisibleIntervals';
static const notices = 'notices';
static const changes = 'changes';
static const overlaps = 'overlaps';
static const operationName = 'operationName';
static const all = <String>{
id,
capturedAt,
window,
tasks,
lockedIntervals,
requiredVisibleIntervals,
notices,
changes,
overlaps,
operationName,
};
}
/// Document field names for [SchedulingWindow] embedded documents.
abstract final class SchedulingWindowDocumentFields {
static const start = 'start';
static const end = 'end';
static const all = <String>{
start,
end,
};
}
/// Document field names for [TimeInterval] embedded documents.
abstract final class TimeIntervalDocumentFields {
static const start = 'start';
static const end = 'end';
static const label = 'label';
static const all = <String>{
start,
end,
label,
};
}
/// Document field names for [SchedulingNotice] embedded documents.
abstract final class SchedulingNoticeDocumentFields {
static const message = 'message';
static const type = 'type';
static const taskId = 'taskId';
static const all = <String>{
message,
type,
taskId,
};
}
/// Document field names for [SchedulingChange] embedded documents.
abstract final class SchedulingChangeDocumentFields {
static const taskId = 'taskId';
static const previousStart = 'previousStart';
static const previousEnd = 'previousEnd';
static const nextStart = 'nextStart';
static const nextEnd = 'nextEnd';
static const all = <String>{
taskId,
previousStart,
previousEnd,
nextStart,
nextEnd,
};
}
/// Document field names for [SchedulingOverlap] embedded documents.
abstract final class SchedulingOverlapDocumentFields {
static const taskId = 'taskId';
static const taskInterval = 'taskInterval';
static const blockedInterval = 'blockedInterval';
static const all = <String>{
taskId,
taskInterval,
blockedInterval,
};
}
/// Every field-name set currently committed for future document mapping.
abstract final class PersistenceDocumentFieldSets {
static const all = <Set<String>>[
TaskDocumentFields.all,
TaskStatisticsDocumentFields.all,
ProjectDocumentFields.all,
ClockTimeDocumentFields.all,
LockedBlockRecurrenceDocumentFields.all,
LockedBlockDocumentFields.all,
LockedBlockOverrideDocumentFields.all,
SchedulingSnapshotDocumentFields.all,
SchedulingWindowDocumentFields.all,
TimeIntervalDocumentFields.all,
SchedulingNoticeDocumentFields.all,
SchedulingChangeDocumentFields.all,
SchedulingOverlapDocumentFields.all,
];
}