@stephendolan/omnifocus-cli 2.0.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- // src/index.ts
3
+ // src/cli.ts
4
4
  import { Command as Command8 } from "commander";
5
5
 
6
6
  // src/lib/output.ts
@@ -17,9 +17,45 @@ function outputJson(data, options = {}) {
17
17
  // src/commands/task.ts
18
18
  import { Command } from "commander";
19
19
 
20
+ // src/lib/errors.ts
21
+ var OmniFocusCliError = class extends Error {
22
+ constructor(message, statusCode = 500) {
23
+ super(message);
24
+ this.statusCode = statusCode;
25
+ this.name = "OmniFocusCliError";
26
+ }
27
+ };
28
+ function handleError(error) {
29
+ let name = "unknown_error";
30
+ let detail = "An unknown error occurred";
31
+ let statusCode = 500;
32
+ if (error instanceof OmniFocusCliError) {
33
+ name = "cli_error";
34
+ detail = error.message;
35
+ statusCode = error.statusCode;
36
+ } else if (error instanceof Error) {
37
+ name = "omnifocus_error";
38
+ detail = error.message;
39
+ if (detail.includes("not found")) {
40
+ statusCode = 404;
41
+ } else if (detail.includes("Multiple")) {
42
+ statusCode = 400;
43
+ }
44
+ }
45
+ outputJson({ error: { name, detail, statusCode } });
46
+ process.exit(1);
47
+ }
48
+
20
49
  // src/lib/command-utils.ts
21
- import ora from "ora";
22
- import chalk from "chalk";
50
+ function withErrorHandling(fn) {
51
+ return async (...args) => {
52
+ try {
53
+ await fn(...args);
54
+ } catch (error) {
55
+ handleError(error);
56
+ }
57
+ };
58
+ }
23
59
 
24
60
  // src/lib/omnifocus.ts
25
61
  import { execFile } from "child_process";
@@ -333,7 +369,7 @@ var OmniFocus = class {
333
369
  updates.push(`task.flagged = ${options.flagged};`);
334
370
  }
335
371
  if (options.completed !== void 0) {
336
- updates.push(`task.completed = ${options.completed};`);
372
+ updates.push(options.completed ? "task.markComplete();" : "task.markIncomplete();");
337
373
  }
338
374
  if (options.estimatedMinutes !== void 0) {
339
375
  updates.push(`task.estimatedMinutes = ${options.estimatedMinutes};`);
@@ -945,109 +981,94 @@ var OmniFocus = class {
945
981
  }
946
982
  };
947
983
 
948
- // src/lib/command-utils.ts
949
- async function executeCommand(loadingMessage, action, onSuccess, failureMessage) {
950
- const spinner = ora(loadingMessage).start();
951
- try {
952
- const result = await action();
953
- spinner.stop();
954
- onSuccess?.(result);
955
- return result;
956
- } catch (error) {
957
- spinner.fail(failureMessage || "Command failed");
958
- console.error(chalk.red(error.message));
959
- throw error;
984
+ // src/lib/dates.ts
985
+ import dayjs from "dayjs";
986
+ function parseDateTime(input) {
987
+ const d = dayjs(input);
988
+ if (!d.isValid()) {
989
+ throw new OmniFocusCliError(`Invalid date: ${input}`, 400);
960
990
  }
961
- }
962
- async function executeOmniFocusCommand(loadingMessage, action, onSuccess, failureMessage) {
963
- const of = new OmniFocus();
964
- return executeCommand(loadingMessage, () => action(of), onSuccess, failureMessage);
991
+ return d.toISOString();
965
992
  }
966
993
 
967
994
  // src/commands/task.ts
968
995
  function createTaskCommand() {
969
996
  const command = new Command("task");
970
997
  command.description("Manage OmniFocus tasks");
971
- command.command("list").alias("ls").description("List tasks").option("-f, --flagged", "Show only flagged tasks").option("-p, --project <name>", "Filter by project").option("-t, --tag <name>", "Filter by tag").option("-c, --completed", "Include completed tasks").action(async (options) => {
972
- await executeOmniFocusCommand(
973
- "Loading tasks...",
974
- (of) => {
975
- const filters = {
976
- includeCompleted: options.completed,
977
- ...options.flagged && { flagged: true },
978
- ...options.project && { project: options.project },
979
- ...options.tag && { tag: options.tag }
980
- };
981
- return of.listTasks(filters);
982
- },
983
- (tasks) => outputJson(tasks),
984
- "Failed to load tasks"
985
- );
986
- });
987
- command.command("create <name>").description("Create a new task").option("-p, --project <name>", "Assign to project").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date (ISO format)").option("-D, --defer <date>", "Set defer date (ISO format)").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(async (name, options) => {
988
- await executeOmniFocusCommand(
989
- "Creating task...",
990
- (of) => of.createTask({
998
+ command.command("list").alias("ls").description("List tasks").option("-f, --flagged", "Show only flagged tasks").option("-p, --project <name>", "Filter by project").option("-t, --tag <name>", "Filter by tag").option("-c, --completed", "Include completed tasks").action(
999
+ withErrorHandling(async (options) => {
1000
+ const of = new OmniFocus();
1001
+ const filters = {
1002
+ includeCompleted: options.completed,
1003
+ ...options.flagged && { flagged: true },
1004
+ ...options.project && { project: options.project },
1005
+ ...options.tag && { tag: options.tag }
1006
+ };
1007
+ const tasks = await of.listTasks(filters);
1008
+ outputJson(tasks);
1009
+ })
1010
+ );
1011
+ command.command("create <name>").description("Create a new task").option("-p, --project <name>", "Assign to project").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
1012
+ withErrorHandling(async (name, options) => {
1013
+ const of = new OmniFocus();
1014
+ const task = await of.createTask({
991
1015
  name,
992
1016
  note: options.note,
993
1017
  project: options.project,
994
1018
  tags: options.tag,
995
- due: options.due,
996
- defer: options.defer,
1019
+ due: options.due ? parseDateTime(options.due) : void 0,
1020
+ defer: options.defer ? parseDateTime(options.defer) : void 0,
997
1021
  flagged: options.flagged,
998
1022
  estimatedMinutes: options.estimate
999
- }),
1000
- (task) => outputJson(task),
1001
- "Failed to create task"
1002
- );
1003
- });
1004
- command.command("update <idOrName>").description("Update an existing task").option("-n, --name <name>", "New name").option("--note <text>", "New note").option("-p, --project <name>", "Move to project").option("-t, --tag <tags...>", "Replace tags").option("-d, --due <date>", "Set due date (ISO format)").option("-D, --defer <date>", "Set defer date (ISO format)").option("-f, --flag", "Flag the task").option("-F, --unflag", "Unflag the task").option("-c, --complete", "Mark as completed").option("-C, --incomplete", "Mark as incomplete").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(async (idOrName, options) => {
1005
- await executeOmniFocusCommand(
1006
- "Updating task...",
1007
- (of) => {
1008
- const updates = {
1009
- ...options.name && { name: options.name },
1010
- ...options.note !== void 0 && { note: options.note },
1011
- ...options.project && { project: options.project },
1012
- ...options.tag && { tags: options.tag },
1013
- ...options.due !== void 0 && { due: options.due },
1014
- ...options.defer !== void 0 && { defer: options.defer },
1015
- ...options.flag && { flagged: true },
1016
- ...options.unflag && { flagged: false },
1017
- ...options.complete && { completed: true },
1018
- ...options.incomplete && { completed: false },
1019
- ...options.estimate !== void 0 && { estimatedMinutes: options.estimate }
1020
- };
1021
- return of.updateTask(idOrName, updates);
1022
- },
1023
- (task) => outputJson(task),
1024
- "Failed to update task"
1025
- );
1026
- });
1027
- command.command("delete <idOrName>").alias("rm").description("Delete a task").action(async (idOrName) => {
1028
- await executeOmniFocusCommand(
1029
- "Deleting task...",
1030
- (of) => of.deleteTask(idOrName),
1031
- () => outputJson({ message: "Task deleted successfully" }),
1032
- "Failed to delete task"
1033
- );
1034
- });
1035
- command.command("view <idOrName>").description("View task details").action(async (idOrName) => {
1036
- await executeOmniFocusCommand(
1037
- "Loading task...",
1038
- (of) => of.getTask(idOrName),
1039
- (task) => outputJson(task),
1040
- "Failed to load task"
1041
- );
1042
- });
1043
- command.command("stats").description("Show task statistics").action(async () => {
1044
- await executeOmniFocusCommand(
1045
- "Analyzing tasks...",
1046
- (of) => of.getTaskStats(),
1047
- (stats) => outputJson(stats),
1048
- "Failed to analyze tasks"
1049
- );
1050
- });
1023
+ });
1024
+ outputJson(task);
1025
+ })
1026
+ );
1027
+ command.command("update <idOrName>").description("Update an existing task").option("-n, --name <name>", "New name").option("--note <text>", "New note").option("-p, --project <name>", "Move to project").option("-t, --tag <tags...>", "Replace tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flag", "Flag the task").option("-F, --unflag", "Unflag the task").option("-c, --complete", "Mark as completed").option("-C, --incomplete", "Mark as incomplete").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
1028
+ withErrorHandling(async (idOrName, options) => {
1029
+ const of = new OmniFocus();
1030
+ const updates = {
1031
+ ...options.name && { name: options.name },
1032
+ ...options.note !== void 0 && { note: options.note },
1033
+ ...options.project && { project: options.project },
1034
+ ...options.tag && { tags: options.tag },
1035
+ ...options.due !== void 0 && {
1036
+ due: options.due ? parseDateTime(options.due) : null
1037
+ },
1038
+ ...options.defer !== void 0 && {
1039
+ defer: options.defer ? parseDateTime(options.defer) : null
1040
+ },
1041
+ ...options.flag && { flagged: true },
1042
+ ...options.unflag && { flagged: false },
1043
+ ...options.complete && { completed: true },
1044
+ ...options.incomplete && { completed: false },
1045
+ ...options.estimate !== void 0 && { estimatedMinutes: options.estimate }
1046
+ };
1047
+ const task = await of.updateTask(idOrName, updates);
1048
+ outputJson(task);
1049
+ })
1050
+ );
1051
+ command.command("delete <idOrName>").alias("rm").description("Delete a task").action(
1052
+ withErrorHandling(async (idOrName) => {
1053
+ const of = new OmniFocus();
1054
+ await of.deleteTask(idOrName);
1055
+ outputJson({ message: "Task deleted successfully" });
1056
+ })
1057
+ );
1058
+ command.command("view <idOrName>").description("View task details").action(
1059
+ withErrorHandling(async (idOrName) => {
1060
+ const of = new OmniFocus();
1061
+ const task = await of.getTask(idOrName);
1062
+ outputJson(task);
1063
+ })
1064
+ );
1065
+ command.command("stats").description("Show task statistics").action(
1066
+ withErrorHandling(async () => {
1067
+ const of = new OmniFocus();
1068
+ const stats = await of.getTaskStats();
1069
+ outputJson(stats);
1070
+ })
1071
+ );
1051
1072
  return command;
1052
1073
  }
1053
1074
 
@@ -1056,79 +1077,69 @@ import { Command as Command2 } from "commander";
1056
1077
  function createProjectCommand() {
1057
1078
  const command = new Command2("project");
1058
1079
  command.description("Manage OmniFocus projects");
1059
- command.command("list").alias("ls").description("List projects").option("-f, --folder <name>", "Filter by folder").option("-s, --status <status>", "Filter by status (active, on hold, dropped)").option("-d, --dropped", "Include dropped projects").action(async (options) => {
1060
- await executeOmniFocusCommand(
1061
- "Loading projects...",
1062
- (of) => {
1063
- const filters = {
1064
- includeDropped: options.dropped,
1065
- ...options.folder && { folder: options.folder },
1066
- ...options.status && { status: options.status }
1067
- };
1068
- return of.listProjects(filters);
1069
- },
1070
- (projects) => outputJson(projects),
1071
- "Failed to load projects"
1072
- );
1073
- });
1074
- command.command("create <name>").description("Create a new project").option("-f, --folder <name>", "Assign to folder").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-s, --sequential", "Make it a sequential project").option("--status <status>", "Set status (active, on hold, dropped)").action(async (name, options) => {
1075
- await executeOmniFocusCommand(
1076
- "Creating project...",
1077
- (of) => of.createProject({
1080
+ command.command("list").alias("ls").description("List projects").option("-f, --folder <name>", "Filter by folder").option("-s, --status <status>", "Filter by status (active, on hold, dropped)").option("-d, --dropped", "Include dropped projects").action(
1081
+ withErrorHandling(async (options) => {
1082
+ const of = new OmniFocus();
1083
+ const filters = {
1084
+ includeDropped: options.dropped,
1085
+ ...options.folder && { folder: options.folder },
1086
+ ...options.status && { status: options.status }
1087
+ };
1088
+ const projects = await of.listProjects(filters);
1089
+ outputJson(projects);
1090
+ })
1091
+ );
1092
+ command.command("create <name>").description("Create a new project").option("-f, --folder <name>", "Assign to folder").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-s, --sequential", "Make it a sequential project").option("--status <status>", "Set status (active, on hold, dropped)").action(
1093
+ withErrorHandling(async (name, options) => {
1094
+ const of = new OmniFocus();
1095
+ const project = await of.createProject({
1078
1096
  name,
1079
1097
  note: options.note,
1080
1098
  folder: options.folder,
1081
1099
  tags: options.tag,
1082
1100
  sequential: options.sequential,
1083
1101
  status: options.status
1084
- }),
1085
- (project) => outputJson(project),
1086
- "Failed to create project"
1087
- );
1088
- });
1089
- command.command("update <idOrName>").description("Update an existing project").option("-n, --name <name>", "Rename project").option("--note <text>", "New note").option("-f, --folder <name>", "Move to folder").option("-t, --tag <tags...>", "Replace tags").option("-s, --sequential", "Make it sequential").option("-p, --parallel", "Make it parallel").option("--status <status>", "Set status (active, on hold, dropped)").action(async (idOrName, options) => {
1090
- await executeOmniFocusCommand(
1091
- "Updating project...",
1092
- (of) => {
1093
- const updates = {
1094
- ...options.name && { name: options.name },
1095
- ...options.note !== void 0 && { note: options.note },
1096
- ...options.folder && { folder: options.folder },
1097
- ...options.tag && { tags: options.tag },
1098
- ...options.sequential && { sequential: true },
1099
- ...options.parallel && { sequential: false },
1100
- ...options.status && { status: options.status }
1101
- };
1102
- return of.updateProject(idOrName, updates);
1103
- },
1104
- (project) => outputJson(project),
1105
- "Failed to update project"
1106
- );
1107
- });
1108
- command.command("delete <idOrName>").alias("rm").description("Delete a project").action(async (idOrName) => {
1109
- await executeOmniFocusCommand(
1110
- "Deleting project...",
1111
- (of) => of.deleteProject(idOrName),
1112
- () => outputJson({ message: "Project deleted successfully" }),
1113
- "Failed to delete project"
1114
- );
1115
- });
1116
- command.command("view <idOrName>").description("View project details").action(async (idOrName) => {
1117
- await executeOmniFocusCommand(
1118
- "Loading project...",
1119
- (of) => of.getProject(idOrName),
1120
- (project) => outputJson(project),
1121
- "Failed to load project"
1122
- );
1123
- });
1124
- command.command("stats").description("Show project statistics").action(async () => {
1125
- await executeOmniFocusCommand(
1126
- "Analyzing projects...",
1127
- (of) => of.getProjectStats(),
1128
- (stats) => outputJson(stats),
1129
- "Failed to analyze projects"
1130
- );
1131
- });
1102
+ });
1103
+ outputJson(project);
1104
+ })
1105
+ );
1106
+ command.command("update <idOrName>").description("Update an existing project").option("-n, --name <name>", "Rename project").option("--note <text>", "New note").option("-f, --folder <name>", "Move to folder").option("-t, --tag <tags...>", "Replace tags").option("-s, --sequential", "Make it sequential").option("-p, --parallel", "Make it parallel").option("--status <status>", "Set status (active, on hold, dropped)").action(
1107
+ withErrorHandling(async (idOrName, options) => {
1108
+ const of = new OmniFocus();
1109
+ const updates = {
1110
+ ...options.name && { name: options.name },
1111
+ ...options.note !== void 0 && { note: options.note },
1112
+ ...options.folder && { folder: options.folder },
1113
+ ...options.tag && { tags: options.tag },
1114
+ ...options.sequential && { sequential: true },
1115
+ ...options.parallel && { sequential: false },
1116
+ ...options.status && { status: options.status }
1117
+ };
1118
+ const project = await of.updateProject(idOrName, updates);
1119
+ outputJson(project);
1120
+ })
1121
+ );
1122
+ command.command("delete <idOrName>").alias("rm").description("Delete a project").action(
1123
+ withErrorHandling(async (idOrName) => {
1124
+ const of = new OmniFocus();
1125
+ await of.deleteProject(idOrName);
1126
+ outputJson({ message: "Project deleted successfully" });
1127
+ })
1128
+ );
1129
+ command.command("view <idOrName>").description("View project details").action(
1130
+ withErrorHandling(async (idOrName) => {
1131
+ const of = new OmniFocus();
1132
+ const project = await of.getProject(idOrName);
1133
+ outputJson(project);
1134
+ })
1135
+ );
1136
+ command.command("stats").description("Show project statistics").action(
1137
+ withErrorHandling(async () => {
1138
+ const of = new OmniFocus();
1139
+ const stats = await of.getProjectStats();
1140
+ outputJson(stats);
1141
+ })
1142
+ );
1132
1143
  return command;
1133
1144
  }
1134
1145
 
@@ -1137,22 +1148,35 @@ import { Command as Command3 } from "commander";
1137
1148
  function createInboxCommand() {
1138
1149
  const command = new Command3("inbox");
1139
1150
  command.description("Manage OmniFocus inbox");
1140
- command.command("list").alias("ls").description("List inbox tasks").action(async () => {
1141
- await executeOmniFocusCommand(
1142
- "Loading inbox...",
1143
- (of) => of.listInboxTasks(),
1144
- (tasks) => outputJson(tasks),
1145
- "Failed to load inbox"
1146
- );
1147
- });
1148
- command.command("count").description("Get inbox count").action(async () => {
1149
- await executeOmniFocusCommand(
1150
- "Counting inbox items...",
1151
- (of) => of.getInboxCount(),
1152
- (count) => outputJson({ count }),
1153
- "Failed to get inbox count"
1154
- );
1155
- });
1151
+ command.command("list").alias("ls").description("List inbox tasks").action(
1152
+ withErrorHandling(async () => {
1153
+ const of = new OmniFocus();
1154
+ const tasks = await of.listInboxTasks();
1155
+ outputJson(tasks);
1156
+ })
1157
+ );
1158
+ command.command("count").description("Get inbox count").action(
1159
+ withErrorHandling(async () => {
1160
+ const of = new OmniFocus();
1161
+ const count = await of.getInboxCount();
1162
+ outputJson({ count });
1163
+ })
1164
+ );
1165
+ command.command("add <name>").description("Add a task to inbox").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
1166
+ withErrorHandling(async (name, options) => {
1167
+ const of = new OmniFocus();
1168
+ const task = await of.createTask({
1169
+ name,
1170
+ note: options.note,
1171
+ tags: options.tag,
1172
+ due: options.due ? parseDateTime(options.due) : void 0,
1173
+ defer: options.defer ? parseDateTime(options.defer) : void 0,
1174
+ flagged: options.flagged,
1175
+ estimatedMinutes: options.estimate
1176
+ });
1177
+ outputJson(task);
1178
+ })
1179
+ );
1156
1180
  return command;
1157
1181
  }
1158
1182
 
@@ -1162,14 +1186,13 @@ function createSearchCommand() {
1162
1186
  const command = new Command4("search");
1163
1187
  command.description("Search tasks by name or note");
1164
1188
  command.argument("<query>", "Search query");
1165
- command.action(async (query) => {
1166
- await executeOmniFocusCommand(
1167
- "Searching...",
1168
- (of) => of.searchTasks(query),
1169
- (tasks) => outputJson(tasks),
1170
- "Search failed"
1171
- );
1172
- });
1189
+ command.action(
1190
+ withErrorHandling(async (query) => {
1191
+ const of = new OmniFocus();
1192
+ const tasks = await of.searchTasks(query);
1193
+ outputJson(tasks);
1194
+ })
1195
+ );
1173
1196
  return command;
1174
1197
  }
1175
1198
 
@@ -1178,22 +1201,20 @@ import { Command as Command5 } from "commander";
1178
1201
  function createPerspectiveCommand() {
1179
1202
  const command = new Command5("perspective");
1180
1203
  command.description("Manage OmniFocus perspectives");
1181
- command.command("list").alias("ls").description("List all perspectives").action(async () => {
1182
- await executeOmniFocusCommand(
1183
- "Loading perspectives...",
1184
- (of) => of.listPerspectives(),
1185
- (perspectives) => outputJson(perspectives),
1186
- "Failed to load perspectives"
1187
- );
1188
- });
1189
- command.command("view <name>").description("View tasks in a perspective").action(async (name) => {
1190
- await executeOmniFocusCommand(
1191
- `Loading perspective "${name}"...`,
1192
- (of) => of.getPerspectiveTasks(name),
1193
- (tasks) => outputJson(tasks),
1194
- "Failed to load perspective"
1195
- );
1196
- });
1204
+ command.command("list").alias("ls").description("List all perspectives").action(
1205
+ withErrorHandling(async () => {
1206
+ const of = new OmniFocus();
1207
+ const perspectives = await of.listPerspectives();
1208
+ outputJson(perspectives);
1209
+ })
1210
+ );
1211
+ command.command("view <name>").description("View tasks in a perspective").action(
1212
+ withErrorHandling(async (name) => {
1213
+ const of = new OmniFocus();
1214
+ const tasks = await of.getPerspectiveTasks(name);
1215
+ outputJson(tasks);
1216
+ })
1217
+ );
1197
1218
  return command;
1198
1219
  }
1199
1220
 
@@ -1202,68 +1223,60 @@ import { Command as Command6 } from "commander";
1202
1223
  function createTagCommand() {
1203
1224
  const command = new Command6("tag");
1204
1225
  command.description("Manage and analyze OmniFocus tags");
1205
- command.command("list").alias("ls").description("List tags with usage information").option("-u, --unused-days <days>", "Show tags unused for N days", parseInt).option("-s, --sort <field>", "Sort by: name, usage, activity (default: name)", "name").option("-a, --active-only", "Only count active (incomplete) tasks").action(async (options) => {
1206
- await executeOmniFocusCommand(
1207
- "Loading tags...",
1208
- (of) => of.listTags({
1226
+ command.command("list").alias("ls").description("List tags with usage information").option("-u, --unused-days <days>", "Show tags unused for N days", parseInt).option("-s, --sort <field>", "Sort by: name, usage, activity (default: name)", "name").option("-a, --active-only", "Only count active (incomplete) tasks").action(
1227
+ withErrorHandling(async (options) => {
1228
+ const of = new OmniFocus();
1229
+ const tags = await of.listTags({
1209
1230
  unusedDays: options.unusedDays,
1210
1231
  sortBy: options.sort,
1211
1232
  activeOnly: options.activeOnly
1212
- }),
1213
- (tags) => outputJson(tags),
1214
- "Failed to load tags"
1215
- );
1216
- });
1217
- command.command("create <name>").description("Create a new tag").option("-p, --parent <name>", "Create as child of parent tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(async (name, options) => {
1218
- await executeOmniFocusCommand(
1219
- "Creating tag...",
1220
- (of) => of.createTag({
1233
+ });
1234
+ outputJson(tags);
1235
+ })
1236
+ );
1237
+ command.command("create <name>").description("Create a new tag").option("-p, --parent <name>", "Create as child of parent tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
1238
+ withErrorHandling(async (name, options) => {
1239
+ const of = new OmniFocus();
1240
+ const tag = await of.createTag({
1221
1241
  name,
1222
1242
  parent: options.parent,
1223
1243
  status: options.status
1224
- }),
1225
- (tag) => outputJson(tag),
1226
- "Failed to create tag"
1227
- );
1228
- });
1229
- command.command("view <idOrName>").description("View tag details").action(async (idOrName) => {
1230
- await executeOmniFocusCommand(
1231
- "Loading tag...",
1232
- (of) => of.getTag(idOrName),
1233
- (tag) => outputJson(tag),
1234
- "Failed to load tag"
1235
- );
1236
- });
1237
- command.command("update <idOrName>").description("Update an existing tag").option("-n, --name <name>", "Rename tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(async (idOrName, options) => {
1238
- await executeOmniFocusCommand(
1239
- "Updating tag...",
1240
- (of) => {
1241
- const updates = {
1242
- ...options.name && { name: options.name },
1243
- ...options.status && { status: options.status }
1244
- };
1245
- return of.updateTag(idOrName, updates);
1246
- },
1247
- (tag) => outputJson(tag),
1248
- "Failed to update tag"
1249
- );
1250
- });
1251
- command.command("delete <idOrName>").alias("rm").description("Delete a tag").action(async (idOrName) => {
1252
- await executeOmniFocusCommand(
1253
- "Deleting tag...",
1254
- (of) => of.deleteTag(idOrName),
1255
- () => outputJson({ message: "Tag deleted successfully" }),
1256
- "Failed to delete tag"
1257
- );
1258
- });
1259
- command.command("stats").description("Show tag usage statistics").action(async () => {
1260
- await executeOmniFocusCommand(
1261
- "Analyzing tags...",
1262
- (of) => of.getTagStats(),
1263
- (stats) => outputJson(stats),
1264
- "Failed to analyze tags"
1265
- );
1266
- });
1244
+ });
1245
+ outputJson(tag);
1246
+ })
1247
+ );
1248
+ command.command("view <idOrName>").description("View tag details").action(
1249
+ withErrorHandling(async (idOrName) => {
1250
+ const of = new OmniFocus();
1251
+ const tag = await of.getTag(idOrName);
1252
+ outputJson(tag);
1253
+ })
1254
+ );
1255
+ command.command("update <idOrName>").description("Update an existing tag").option("-n, --name <name>", "Rename tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
1256
+ withErrorHandling(async (idOrName, options) => {
1257
+ const of = new OmniFocus();
1258
+ const updates = {
1259
+ ...options.name && { name: options.name },
1260
+ ...options.status && { status: options.status }
1261
+ };
1262
+ const tag = await of.updateTag(idOrName, updates);
1263
+ outputJson(tag);
1264
+ })
1265
+ );
1266
+ command.command("delete <idOrName>").alias("rm").description("Delete a tag").action(
1267
+ withErrorHandling(async (idOrName) => {
1268
+ const of = new OmniFocus();
1269
+ await of.deleteTag(idOrName);
1270
+ outputJson({ message: "Tag deleted successfully" });
1271
+ })
1272
+ );
1273
+ command.command("stats").description("Show tag usage statistics").action(
1274
+ withErrorHandling(async () => {
1275
+ const of = new OmniFocus();
1276
+ const stats = await of.getTagStats();
1277
+ outputJson(stats);
1278
+ })
1279
+ );
1267
1280
  return command;
1268
1281
  }
1269
1282
 
@@ -1272,29 +1285,27 @@ import { Command as Command7 } from "commander";
1272
1285
  function createFolderCommand() {
1273
1286
  const command = new Command7("folder");
1274
1287
  command.description("View OmniFocus folder hierarchy");
1275
- command.command("list").alias("ls").description("List top-level folders with nested children").option("-d, --dropped", "Include dropped folders").action(async (options) => {
1276
- await executeOmniFocusCommand(
1277
- "Loading folders...",
1278
- (of) => of.listFolders({ includeDropped: options.dropped }),
1279
- (folders) => outputJson(folders),
1280
- "Failed to load folders"
1281
- );
1282
- });
1283
- command.command("view <idOrName>").description("View folder details and children").option("-d, --dropped", "Include dropped child folders").action(async (idOrName, options) => {
1284
- const filters = { includeDropped: options.dropped };
1285
- await executeOmniFocusCommand(
1286
- "Loading folder...",
1287
- (of) => of.getFolder(idOrName, filters),
1288
- (folder) => outputJson(folder),
1289
- "Failed to load folder"
1290
- );
1291
- });
1288
+ command.command("list").alias("ls").description("List top-level folders with nested children").option("-d, --dropped", "Include dropped folders").action(
1289
+ withErrorHandling(async (options) => {
1290
+ const of = new OmniFocus();
1291
+ const folders = await of.listFolders({ includeDropped: options.dropped });
1292
+ outputJson(folders);
1293
+ })
1294
+ );
1295
+ command.command("view <idOrName>").description("View folder details and children").option("-d, --dropped", "Include dropped child folders").action(
1296
+ withErrorHandling(async (idOrName, options) => {
1297
+ const of = new OmniFocus();
1298
+ const filters = { includeDropped: options.dropped };
1299
+ const folder = await of.getFolder(idOrName, filters);
1300
+ outputJson(folder);
1301
+ })
1302
+ );
1292
1303
  return command;
1293
1304
  }
1294
1305
 
1295
- // src/index.ts
1306
+ // src/cli.ts
1296
1307
  var program = new Command8();
1297
- program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.0.0").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
1308
+ program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.2.1").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
1298
1309
  const options = thisCommand.opts();
1299
1310
  setOutputOptions({
1300
1311
  compact: options.compact
@@ -1310,4 +1321,4 @@ program.addCommand(createFolderCommand());
1310
1321
  program.parseAsync().catch(() => {
1311
1322
  process.exit(1);
1312
1323
  });
1313
- //# sourceMappingURL=index.js.map
1324
+ //# sourceMappingURL=cli.js.map