From 6e72d0328b82304c0254063a80f430b17a053506 Mon Sep 17 00:00:00 2001
From: Jamie Brynes <jamiebrynes7@gmail.com>
Date: Tue, 26 Mar 2024 15:58:28 +0000
Subject: [PATCH] refactor: strongly type manually dispatched commands

---
 plugin/src/commands/addTask.ts    |  9 +++------
 plugin/src/commands/index.ts      | 32 +++++++++++++++----------------
 plugin/src/ui/TodoistQuery.svelte |  2 +-
 3 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/plugin/src/commands/addTask.ts b/plugin/src/commands/addTask.ts
index 1f56cae..a55e530 100644
--- a/plugin/src/commands/addTask.ts
+++ b/plugin/src/commands/addTask.ts
@@ -3,15 +3,14 @@ import type { MakeCommand } from ".";
 import type TodoistPlugin from "..";
 import type { TaskCreationOptions } from "../ui/createTaskModal";
 
-const addTask: MakeCommand = (plugin: TodoistPlugin) => {
+export const addTask: MakeCommand = (plugin: TodoistPlugin) => {
   return {
-    id: "add-task",
     name: "Add task",
     callback: makeCallback(plugin),
   };
 };
 
-const addTaskWithPageInContent: MakeCommand = (plugin: TodoistPlugin) => {
+export const addTaskWithPageInContent: MakeCommand = (plugin: TodoistPlugin) => {
   return {
     id: "add-task-page-content",
     name: "Add task with current page in task content",
@@ -19,7 +18,7 @@ const addTaskWithPageInContent: MakeCommand = (plugin: TodoistPlugin) => {
   };
 };
 
-const addTaskWithPageInDescription: MakeCommand = (plugin: TodoistPlugin) => {
+export const addTaskWithPageInDescription: MakeCommand = (plugin: TodoistPlugin) => {
   return {
     id: "add-task-page-description",
     name: "Add task with current page in task description",
@@ -59,5 +58,3 @@ const grabSelection = (plugin: TodoistPlugin): string => {
 const getFileContext = (plugin: TodoistPlugin): TFile | undefined => {
   return plugin.app.workspace.getActiveFile() ?? undefined;
 };
-
-export default [addTask, addTaskWithPageInContent, addTaskWithPageInDescription];
diff --git a/plugin/src/commands/index.ts b/plugin/src/commands/index.ts
index accdaf3..98d2559 100644
--- a/plugin/src/commands/index.ts
+++ b/plugin/src/commands/index.ts
@@ -1,13 +1,12 @@
 import { type Command as ObsidianCommand } from "obsidian";
 import type TodoistPlugin from "..";
 import debug from "../log";
-import addTaskCommands from "./addTask";
+import { addTask, addTaskWithPageInContent, addTaskWithPageInDescription } from "./addTask";
 
-export type MakeCommand = (plugin: TodoistPlugin) => ObsidianCommand;
+export type MakeCommand = (plugin: TodoistPlugin) => Omit<ObsidianCommand, "id">;
 
 const syncCommand: MakeCommand = (plugin: TodoistPlugin) => {
   return {
-    id: "todoist-sync",
     name: "Sync with Todoist",
     callback: async () => {
       debug("Syncing with Todoist API");
@@ -16,23 +15,22 @@ const syncCommand: MakeCommand = (plugin: TodoistPlugin) => {
   };
 };
 
-const commands: MakeCommand[] = [syncCommand, ...addTaskCommands];
+const commands = {
+  "todoist-sync": syncCommand,
+  "add-task": addTask,
+  "add-task-page-content": addTaskWithPageInContent,
+  "add-task-page-description": addTaskWithPageInDescription,
+};
+
+type CommandId = keyof typeof commands;
 
 export const registerCommands = (plugin: TodoistPlugin) => {
-  for (const make of commands) {
-    plugin.addCommand(make(plugin));
+  for (const [id, make] of Object.entries(commands)) {
+    plugin.addCommand({ id, ...make(plugin) });
   }
 };
 
-// TODO: Strongly type the IDs
-export const fireCommand = (plugin: TodoistPlugin, id: string) => {
-  for (const make of commands) {
-    const cmd = make(plugin);
-    if (cmd.id === id) {
-      cmd.callback?.();
-      return;
-    }
-  }
-
-  throw Error(`Failed to find command by ID: ${id}`);
+export const fireCommand = <K extends CommandId>(id: K, plugin: TodoistPlugin) => {
+  const make = commands[id];
+  make(plugin).callback?.();
 };
diff --git a/plugin/src/ui/TodoistQuery.svelte b/plugin/src/ui/TodoistQuery.svelte
index 92be030..d1493d7 100644
--- a/plugin/src/ui/TodoistQuery.svelte
+++ b/plugin/src/ui/TodoistQuery.svelte
@@ -106,7 +106,7 @@
   });
 
   function callTaskModal() {
-    fireCommand(plugin, "add-task-page-content");
+    fireCommand("add-task-page-content", plugin);
   }
 
   async function forceRefresh() {