@filcuk/planka-mcp 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/client.d.ts +55 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +193 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +39 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +82 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/operations/boards.d.ts +39 -0
- package/dist/operations/boards.d.ts.map +1 -0
- package/dist/operations/boards.js +76 -0
- package/dist/operations/boards.js.map +1 -0
- package/dist/operations/cards.d.ts +35 -0
- package/dist/operations/cards.d.ts.map +1 -0
- package/dist/operations/cards.js +70 -0
- package/dist/operations/cards.js.map +1 -0
- package/dist/operations/comments.d.ts +20 -0
- package/dist/operations/comments.d.ts.map +1 -0
- package/dist/operations/comments.js +42 -0
- package/dist/operations/comments.js.map +1 -0
- package/dist/operations/labels.d.ts +32 -0
- package/dist/operations/labels.d.ts.map +1 -0
- package/dist/operations/labels.js +91 -0
- package/dist/operations/labels.js.map +1 -0
- package/dist/operations/lists.d.ts +15 -0
- package/dist/operations/lists.d.ts.map +1 -0
- package/dist/operations/lists.js +35 -0
- package/dist/operations/lists.js.map +1 -0
- package/dist/operations/projects.d.ts +23 -0
- package/dist/operations/projects.d.ts.map +1 -0
- package/dist/operations/projects.js +52 -0
- package/dist/operations/projects.js.map +1 -0
- package/dist/operations/tasks.d.ts +30 -0
- package/dist/operations/tasks.d.ts.map +1 -0
- package/dist/operations/tasks.js +102 -0
- package/dist/operations/tasks.js.map +1 -0
- package/dist/schemas/entities.d.ts +307 -0
- package/dist/schemas/entities.d.ts.map +1 -0
- package/dist/schemas/entities.js +168 -0
- package/dist/schemas/entities.js.map +1 -0
- package/dist/schemas/requests.d.ts +225 -0
- package/dist/schemas/requests.d.ts.map +1 -0
- package/dist/schemas/requests.js +87 -0
- package/dist/schemas/requests.js.map +1 -0
- package/dist/schemas/responses.d.ts +2161 -0
- package/dist/schemas/responses.d.ts.map +1 -0
- package/dist/schemas/responses.js +68 -0
- package/dist/schemas/responses.js.map +1 -0
- package/dist/tools/cards.d.ts +401 -0
- package/dist/tools/cards.d.ts.map +1 -0
- package/dist/tools/cards.js +367 -0
- package/dist/tools/cards.js.map +1 -0
- package/dist/tools/comments.d.ts +134 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +109 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/index.d.ts +790 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +44 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/labels.d.ts +198 -0
- package/dist/tools/labels.d.ts.map +1 -0
- package/dist/tools/labels.js +265 -0
- package/dist/tools/labels.js.map +1 -0
- package/dist/tools/lists.d.ts +117 -0
- package/dist/tools/lists.d.ts.map +1 -0
- package/dist/tools/lists.js +178 -0
- package/dist/tools/lists.js.map +1 -0
- package/dist/tools/navigation.d.ts +106 -0
- package/dist/tools/navigation.d.ts.map +1 -0
- package/dist/tools/navigation.js +151 -0
- package/dist/tools/navigation.js.map +1 -0
- package/dist/tools/tasks.d.ts +223 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +169 -0
- package/dist/tools/tasks.js.map +1 -0
- package/package.json +53 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PLANKA MCP Server
|
|
4
|
+
*
|
|
5
|
+
* A Model Context Protocol server for PLANKA kanban boards.
|
|
6
|
+
* Provides tools for managing projects, boards, cards, tasks, labels, and comments.
|
|
7
|
+
*/
|
|
8
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
import { getToolDefinitions, getTool } from "./tools/index.js";
|
|
12
|
+
import { PlankaError, PlankaConfigError } from "./errors.js";
|
|
13
|
+
/**
|
|
14
|
+
* Main entry point.
|
|
15
|
+
*/
|
|
16
|
+
async function main() {
|
|
17
|
+
// Create the MCP server
|
|
18
|
+
const server = new Server({
|
|
19
|
+
name: "planka-mcp",
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
}, {
|
|
22
|
+
capabilities: {
|
|
23
|
+
tools: {},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
// Handler for listing available tools
|
|
27
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
28
|
+
return {
|
|
29
|
+
tools: getToolDefinitions(),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Handler for tool calls
|
|
33
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
34
|
+
const { name, arguments: args } = request.params;
|
|
35
|
+
const tool = getTool(name);
|
|
36
|
+
if (!tool) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: `Unknown tool: ${name}`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const result = await tool.handler(args || {});
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
// Handle configuration errors specifically
|
|
53
|
+
if (error instanceof PlankaConfigError) {
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Configuration error: ${error.message}\n\nRequired environment variables:\n- PLANKA_BASE_URL\n- PLANKA_AGENT_EMAIL\n- PLANKA_AGENT_PASSWORD`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
isError: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Handle other PLANKA errors
|
|
65
|
+
if (error instanceof PlankaError) {
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: "text",
|
|
70
|
+
text: `PLANKA error: ${error.message}`,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Log unexpected errors and return generic message
|
|
77
|
+
console.error(`Error in tool ${name}:`, error);
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: `Unexpected error: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
isError: true,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Connect to stdio transport
|
|
90
|
+
const transport = new StdioServerTransport();
|
|
91
|
+
await server.connect(transport);
|
|
92
|
+
// Log startup (to stderr so it doesn't interfere with MCP protocol)
|
|
93
|
+
console.error("PLANKA MCP server started");
|
|
94
|
+
}
|
|
95
|
+
// Run the server
|
|
96
|
+
main().catch((error) => {
|
|
97
|
+
console.error("Fatal error:", error);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Board, List, Card, Label, CardLabel, TaskList, Task } from "../schemas/entities.js";
|
|
2
|
+
/**
|
|
3
|
+
* Full board details with all included entities.
|
|
4
|
+
*/
|
|
5
|
+
export interface BoardDetails {
|
|
6
|
+
board: Board;
|
|
7
|
+
lists: List[];
|
|
8
|
+
cards: Card[];
|
|
9
|
+
labels: Label[];
|
|
10
|
+
cardLabels: CardLabel[];
|
|
11
|
+
taskLists: TaskList[];
|
|
12
|
+
tasks: Task[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Card with computed task counts.
|
|
16
|
+
*/
|
|
17
|
+
export interface CardWithTaskCounts extends Card {
|
|
18
|
+
taskCount: number;
|
|
19
|
+
completedTaskCount: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get a board by ID with all included entities.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getBoard(boardId: string): Promise<BoardDetails>;
|
|
25
|
+
/**
|
|
26
|
+
* Get a board with cards enriched with task counts.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getBoardWithTaskCounts(boardId: string): Promise<{
|
|
29
|
+
board: Board;
|
|
30
|
+
lists: List[];
|
|
31
|
+
cards: CardWithTaskCounts[];
|
|
32
|
+
labels: Label[];
|
|
33
|
+
cardLabels: CardLabel[];
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Get cards for a specific list on a board.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getCardsForList(boardId: string, listId: string): Promise<Card[]>;
|
|
39
|
+
//# sourceMappingURL=boards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boards.d.ts","sourceRoot":"","sources":["../../src/operations/boards.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,QAAQ,EACR,IAAI,EACL,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,IAAI;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkBrE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB,CAAC,CAgDD;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,EAAE,CAAC,CAKjB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board operations for PLANKA API.
|
|
3
|
+
*/
|
|
4
|
+
import { plankaClient } from "../client.js";
|
|
5
|
+
import { BoardResponse, BoardIncludedSchema } from "../schemas/responses.js";
|
|
6
|
+
/**
|
|
7
|
+
* Get a board by ID with all included entities.
|
|
8
|
+
*/
|
|
9
|
+
export async function getBoard(boardId) {
|
|
10
|
+
const response = await plankaClient.get(`/api/boards/${boardId}`);
|
|
11
|
+
const parsed = BoardResponse.parse(response);
|
|
12
|
+
const included = BoardIncludedSchema.parse(response.included || {});
|
|
13
|
+
return {
|
|
14
|
+
board: parsed.item,
|
|
15
|
+
lists: (included.lists || []).sort((a, b) => (a.position ?? Infinity) - (b.position ?? Infinity)),
|
|
16
|
+
cards: included.cards || [],
|
|
17
|
+
labels: (included.labels || []).sort((a, b) => a.position - b.position),
|
|
18
|
+
cardLabels: included.cardLabels || [],
|
|
19
|
+
taskLists: (included.taskLists || []).sort((a, b) => a.position - b.position),
|
|
20
|
+
tasks: included.tasks || [],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get a board with cards enriched with task counts.
|
|
25
|
+
*/
|
|
26
|
+
export async function getBoardWithTaskCounts(boardId) {
|
|
27
|
+
const details = await getBoard(boardId);
|
|
28
|
+
// Build taskList -> cardId mapping (PLANKA 2.0: tasks belong to taskLists, not cards directly)
|
|
29
|
+
const taskListToCard = new Map();
|
|
30
|
+
for (const taskList of details.taskLists) {
|
|
31
|
+
taskListToCard.set(taskList.id, taskList.cardId);
|
|
32
|
+
}
|
|
33
|
+
// Build task count map by card
|
|
34
|
+
const taskCountsByCard = new Map();
|
|
35
|
+
for (const task of details.tasks) {
|
|
36
|
+
// Get cardId via the taskList
|
|
37
|
+
const cardId = taskListToCard.get(task.taskListId);
|
|
38
|
+
if (!cardId)
|
|
39
|
+
continue;
|
|
40
|
+
const counts = taskCountsByCard.get(cardId) || {
|
|
41
|
+
total: 0,
|
|
42
|
+
completed: 0,
|
|
43
|
+
};
|
|
44
|
+
counts.total++;
|
|
45
|
+
if (task.isCompleted) {
|
|
46
|
+
counts.completed++;
|
|
47
|
+
}
|
|
48
|
+
taskCountsByCard.set(cardId, counts);
|
|
49
|
+
}
|
|
50
|
+
// Enrich cards with task counts
|
|
51
|
+
const cardsWithCounts = details.cards.map((card) => {
|
|
52
|
+
const counts = taskCountsByCard.get(card.id) || { total: 0, completed: 0 };
|
|
53
|
+
return {
|
|
54
|
+
...card,
|
|
55
|
+
taskCount: counts.total,
|
|
56
|
+
completedTaskCount: counts.completed,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
board: details.board,
|
|
61
|
+
lists: details.lists,
|
|
62
|
+
cards: cardsWithCounts,
|
|
63
|
+
labels: details.labels,
|
|
64
|
+
cardLabels: details.cardLabels,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get cards for a specific list on a board.
|
|
69
|
+
*/
|
|
70
|
+
export async function getCardsForList(boardId, listId) {
|
|
71
|
+
const details = await getBoard(boardId);
|
|
72
|
+
return details.cards
|
|
73
|
+
.filter((card) => card.listId === listId)
|
|
74
|
+
.sort((a, b) => a.position - b.position);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=boards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boards.js","sourceRoot":"","sources":["../../src/operations/boards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Card, TaskList, Task, Comment, Label, CardLabel, Attachment } from "../schemas/entities.js";
|
|
2
|
+
import { CreateCardInput, UpdateCardInput, MoveCardInput } from "../schemas/requests.js";
|
|
3
|
+
/**
|
|
4
|
+
* Card details with all related entities.
|
|
5
|
+
*/
|
|
6
|
+
export interface CardDetails {
|
|
7
|
+
card: Card;
|
|
8
|
+
taskLists: TaskList[];
|
|
9
|
+
tasks: Task[];
|
|
10
|
+
comments: Comment[];
|
|
11
|
+
labels: Label[];
|
|
12
|
+
cardLabels: CardLabel[];
|
|
13
|
+
attachments: Attachment[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a new card in a list.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createCard(input: CreateCardInput): Promise<Card>;
|
|
19
|
+
/**
|
|
20
|
+
* Get a card by ID with all related entities.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getCard(cardId: string): Promise<CardDetails>;
|
|
23
|
+
/**
|
|
24
|
+
* Update a card's properties.
|
|
25
|
+
*/
|
|
26
|
+
export declare function updateCard(cardId: string, input: UpdateCardInput): Promise<Card>;
|
|
27
|
+
/**
|
|
28
|
+
* Move a card to a different list/position.
|
|
29
|
+
*/
|
|
30
|
+
export declare function moveCard(input: MoveCardInput): Promise<Card>;
|
|
31
|
+
/**
|
|
32
|
+
* Delete a card.
|
|
33
|
+
*/
|
|
34
|
+
export declare function deleteCard(cardId: string): Promise<void>;
|
|
35
|
+
//# sourceMappingURL=cards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../../src/operations/cards.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAIL,eAAe,EACf,eAAe,EACf,aAAa,EACd,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBtE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBlE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBlE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card operations for PLANKA API.
|
|
3
|
+
*/
|
|
4
|
+
import { plankaClient } from "../client.js";
|
|
5
|
+
import { CreateCardSchema, UpdateCardSchema, MoveCardSchema, } from "../schemas/requests.js";
|
|
6
|
+
import { CardResponse, CardIncludedSchema } from "../schemas/responses.js";
|
|
7
|
+
/**
|
|
8
|
+
* Create a new card in a list.
|
|
9
|
+
*/
|
|
10
|
+
export async function createCard(input) {
|
|
11
|
+
const validated = CreateCardSchema.parse(input);
|
|
12
|
+
const response = await plankaClient.post(`/api/lists/${validated.listId}/cards`, {
|
|
13
|
+
name: validated.name,
|
|
14
|
+
description: validated.description,
|
|
15
|
+
position: validated.position,
|
|
16
|
+
type: validated.type, // Required for PLANKA 2.0
|
|
17
|
+
dueDate: validated.dueDate,
|
|
18
|
+
});
|
|
19
|
+
const parsed = CardResponse.parse(response);
|
|
20
|
+
return parsed.item;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get a card by ID with all related entities.
|
|
24
|
+
*/
|
|
25
|
+
export async function getCard(cardId) {
|
|
26
|
+
const response = await plankaClient.get(`/api/cards/${cardId}`);
|
|
27
|
+
const parsed = CardResponse.parse(response);
|
|
28
|
+
const included = CardIncludedSchema.parse(response.included || {});
|
|
29
|
+
return {
|
|
30
|
+
card: parsed.item,
|
|
31
|
+
taskLists: (included.taskLists || []).sort((a, b) => a.position - b.position),
|
|
32
|
+
tasks: (included.tasks || []).sort((a, b) => a.position - b.position),
|
|
33
|
+
comments: (included.comments || []).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()),
|
|
34
|
+
labels: included.labels || [],
|
|
35
|
+
cardLabels: included.cardLabels || [],
|
|
36
|
+
attachments: included.attachments || [],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Update a card's properties.
|
|
41
|
+
*/
|
|
42
|
+
export async function updateCard(cardId, input) {
|
|
43
|
+
const validated = UpdateCardSchema.parse(input);
|
|
44
|
+
const response = await plankaClient.patch(`/api/cards/${cardId}`, validated);
|
|
45
|
+
const parsed = CardResponse.parse(response);
|
|
46
|
+
return parsed.item;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Move a card to a different list/position.
|
|
50
|
+
*/
|
|
51
|
+
export async function moveCard(input) {
|
|
52
|
+
const validated = MoveCardSchema.parse(input);
|
|
53
|
+
const updatePayload = {
|
|
54
|
+
listId: validated.listId,
|
|
55
|
+
position: validated.position,
|
|
56
|
+
};
|
|
57
|
+
if (validated.boardId) {
|
|
58
|
+
updatePayload.boardId = validated.boardId;
|
|
59
|
+
}
|
|
60
|
+
const response = await plankaClient.patch(`/api/cards/${validated.cardId}`, updatePayload);
|
|
61
|
+
const parsed = CardResponse.parse(response);
|
|
62
|
+
return parsed.item;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Delete a card.
|
|
66
|
+
*/
|
|
67
|
+
export async function deleteCard(cardId) {
|
|
68
|
+
await plankaClient.delete(`/api/cards/${cardId}`);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cards.js","sourceRoot":"","sources":["../../src/operations/cards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Comment } from "../schemas/entities.js";
|
|
2
|
+
import { CreateCommentInput, UpdateCommentInput } from "../schemas/requests.js";
|
|
3
|
+
/**
|
|
4
|
+
* Add a comment to a card.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createComment(input: CreateCommentInput): Promise<Comment>;
|
|
7
|
+
/**
|
|
8
|
+
* Update a comment's text.
|
|
9
|
+
*/
|
|
10
|
+
export declare function updateComment(commentId: string, input: UpdateCommentInput): Promise<Comment>;
|
|
11
|
+
/**
|
|
12
|
+
* Delete a comment.
|
|
13
|
+
*/
|
|
14
|
+
export declare function deleteComment(commentId: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Get all comments for a card.
|
|
17
|
+
* Comments are included when fetching card details.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCommentsForCard(cardId: string): Promise<Comment[]>;
|
|
20
|
+
//# sourceMappingURL=comments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/operations/comments.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAGL,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAIhC;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAY/E;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAG3E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comment operations for PLANKA API.
|
|
3
|
+
*/
|
|
4
|
+
import { plankaClient } from "../client.js";
|
|
5
|
+
import { CreateCommentSchema, UpdateCommentSchema, } from "../schemas/requests.js";
|
|
6
|
+
import { CommentResponse } from "../schemas/responses.js";
|
|
7
|
+
import { getCard } from "./cards.js";
|
|
8
|
+
/**
|
|
9
|
+
* Add a comment to a card.
|
|
10
|
+
*/
|
|
11
|
+
export async function createComment(input) {
|
|
12
|
+
const validated = CreateCommentSchema.parse(input);
|
|
13
|
+
const response = await plankaClient.post(`/api/cards/${validated.cardId}/comments`, {
|
|
14
|
+
text: validated.text,
|
|
15
|
+
});
|
|
16
|
+
const parsed = CommentResponse.parse(response);
|
|
17
|
+
return parsed.item;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Update a comment's text.
|
|
21
|
+
*/
|
|
22
|
+
export async function updateComment(commentId, input) {
|
|
23
|
+
const validated = UpdateCommentSchema.parse(input);
|
|
24
|
+
const response = await plankaClient.patch(`/api/comments/${commentId}`, validated);
|
|
25
|
+
const parsed = CommentResponse.parse(response);
|
|
26
|
+
return parsed.item;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Delete a comment.
|
|
30
|
+
*/
|
|
31
|
+
export async function deleteComment(commentId) {
|
|
32
|
+
await plankaClient.delete(`/api/comments/${commentId}`);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get all comments for a card.
|
|
36
|
+
* Comments are included when fetching card details.
|
|
37
|
+
*/
|
|
38
|
+
export async function getCommentsForCard(cardId) {
|
|
39
|
+
const cardDetails = await getCard(cardId);
|
|
40
|
+
return cardDetails.comments;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/operations/comments.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GAGpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAyB;IAC3D,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CACtC,cAAc,SAAS,CAAC,MAAM,WAAW,EACzC;QACE,IAAI,EAAE,SAAS,CAAC,IAAI;KACrB,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB,EACjB,KAAyB;IAEzB,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CACvC,iBAAiB,SAAS,EAAE,EAC5B,SAAS,CACV,CAAC;IAEF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,MAAM,YAAY,CAAC,MAAM,CAAC,iBAAiB,SAAS,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAc;IACrD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,WAAW,CAAC,QAAQ,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Label, CardLabel } from "../schemas/entities.js";
|
|
2
|
+
import { CreateLabelInput, UpdateLabelInput, AddLabelToCardInput } from "../schemas/requests.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a new label on a board.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createLabel(input: CreateLabelInput): Promise<Label>;
|
|
7
|
+
/**
|
|
8
|
+
* Update a label's properties.
|
|
9
|
+
*/
|
|
10
|
+
export declare function updateLabel(labelId: string, input: UpdateLabelInput): Promise<Label>;
|
|
11
|
+
/**
|
|
12
|
+
* Delete a label.
|
|
13
|
+
*/
|
|
14
|
+
export declare function deleteLabel(labelId: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Add a label to a card.
|
|
17
|
+
* Uses PLANKA 2.0 /card-labels endpoint.
|
|
18
|
+
*/
|
|
19
|
+
export declare function addLabelToCard(input: AddLabelToCardInput): Promise<CardLabel>;
|
|
20
|
+
/**
|
|
21
|
+
* Remove a label from a card.
|
|
22
|
+
* Uses PLANKA 2.0 /card-labels endpoint.
|
|
23
|
+
*
|
|
24
|
+
* Note: We need the cardLabelId (the junction record ID), not the labelId.
|
|
25
|
+
* This function finds the correct cardLabelId from the card's existing labels.
|
|
26
|
+
*/
|
|
27
|
+
export declare function removeLabelFromCard(cardId: string, labelId: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Set labels on a card (add some, remove others).
|
|
30
|
+
*/
|
|
31
|
+
export declare function setCardLabels(cardId: string, addLabelIds?: string[], removeLabelIds?: string[]): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../src/operations/labels.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAIhC;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,CAczE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,KAAK,CAAC,CAUhB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC,CAYnF;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CAsBf"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Label operations for PLANKA API.
|
|
3
|
+
*/
|
|
4
|
+
import { plankaClient } from "../client.js";
|
|
5
|
+
import { CreateLabelSchema, UpdateLabelSchema, AddLabelToCardSchema, } from "../schemas/requests.js";
|
|
6
|
+
import { LabelResponse, CardLabelResponse } from "../schemas/responses.js";
|
|
7
|
+
import { getCard } from "./cards.js";
|
|
8
|
+
/**
|
|
9
|
+
* Create a new label on a board.
|
|
10
|
+
*/
|
|
11
|
+
export async function createLabel(input) {
|
|
12
|
+
const validated = CreateLabelSchema.parse(input);
|
|
13
|
+
const response = await plankaClient.post(`/api/boards/${validated.boardId}/labels`, {
|
|
14
|
+
name: validated.name,
|
|
15
|
+
color: validated.color,
|
|
16
|
+
position: validated.position,
|
|
17
|
+
});
|
|
18
|
+
const parsed = LabelResponse.parse(response);
|
|
19
|
+
return parsed.item;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Update a label's properties.
|
|
23
|
+
*/
|
|
24
|
+
export async function updateLabel(labelId, input) {
|
|
25
|
+
const validated = UpdateLabelSchema.parse(input);
|
|
26
|
+
const response = await plankaClient.patch(`/api/labels/${labelId}`, validated);
|
|
27
|
+
const parsed = LabelResponse.parse(response);
|
|
28
|
+
return parsed.item;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Delete a label.
|
|
32
|
+
*/
|
|
33
|
+
export async function deleteLabel(labelId) {
|
|
34
|
+
await plankaClient.delete(`/api/labels/${labelId}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Add a label to a card.
|
|
38
|
+
* Uses PLANKA 2.0 /card-labels endpoint.
|
|
39
|
+
*/
|
|
40
|
+
export async function addLabelToCard(input) {
|
|
41
|
+
const validated = AddLabelToCardSchema.parse(input);
|
|
42
|
+
const response = await plankaClient.post(`/api/cards/${validated.cardId}/card-labels`, {
|
|
43
|
+
labelId: validated.labelId,
|
|
44
|
+
});
|
|
45
|
+
const parsed = CardLabelResponse.parse(response);
|
|
46
|
+
return parsed.item;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Remove a label from a card.
|
|
50
|
+
* Uses PLANKA 2.0 /card-labels endpoint.
|
|
51
|
+
*
|
|
52
|
+
* Note: We need the cardLabelId (the junction record ID), not the labelId.
|
|
53
|
+
* This function finds the correct cardLabelId from the card's existing labels.
|
|
54
|
+
*/
|
|
55
|
+
export async function removeLabelFromCard(cardId, labelId) {
|
|
56
|
+
// Get the card to find the cardLabel record
|
|
57
|
+
const cardDetails = await getCard(cardId);
|
|
58
|
+
const cardLabel = cardDetails.cardLabels.find((cl) => cl.labelId === labelId);
|
|
59
|
+
if (!cardLabel) {
|
|
60
|
+
// Label not on card, nothing to remove
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await plankaClient.delete(`/api/cards/${cardId}/card-labels/${cardLabel.id}`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Set labels on a card (add some, remove others).
|
|
67
|
+
*/
|
|
68
|
+
export async function setCardLabels(cardId, addLabelIds, removeLabelIds) {
|
|
69
|
+
// Remove labels first
|
|
70
|
+
if (removeLabelIds && removeLabelIds.length > 0) {
|
|
71
|
+
for (const labelId of removeLabelIds) {
|
|
72
|
+
await removeLabelFromCard(cardId, labelId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Add labels
|
|
76
|
+
if (addLabelIds && addLabelIds.length > 0) {
|
|
77
|
+
for (const labelId of addLabelIds) {
|
|
78
|
+
try {
|
|
79
|
+
await addLabelToCard({ cardId, labelId });
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// Ignore if label already on card
|
|
83
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
84
|
+
if (!message.includes("already")) {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../../src/operations/labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { List } from "../schemas/entities.js";
|
|
2
|
+
import { CreateListInput, UpdateListInput } from "../schemas/requests.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a new list on a board.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createList(input: CreateListInput): Promise<List>;
|
|
7
|
+
/**
|
|
8
|
+
* Update a list's properties.
|
|
9
|
+
*/
|
|
10
|
+
export declare function updateList(listId: string, input: UpdateListInput): Promise<List>;
|
|
11
|
+
/**
|
|
12
|
+
* Delete a list.
|
|
13
|
+
*/
|
|
14
|
+
export declare function deleteList(listId: string): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=lists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lists.d.ts","sourceRoot":"","sources":["../../src/operations/lists.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,EAGL,eAAe,EACf,eAAe,EAChB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CActE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List operations for PLANKA API.
|
|
3
|
+
*/
|
|
4
|
+
import { plankaClient } from "../client.js";
|
|
5
|
+
import { ListResponse } from "../schemas/responses.js";
|
|
6
|
+
import { CreateListSchema, UpdateListSchema, } from "../schemas/requests.js";
|
|
7
|
+
/**
|
|
8
|
+
* Create a new list on a board.
|
|
9
|
+
*/
|
|
10
|
+
export async function createList(input) {
|
|
11
|
+
const validated = CreateListSchema.parse(input);
|
|
12
|
+
const response = await plankaClient.post(`/api/boards/${validated.boardId}/lists`, {
|
|
13
|
+
name: validated.name,
|
|
14
|
+
type: validated.type, // Required for PLANKA 2.0
|
|
15
|
+
position: validated.position,
|
|
16
|
+
});
|
|
17
|
+
const parsed = ListResponse.parse(response);
|
|
18
|
+
return parsed.item;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Update a list's properties.
|
|
22
|
+
*/
|
|
23
|
+
export async function updateList(listId, input) {
|
|
24
|
+
const validated = UpdateListSchema.parse(input);
|
|
25
|
+
const response = await plankaClient.patch(`/api/lists/${listId}`, validated);
|
|
26
|
+
const parsed = ListResponse.parse(response);
|
|
27
|
+
return parsed.item;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Delete a list.
|
|
31
|
+
*/
|
|
32
|
+
export async function deleteList(listId) {
|
|
33
|
+
await plankaClient.delete(`/api/lists/${listId}`);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=lists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lists.js","sourceRoot":"","sources":["../../src/operations/lists.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,GAGjB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CACtC,eAAe,SAAS,CAAC,OAAO,QAAQ,EACxC;QACE,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,0BAA0B;QAChD,QAAQ,EAAE,SAAS,CAAC,QAAQ;KAC7B,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,KAAsB;IAEtB,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CACvC,cAAc,MAAM,EAAE,EACtB,SAAS,CACV,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,YAAY,CAAC,MAAM,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Project, Board, List } from "../schemas/entities.js";
|
|
2
|
+
/**
|
|
3
|
+
* Full project structure with boards and lists.
|
|
4
|
+
*/
|
|
5
|
+
export interface ProjectStructure {
|
|
6
|
+
project: Project;
|
|
7
|
+
boards: Array<{
|
|
8
|
+
board: Board;
|
|
9
|
+
lists: List[];
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get all projects with their boards.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getProjects(): Promise<{
|
|
16
|
+
projects: Project[];
|
|
17
|
+
boards: Board[];
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the full structure: projects -> boards -> lists.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getStructure(projectId?: string): Promise<ProjectStructure[]>;
|
|
23
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/operations/projects.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AAI1E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,IAAI,EAAE,CAAC;KACf,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC;IAC3C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC,CAWD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyClF"}
|