// ── SDK v2 — BoardsClient ────────────────────────────────────────────────────── // // Covers: // GET /v2/boards // POST /v2/boards // GET /v2/boards/:id // PATCH /v2/boards/:id // DELETE /v2/boards/:id // GET /v2/boards/:id/tags // GET /v2/boards/:id/members // DELETE /v2/boards/:id/recycle-bin // GET /v2/boards/:id/external-channels // POST /v2/boards/:id/external-channels // GET /v2/boards/:id/external-channels/:cid // PATCH /v2/boards/:id/external-channels/:cid // DELETE /v2/boards/:id/external-channels/:cid import type { Fetcher } from "../http/fetcher"; import type { RequestOptions } from "../http/types"; import type { Board, BoardCreate, BoardUpdate, ExternalChannel, ExternalChannelCreate, ExternalChannelUpdate, ListParams, Paginated, } from "../types/index"; export class BoardsClient { constructor(private readonly fetcher: Fetcher) {} // ── Boards CRUD ─────────────────────────────────────────────────────────────── /** * Lists boards with cursor pagination and optional DSL filtering. * * @example * ```ts * const page = await client.boards.list({ q: "team_id.eq:'team-abc'" }); * for (const board of page.data) console.log(board.name); * ``` */ list(params?: ListParams, opts?: RequestOptions): Promise> { return this.fetcher.list("/boards", params, opts); } /** * Creates a new board. * * @example * ```ts * const board = await client.boards.create({ * team_id: "team-abc", * owner_id: "user-1", * created_by: "user-1", * name: "Sprint 1", * }); * ``` */ create(data: BoardCreate, opts?: RequestOptions): Promise { return this.fetcher.post("/boards", data, opts); } /** * Gets a single board by ID or URL-safe alias. * * @throws {NotFoundError} when no board with `id` exists. */ get(id: string, opts?: RequestOptions): Promise { return this.fetcher.get(`/boards/${id}`, undefined, opts); } /** * Partially updates a board. Only provided fields are changed. * * @throws {NotFoundError} when no board with `id` exists. */ update(id: string, data: BoardUpdate, opts?: RequestOptions): Promise { return this.fetcher.patch(`/boards/${id}`, data, opts); } /** * Deletes a board and all its associated data. * * @throws {NotFoundError} when no board with `id` exists. */ delete(id: string, opts?: RequestOptions): Promise { return this.fetcher.delete(`/boards/${id}`, opts); } // ── Board utilities ─────────────────────────────────────────────────────────── /** * Returns all tags aggregated from cards on this board. * * @example * ```ts * const { tags } = await client.boards.listTags(boardId); * ``` */ listTags( id: string, opts?: RequestOptions, ): Promise<{ board_id: string; tags: string[] }> { return this.fetcher.get(`/boards/${id}/tags`, undefined, opts); } /** * Returns the aggregated member and agent IDs across all cards on this board. * * @example * ```ts * const { member_ids, agent_ids } = await client.boards.listMembers(boardId); * ``` */ listMembers( id: string, opts?: RequestOptions, ): Promise<{ board_id: string; member_ids: string[]; agent_ids: string[] }> { return this.fetcher.get(`/boards/${id}/members`, undefined, opts); } /** * Hard-deletes all soft-deleted (recycled) cards on the board. * Returns the count of permanently deleted cards. * * @example * ```ts * const { deleted_count } = await client.boards.emptyRecycleBin(boardId); * ``` */ emptyRecycleBin( id: string, opts?: RequestOptions, ): Promise<{ deleted_count: number }> { return this.fetcher.delete<{ deleted_count: number }>( `/boards/${id}/recycle-bin`, opts, ); } // ── External Channels ───────────────────────────────────────────────────────── /** * Lists external channels linked to a board. * * @example * ```ts * const channels = await client.boards.listChannels(boardId); * ``` */ listChannels( boardId: string, params?: ListParams, opts?: RequestOptions, ): Promise> { return this.fetcher.list( `/boards/${boardId}/external-channels`, params, opts, ); } /** * Links an external channel (e.g. Slack) to a board. * * @throws {NotFoundError} when no board with `boardId` exists. */ createChannel( boardId: string, data: ExternalChannelCreate, opts?: RequestOptions, ): Promise { return this.fetcher.post( `/boards/${boardId}/external-channels`, data, opts, ); } /** * Gets a single external channel by ID. * * @throws {NotFoundError} when the channel doesn't exist. */ getChannel( boardId: string, channelId: string, opts?: RequestOptions, ): Promise { return this.fetcher.get( `/boards/${boardId}/external-channels/${channelId}`, undefined, opts, ); } /** * Updates an external channel. * * @throws {NotFoundError} when the channel doesn't exist. */ updateChannel( boardId: string, channelId: string, data: ExternalChannelUpdate, opts?: RequestOptions, ): Promise { return this.fetcher.patch( `/boards/${boardId}/external-channels/${channelId}`, data, opts, ); } /** * Removes an external channel from a board. * * @throws {NotFoundError} when the channel doesn't exist. */ deleteChannel( boardId: string, channelId: string, opts?: RequestOptions, ): Promise { return this.fetcher.delete( `/boards/${boardId}/external-channels/${channelId}`, opts, ); } }