feat: add Linear issue watchers (#805)

This commit is contained in:
João Salavisa
2026-05-05 08:28:09 +01:00
committed by GitHub
parent ec1e4a8d61
commit 83de4793fd
36 changed files with 3473 additions and 29 deletions
+65
View File
@@ -1,13 +1,16 @@
import { fetchJson, type ApiRequestOptions } from "../client";
import type {
CreateLinearIssueWatchInput,
LinearConfig,
LinearIssue,
LinearIssueWatch,
LinearSearchFilter,
LinearSearchResult,
LinearTeam,
LinearWorkflowState,
SetLinearConfigRequest,
TestLinearConnectionResult,
UpdateLinearIssueWatchInput,
} from "@/lib/types/linear";
// getLinearConfig returns null when the backend responds 204 (no config yet).
@@ -90,3 +93,65 @@ export async function setLinearIssueState(
},
);
}
// --- Issue watches ---
// listLinearIssueWatches fetches watches across all workspaces when
// workspaceId is omitted, or scoped to one workspace when provided.
export async function listLinearIssueWatches(workspaceId?: string, options?: ApiRequestOptions) {
const path = workspaceId
? `/api/v1/linear/watches/issue?workspace_id=${encodeURIComponent(workspaceId)}`
: `/api/v1/linear/watches/issue`;
const res = await fetchJson<{ watches: LinearIssueWatch[] }>(path, options);
return res.watches ?? [];
}
export async function createLinearIssueWatch(
payload: CreateLinearIssueWatchInput,
options?: ApiRequestOptions,
) {
return fetchJson<LinearIssueWatch>(`/api/v1/linear/watches/issue`, {
...options,
init: { ...(options?.init ?? {}), method: "POST", body: JSON.stringify(payload) },
});
}
// All mutation/trigger endpoints require `workspace_id` so the backend can
// reject cross-workspace IDOR.
export async function updateLinearIssueWatch(
workspaceId: string,
id: string,
payload: UpdateLinearIssueWatchInput,
options?: ApiRequestOptions,
) {
return fetchJson<LinearIssueWatch>(
`/api/v1/linear/watches/issue/${encodeURIComponent(id)}?workspace_id=${encodeURIComponent(workspaceId)}`,
{
...options,
init: { ...(options?.init ?? {}), method: "PATCH", body: JSON.stringify(payload) },
},
);
}
export async function deleteLinearIssueWatch(
workspaceId: string,
id: string,
options?: ApiRequestOptions,
) {
return fetchJson<{ deleted: boolean }>(
`/api/v1/linear/watches/issue/${encodeURIComponent(id)}?workspace_id=${encodeURIComponent(workspaceId)}`,
{ ...options, init: { ...(options?.init ?? {}), method: "DELETE" } },
);
}
export async function triggerLinearIssueWatch(
workspaceId: string,
id: string,
options?: ApiRequestOptions,
) {
return fetchJson<{ newIssues: number }>(
`/api/v1/linear/watches/issue/${encodeURIComponent(id)}/trigger?workspace_id=${encodeURIComponent(workspaceId)}`,
{ ...options, init: { ...(options?.init ?? {}), method: "POST" } },
);
}