dumpDatabase.ts•6.14 kB
import { OmnifocusDatabase, OmnifocusTask, OmnifocusProject, OmnifocusFolder, OmnifocusTag } from '../types.js';
import { executeOmniFocusScript } from '../utils/scriptExecution.js';
import fs from 'fs';
// Define interfaces for the data returned from the script
interface OmnifocusDumpTask {
id: string;
name: string;
note?: string;
taskStatus: string;
flagged: boolean;
dueDate: string | null;
deferDate: string | null;
effectiveDueDate: string | null;
effectiveDeferDate: string | null;
estimatedMinutes: number | null;
completedByChildren: boolean;
sequential: boolean;
tags: string[];
projectID: string | null;
parentTaskID: string | null;
children: string[];
inInbox: boolean;
}
interface OmnifocusDumpProject {
id: string;
name: string;
status: string;
folderID: string | null;
sequential: boolean;
effectiveDueDate: string | null;
effectiveDeferDate: string | null;
dueDate: string | null;
deferDate: string | null;
completedByChildren: boolean;
containsSingletonActions: boolean;
note: string;
tasks: string[];
}
interface OmnifocusDumpFolder {
id: string;
name: string;
parentFolderID: string | null;
status: string;
projects: string[];
subfolders: string[];
}
interface OmnifocusDumpTag {
id: string;
name: string;
parentTagID: string | null;
active: boolean;
allowsNextAction: boolean;
tasks: string[];
}
interface OmnifocusDumpData {
exportDate: string;
tasks: OmnifocusDumpTask[];
projects: Record<string, OmnifocusDumpProject>;
folders: Record<string, OmnifocusDumpFolder>;
tags: Record<string, OmnifocusDumpTag>;
}
// Main function to dump the database
export async function dumpDatabase(): Promise<OmnifocusDatabase> {
try {
// Execute the OmniFocus script
const data = await executeOmniFocusScript('@omnifocusDump.js') as OmnifocusDumpData;
// wait 1 second
await new Promise(resolve => setTimeout(resolve, 1000));
// Create an empty database if no data returned
if (!data) {
return {
exportDate: new Date().toISOString(),
tasks: [],
projects: {},
folders: {},
tags: {}
};
}
// Initialize the database object
const database: OmnifocusDatabase = {
exportDate: data.exportDate,
tasks: [],
projects: {},
folders: {},
tags: {}
};
// Process tasks
if (data.tasks && Array.isArray(data.tasks)) {
// Convert the tasks to our OmnifocusTask format
database.tasks = data.tasks.map((task: OmnifocusDumpTask) => {
// Get tag names from the tag IDs
const tagNames = (task.tags || []).map(tagId => {
return data.tags[tagId]?.name || 'Unknown Tag';
});
return {
id: String(task.id),
name: String(task.name),
note: String(task.note || ""),
flagged: Boolean(task.flagged),
completed: task.taskStatus === "Completed",
completionDate: null, // Not available in the new format
dropDate: null, // Not available in the new format
taskStatus: String(task.taskStatus),
active: task.taskStatus !== "Completed" && task.taskStatus !== "Dropped",
dueDate: task.dueDate,
deferDate: task.deferDate,
estimatedMinutes: task.estimatedMinutes ? Number(task.estimatedMinutes) : null,
tags: task.tags || [],
tagNames: tagNames,
parentId: task.parentTaskID || null,
containingProjectId: task.projectID || null,
projectId: task.projectID || null,
childIds: task.children || [],
hasChildren: (task.children && task.children.length > 0) || false,
sequential: Boolean(task.sequential),
completedByChildren: Boolean(task.completedByChildren),
isRepeating: false, // Not available in the new format
repetitionMethod: null, // Not available in the new format
repetitionRule: null, // Not available in the new format
attachments: [], // Default empty array
linkedFileURLs: [], // Default empty array
notifications: [], // Default empty array
shouldUseFloatingTimeZone: false // Default value
};
});
}
// Process projects
if (data.projects) {
for (const [id, project] of Object.entries(data.projects)) {
database.projects[id] = {
id: String(project.id),
name: String(project.name),
status: String(project.status),
folderID: project.folderID || null,
sequential: Boolean(project.sequential),
effectiveDueDate: project.effectiveDueDate,
effectiveDeferDate: project.effectiveDeferDate,
dueDate: project.dueDate,
deferDate: project.deferDate,
completedByChildren: Boolean(project.completedByChildren),
containsSingletonActions: Boolean(project.containsSingletonActions),
note: String(project.note || ""),
tasks: project.tasks || [],
flagged: false, // Default value
estimatedMinutes: null // Default value
};
}
}
// Process folders
if (data.folders) {
for (const [id, folder] of Object.entries(data.folders)) {
database.folders[id] = {
id: String(folder.id),
name: String(folder.name),
parentFolderID: folder.parentFolderID || null,
status: String(folder.status),
projects: folder.projects || [],
subfolders: folder.subfolders || []
};
}
}
// Process tags
if (data.tags) {
for (const [id, tag] of Object.entries(data.tags)) {
database.tags[id] = {
id: String(tag.id),
name: String(tag.name),
parentTagID: tag.parentTagID || null,
active: Boolean(tag.active),
allowsNextAction: Boolean(tag.allowsNextAction),
tasks: tag.tasks || []
};
}
}
return database;
} catch (error) {
console.error("Error in dumpDatabase:", error);
throw error;
}
}