Skip to content

Comments

Reduce duplication in Tasks API layer#805

Open
EhabY wants to merge 2 commits intorefactor-tasks-webviewfrom
reduce-duplication-tasks-api
Open

Reduce duplication in Tasks API layer#805
EhabY wants to merge 2 commits intorefactor-tasks-webviewfrom
reduce-duplication-tasks-api

Conversation

@EhabY
Copy link
Collaborator

@EhabY EhabY commented Feb 20, 2026

Summary

  • Replace per-definition requestHandler/commandHandler wrappers with buildRequestHandlers and buildCommandHandlers mapped-type builders that enforce compile-time completeness over the full API surface
  • Add buildApiHook and ApiHook<Api> so that useTasksApi is auto-generated from the TasksApi definition object at runtime, eliminating ~60 lines of manual method listings that had to stay in sync
  • Add kind discriminant to RequestDef, CommandDef, and NotificationDef so builders can dispatch by kind at runtime
  • Inline intermediate const declarations in api.ts directly into the TasksApi object and remove unused ParamsOf/ResponseOf utility types
  • Replace raw sendNotification calls in tasksPanelProvider with a typed notify helper

Replace per-definition requestHandler/commandHandler wrappers with
buildRequestHandlers and buildCommandHandlers that enforce compile-time
completeness over the full API surface.

- Add kind discriminant to RequestDef, CommandDef, and NotificationDef
  interfaces and their factory functions
- Add RequestHandlerMap and CommandHandlerMap mapped types that require
  a handler for every definition of the corresponding kind
- Add buildRequestHandlers and buildCommandHandlers builder functions
  with typed overloads for compile-time completeness checking
- Replace manual method-keyed handler maps in tasksPanelProvider with
  builder calls using property-name keys
- Replace raw sendNotification calls with a typed notify helper
Add buildApiHook and ApiHook<Api> to protocol.ts so that useTasksApi
can be derived from the TasksApi definition object with zero manual sync.

- Add ApiHook<Api> mapped type that derives request, command, and
  notification subscription signatures from an API definition
- Add buildApiHook() that iterates API entries by kind at runtime,
  dispatching to ipc.request/command/onNotification
- Replace ~60 lines of manual method listings in useTasksApi with a
  single buildApiHook(TasksApi, useIpc()) call
- Update 5 consumer call sites from positional args to params objects
- Inline intermediate const declarations in api.ts into TasksApi object
- Remove unused ParamsOf and ResponseOf utility types
@EhabY EhabY self-assigned this Feb 20, 2026
@EhabY EhabY changed the base branch from main to refactor-tasks-webview February 20, 2026 01:04
@mafredri mafredri self-requested a review February 20, 2026 07:51
type: TasksApi.tasksUpdated.method,
data: tasks,
});
this.notify(TasksApi.tasksUpdated, [...tasks]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we're performing [...tasks] here?

If it is because tasks is readonly Task[] and tasksUpdated only accepts Task[], could we investigate having tasksUpdated accept readonly Task[]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it isn't necessary?

) => () => void;
},
): ApiHook<Api>;
export function buildApiHook(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking: thoughts on a unit test for this function? If it is sufficiently tested indirectly then no worries.

export function buildApiHook(
api: Record<string, { kind: string; method: string }>,
ipc: {
request: (def: { method: string }, params: unknown) => Promise<unknown>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be params?

readonly kind: "request";
readonly method: string;
/** @internal Phantom types for inference - not present at runtime */
readonly _types?: { params: P; response: R };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with never?

readonly _types?: never & { params: P; response: R };

type: TasksApi.tasksUpdated.method,
data: tasks,
});
this.notify(TasksApi.tasksUpdated, [...tasks]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it isn't necessary?

private readonly requestHandlers = buildRequestHandlers(TasksApi, {
getTasks: () => this.fetchTasks(),
getTemplates: () => this.fetchTemplates(),
getTask: (p) => this.client.getTask("me", p.taskId),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a risk that client will not be initialized at the moment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants