@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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +180 -0
  3. package/dist/client.d.ts +55 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +193 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/errors.d.ts +39 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +82 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +100 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/operations/boards.d.ts +39 -0
  16. package/dist/operations/boards.d.ts.map +1 -0
  17. package/dist/operations/boards.js +76 -0
  18. package/dist/operations/boards.js.map +1 -0
  19. package/dist/operations/cards.d.ts +35 -0
  20. package/dist/operations/cards.d.ts.map +1 -0
  21. package/dist/operations/cards.js +70 -0
  22. package/dist/operations/cards.js.map +1 -0
  23. package/dist/operations/comments.d.ts +20 -0
  24. package/dist/operations/comments.d.ts.map +1 -0
  25. package/dist/operations/comments.js +42 -0
  26. package/dist/operations/comments.js.map +1 -0
  27. package/dist/operations/labels.d.ts +32 -0
  28. package/dist/operations/labels.d.ts.map +1 -0
  29. package/dist/operations/labels.js +91 -0
  30. package/dist/operations/labels.js.map +1 -0
  31. package/dist/operations/lists.d.ts +15 -0
  32. package/dist/operations/lists.d.ts.map +1 -0
  33. package/dist/operations/lists.js +35 -0
  34. package/dist/operations/lists.js.map +1 -0
  35. package/dist/operations/projects.d.ts +23 -0
  36. package/dist/operations/projects.d.ts.map +1 -0
  37. package/dist/operations/projects.js +52 -0
  38. package/dist/operations/projects.js.map +1 -0
  39. package/dist/operations/tasks.d.ts +30 -0
  40. package/dist/operations/tasks.d.ts.map +1 -0
  41. package/dist/operations/tasks.js +102 -0
  42. package/dist/operations/tasks.js.map +1 -0
  43. package/dist/schemas/entities.d.ts +307 -0
  44. package/dist/schemas/entities.d.ts.map +1 -0
  45. package/dist/schemas/entities.js +168 -0
  46. package/dist/schemas/entities.js.map +1 -0
  47. package/dist/schemas/requests.d.ts +225 -0
  48. package/dist/schemas/requests.d.ts.map +1 -0
  49. package/dist/schemas/requests.js +87 -0
  50. package/dist/schemas/requests.js.map +1 -0
  51. package/dist/schemas/responses.d.ts +2161 -0
  52. package/dist/schemas/responses.d.ts.map +1 -0
  53. package/dist/schemas/responses.js +68 -0
  54. package/dist/schemas/responses.js.map +1 -0
  55. package/dist/tools/cards.d.ts +401 -0
  56. package/dist/tools/cards.d.ts.map +1 -0
  57. package/dist/tools/cards.js +367 -0
  58. package/dist/tools/cards.js.map +1 -0
  59. package/dist/tools/comments.d.ts +134 -0
  60. package/dist/tools/comments.d.ts.map +1 -0
  61. package/dist/tools/comments.js +109 -0
  62. package/dist/tools/comments.js.map +1 -0
  63. package/dist/tools/index.d.ts +790 -0
  64. package/dist/tools/index.d.ts.map +1 -0
  65. package/dist/tools/index.js +44 -0
  66. package/dist/tools/index.js.map +1 -0
  67. package/dist/tools/labels.d.ts +198 -0
  68. package/dist/tools/labels.d.ts.map +1 -0
  69. package/dist/tools/labels.js +265 -0
  70. package/dist/tools/labels.js.map +1 -0
  71. package/dist/tools/lists.d.ts +117 -0
  72. package/dist/tools/lists.d.ts.map +1 -0
  73. package/dist/tools/lists.js +178 -0
  74. package/dist/tools/lists.js.map +1 -0
  75. package/dist/tools/navigation.d.ts +106 -0
  76. package/dist/tools/navigation.d.ts.map +1 -0
  77. package/dist/tools/navigation.js +151 -0
  78. package/dist/tools/navigation.js.map +1 -0
  79. package/dist/tools/tasks.d.ts +223 -0
  80. package/dist/tools/tasks.d.ts.map +1 -0
  81. package/dist/tools/tasks.js +169 -0
  82. package/dist/tools/tasks.js.map +1 -0
  83. package/package.json +53 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 filcuk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # PLANKA MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for [PLANKA](https://planka.app) kanban boards, purpose-built for Claude and other AI agents.
4
+
5
+ Forked from [gogogadgetbytes/planka-mcp](https://github.com/gogogadgetbytes/planka-mcp).
6
+
7
+ ## Features
8
+
9
+ - Full PLANKA 2.0 API support
10
+ - Type-safe with Zod validation
11
+ - Optimized for agent workflows (combined operations, sensible defaults)
12
+ - 13 tools covering cards, tasks, labels, comments, and lists
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @filcuk/planka-mcp
18
+ ```
19
+
20
+ Or run directly:
21
+
22
+ ```bash
23
+ npx @filcuk/planka-mcp
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ ### Environment Variables
29
+
30
+ | Variable | Required | Description |
31
+ |----------|----------|-------------|
32
+ | `PLANKA_BASE_URL` | Yes | Your PLANKA server URL |
33
+ | `PLANKA_AGENT_EMAIL` | Yes | Agent user email |
34
+ | `PLANKA_AGENT_PASSWORD` | Yes | Agent user password |
35
+
36
+ ### Claude Desktop
37
+
38
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "planka": {
44
+ "command": "npx",
45
+ "args": ["@filcuk/planka-mcp"],
46
+ "env": {
47
+ "PLANKA_BASE_URL": "https://planka.example.com",
48
+ "PLANKA_AGENT_EMAIL": "agent@example.com",
49
+ "PLANKA_AGENT_PASSWORD": "your-password"
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ### Claude Code
57
+
58
+ Add to `~/.claude.json`:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "planka": {
64
+ "command": "npx",
65
+ "args": ["@filcuk/planka-mcp"],
66
+ "env": {
67
+ "PLANKA_BASE_URL": "https://planka.example.com",
68
+ "PLANKA_AGENT_EMAIL": "agent@example.com",
69
+ "PLANKA_AGENT_PASSWORD": "your-password"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## Available Tools
77
+
78
+ ### Navigation
79
+
80
+ | Tool | Description |
81
+ |------|-------------|
82
+ | `planka_get_structure` | Get projects, boards, and lists hierarchy |
83
+ | `planka_get_board` | Get a board with all cards, lists, and labels |
84
+
85
+ ### Cards
86
+
87
+ | Tool | Description |
88
+ |------|-------------|
89
+ | `planka_create_card` | Create a card (optionally with tasks) |
90
+ | `planka_update_card` | Update card properties |
91
+ | `planka_move_card` | Move card to different list/position |
92
+ | `planka_get_card` | Get card details with tasks/comments |
93
+ | `planka_delete_card` | Delete a card |
94
+
95
+ ### Tasks
96
+
97
+ | Tool | Description |
98
+ |------|-------------|
99
+ | `planka_create_tasks` | Add tasks (checklist items) to a card |
100
+ | `planka_update_task` | Update task name or completion |
101
+ | `planka_delete_task` | Delete a task |
102
+
103
+ ### Labels
104
+
105
+ | Tool | Description |
106
+ |------|-------------|
107
+ | `planka_manage_labels` | Create/update/delete board labels |
108
+ | `planka_set_card_labels` | Add/remove labels from a card |
109
+
110
+ ### Comments
111
+
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `planka_add_comment` | Add a comment to a card |
115
+ | `planka_get_comments` | Get all comments on a card |
116
+
117
+ ### Lists
118
+
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `planka_manage_lists` | Create/update/delete lists |
122
+
123
+ ## Usage Examples
124
+
125
+ ### Get board structure
126
+
127
+ ```
128
+ Use planka_get_structure to see all projects and boards
129
+ ```
130
+
131
+ ### Create a card with tasks
132
+
133
+ ```
134
+ Use planka_create_card with:
135
+ - listId: "abc123"
136
+ - name: "Implement feature X"
137
+ - tasks: ["Research", "Design", "Implement", "Test"]
138
+ ```
139
+
140
+ ### Move card through workflow
141
+
142
+ ```
143
+ Use planka_move_card to move card from "To Do" to "In Progress"
144
+ ```
145
+
146
+ ## PLANKA 2.0 Compatibility
147
+
148
+ This server is designed for PLANKA 2.0 and handles the API differences from 1.x:
149
+
150
+ - Card creation includes required `type` field
151
+ - Label endpoints use `/card-labels` path
152
+ - Optional fields handled gracefully
153
+
154
+ ## Development
155
+
156
+ ```bash
157
+ # Clone
158
+ git clone https://github.com/filcuk/planka-mcp.git
159
+ cd planka-mcp
160
+
161
+ # Install
162
+ npm install
163
+
164
+ # Build
165
+ npm run build
166
+
167
+ # Test
168
+ npm test
169
+ ```
170
+
171
+ ## License
172
+
173
+ MIT
174
+
175
+ ## Links
176
+
177
+ - [PLANKA](https://planka.app) - The kanban board
178
+ - [PLANKA Swagger](https://plankanban.github.io/planka/swagger-ui/swagger.json) - The kanban board
179
+ - [MCP SDK](https://github.com/modelcontextprotocol/sdk) - Model Context Protocol
180
+ - [Design Document](./DESIGN.md) - Technical design details
@@ -0,0 +1,55 @@
1
+ /**
2
+ * PLANKA API client with automatic JWT token management.
3
+ */
4
+ declare class PlankaClient {
5
+ private config;
6
+ private token;
7
+ private tokenExpiresAt;
8
+ /**
9
+ * Gets or initializes the configuration.
10
+ */
11
+ private getConfig;
12
+ /** Request timeout in milliseconds */
13
+ private static readonly REQUEST_TIMEOUT_MS;
14
+ /**
15
+ * Creates an AbortSignal with timeout.
16
+ * Uses AbortSignal.timeout() which automatically cleans up when the request completes.
17
+ */
18
+ private createTimeoutSignal;
19
+ /**
20
+ * Authenticates and retrieves a new JWT token.
21
+ */
22
+ private authenticate;
23
+ /**
24
+ * Gets a valid token, refreshing if necessary.
25
+ */
26
+ private getToken;
27
+ /**
28
+ * Safely parses JSON from a response, returning null on failure.
29
+ */
30
+ private safeParseJson;
31
+ /**
32
+ * Makes an authenticated request to the PLANKA API.
33
+ * @param isRetry - Internal flag to prevent infinite retry loops on 401
34
+ */
35
+ private request;
36
+ /**
37
+ * GET request.
38
+ */
39
+ get<T>(path: string): Promise<T>;
40
+ /**
41
+ * POST request.
42
+ */
43
+ post<T>(path: string, body: unknown): Promise<T>;
44
+ /**
45
+ * PATCH request.
46
+ */
47
+ patch<T>(path: string, body: unknown): Promise<T>;
48
+ /**
49
+ * DELETE request.
50
+ */
51
+ delete(path: string): Promise<void>;
52
+ }
53
+ export declare const plankaClient: PlankaClient;
54
+ export {};
55
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAmDA;;GAEG;AACH,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,cAAc,CAAa;IAEnC;;OAEG;IACH,OAAO,CAAC,SAAS;IAOjB,sCAAsC;IACtC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAEnD;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;YACW,YAAY;IAiD1B;;OAEG;YACW,QAAQ;IAOtB;;OAEG;YACW,aAAa;IAQ3B;;;OAGG;YACW,OAAO;IAqDrB;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAItC;;OAEG;IACG,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAItD;;OAEG;IACG,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C;AAGD,eAAO,MAAM,YAAY,cAAqB,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,193 @@
1
+ /**
2
+ * HTTP client for PLANKA API with automatic authentication.
3
+ */
4
+ import { PlankaAuthError, PlankaConfigError, PlankaNetworkError, createPlankaError, } from "./errors.js";
5
+ import { AuthResponse } from "./schemas/responses.js";
6
+ /**
7
+ * Validates and returns the configuration from environment variables.
8
+ */
9
+ function getConfig() {
10
+ const baseUrl = process.env.PLANKA_BASE_URL;
11
+ const email = process.env.PLANKA_AGENT_EMAIL;
12
+ const password = process.env.PLANKA_AGENT_PASSWORD;
13
+ const missing = [];
14
+ if (!baseUrl)
15
+ missing.push("PLANKA_BASE_URL");
16
+ if (!email)
17
+ missing.push("PLANKA_AGENT_EMAIL");
18
+ if (!password)
19
+ missing.push("PLANKA_AGENT_PASSWORD");
20
+ if (missing.length > 0) {
21
+ throw new PlankaConfigError(`Missing required environment variables: ${missing.join(", ")}`);
22
+ }
23
+ // Validate URL format
24
+ try {
25
+ new URL(baseUrl);
26
+ }
27
+ catch {
28
+ throw new PlankaConfigError(`Invalid PLANKA_BASE_URL: ${baseUrl}`);
29
+ }
30
+ // TypeScript narrowing: after the check above, these are guaranteed to be defined
31
+ return {
32
+ baseUrl: baseUrl.replace(/\/$/, ""), // Remove trailing slash
33
+ email: email,
34
+ password: password,
35
+ };
36
+ }
37
+ /**
38
+ * PLANKA API client with automatic JWT token management.
39
+ */
40
+ class PlankaClient {
41
+ config = null;
42
+ token = null;
43
+ tokenExpiresAt = 0;
44
+ /**
45
+ * Gets or initializes the configuration.
46
+ */
47
+ getConfig() {
48
+ if (!this.config) {
49
+ this.config = getConfig();
50
+ }
51
+ return this.config;
52
+ }
53
+ /** Request timeout in milliseconds */
54
+ static REQUEST_TIMEOUT_MS = 30000;
55
+ /**
56
+ * Creates an AbortSignal with timeout.
57
+ * Uses AbortSignal.timeout() which automatically cleans up when the request completes.
58
+ */
59
+ createTimeoutSignal() {
60
+ return AbortSignal.timeout(PlankaClient.REQUEST_TIMEOUT_MS);
61
+ }
62
+ /**
63
+ * Authenticates and retrieves a new JWT token.
64
+ */
65
+ async authenticate() {
66
+ const config = this.getConfig();
67
+ const url = `${config.baseUrl}/api/access-tokens`;
68
+ let response;
69
+ try {
70
+ response = await fetch(url, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ },
75
+ body: JSON.stringify({
76
+ emailOrUsername: config.email,
77
+ password: config.password,
78
+ }),
79
+ signal: this.createTimeoutSignal(),
80
+ });
81
+ }
82
+ catch (error) {
83
+ if (error instanceof Error && error.name === "AbortError") {
84
+ throw new PlankaNetworkError(`Request timeout connecting to PLANKA at ${config.baseUrl}`, error);
85
+ }
86
+ throw new PlankaNetworkError(`Failed to connect to PLANKA at ${config.baseUrl}`, error);
87
+ }
88
+ if (!response.ok) {
89
+ const body = await this.safeParseJson(response);
90
+ throw new PlankaAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
91
+ }
92
+ const data = await response.json();
93
+ const parsed = AuthResponse.parse(data);
94
+ // PLANKA tokens are valid for 30 minutes by default.
95
+ // We refresh after 25 minutes to avoid edge cases.
96
+ // If PLANKA's token lifetime changes, adjust this value.
97
+ this.tokenExpiresAt = Date.now() + 25 * 60 * 1000;
98
+ this.token = parsed.item;
99
+ return this.token;
100
+ }
101
+ /**
102
+ * Gets a valid token, refreshing if necessary.
103
+ */
104
+ async getToken() {
105
+ if (!this.token || Date.now() >= this.tokenExpiresAt) {
106
+ return this.authenticate();
107
+ }
108
+ return this.token;
109
+ }
110
+ /**
111
+ * Safely parses JSON from a response, returning null on failure.
112
+ */
113
+ async safeParseJson(response) {
114
+ try {
115
+ return await response.json();
116
+ }
117
+ catch {
118
+ return null;
119
+ }
120
+ }
121
+ /**
122
+ * Makes an authenticated request to the PLANKA API.
123
+ * @param isRetry - Internal flag to prevent infinite retry loops on 401
124
+ */
125
+ async request(method, path, body, isRetry = false) {
126
+ const config = this.getConfig();
127
+ const token = await this.getToken();
128
+ const url = `${config.baseUrl}${path}`;
129
+ const headers = {
130
+ Authorization: `Bearer ${token}`,
131
+ };
132
+ if (body !== undefined) {
133
+ headers["Content-Type"] = "application/json";
134
+ }
135
+ let response;
136
+ try {
137
+ response = await fetch(url, {
138
+ method,
139
+ headers,
140
+ body: body !== undefined ? JSON.stringify(body) : undefined,
141
+ signal: this.createTimeoutSignal(),
142
+ });
143
+ }
144
+ catch (error) {
145
+ if (error instanceof Error && error.name === "AbortError") {
146
+ throw new PlankaNetworkError(`Request timeout: ${method} ${path}`, error);
147
+ }
148
+ throw new PlankaNetworkError(`Network error: ${method} ${path}`, error);
149
+ }
150
+ // Handle 204 No Content
151
+ if (response.status === 204) {
152
+ return undefined;
153
+ }
154
+ const data = await this.safeParseJson(response);
155
+ if (!response.ok) {
156
+ // If token expired and this is not already a retry, get fresh token and retry once
157
+ if (response.status === 401 && this.token && !isRetry) {
158
+ this.token = null;
159
+ this.tokenExpiresAt = 0;
160
+ return this.request(method, path, body, true);
161
+ }
162
+ throw createPlankaError(response.status, data, `${method} ${path}`);
163
+ }
164
+ return data;
165
+ }
166
+ /**
167
+ * GET request.
168
+ */
169
+ async get(path) {
170
+ return this.request("GET", path);
171
+ }
172
+ /**
173
+ * POST request.
174
+ */
175
+ async post(path, body) {
176
+ return this.request("POST", path, body);
177
+ }
178
+ /**
179
+ * PATCH request.
180
+ */
181
+ async patch(path, body) {
182
+ return this.request("PATCH", path, body);
183
+ }
184
+ /**
185
+ * DELETE request.
186
+ */
187
+ async delete(path) {
188
+ return this.request("DELETE", path);
189
+ }
190
+ }
191
+ // Singleton client instance
192
+ export const plankaClient = new PlankaClient();
193
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Typed error classes for PLANKA API operations.
3
+ */
4
+ export declare class PlankaError extends Error {
5
+ readonly code: string;
6
+ readonly status: number;
7
+ readonly details?: unknown | undefined;
8
+ constructor(message: string, code: string, status: number, details?: unknown | undefined);
9
+ }
10
+ export declare class PlankaAuthError extends PlankaError {
11
+ constructor(message?: string);
12
+ }
13
+ export declare class PlankaNotFoundError extends PlankaError {
14
+ constructor(resource: string, id: string);
15
+ }
16
+ export declare class PlankaValidationError extends PlankaError {
17
+ constructor(message: string, details?: unknown);
18
+ }
19
+ export declare class PlankaPermissionError extends PlankaError {
20
+ constructor(message?: string);
21
+ }
22
+ export declare class PlankaConfigError extends PlankaError {
23
+ constructor(message: string);
24
+ }
25
+ export declare class PlankaNetworkError extends PlankaError {
26
+ constructor(message: string, details?: unknown);
27
+ }
28
+ /**
29
+ * Factory function to create typed errors from API responses.
30
+ * @param status HTTP status code
31
+ * @param body Response body (parsed JSON or null)
32
+ * @param context Optional context (e.g., "GET /api/cards/123")
33
+ */
34
+ export declare function createPlankaError(status: number, body: unknown, context?: string): PlankaError;
35
+ /**
36
+ * Type guard for PlankaError instances.
37
+ */
38
+ export declare function isPlankaError(error: unknown): error is PlankaError;
39
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,WAAY,SAAQ,KAAK;aAGlB,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;aACd,OAAO,CAAC,EAAE,OAAO;gBAHjC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,YAAA;CAKpC;AAED,qBAAa,eAAgB,SAAQ,WAAW;gBAClC,OAAO,SAA0B;CAI9C;AAED,qBAAa,mBAAoB,SAAQ,WAAW;gBACtC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAIzC;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;CAI/C;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,OAAO,SAA6B;CAIjD;AAED,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;CAI/C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,MAAM,GACf,WAAW,CAoBb;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE"}
package/dist/errors.js ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Typed error classes for PLANKA API operations.
3
+ */
4
+ export class PlankaError extends Error {
5
+ code;
6
+ status;
7
+ details;
8
+ constructor(message, code, status, details) {
9
+ super(message);
10
+ this.code = code;
11
+ this.status = status;
12
+ this.details = details;
13
+ this.name = "PlankaError";
14
+ }
15
+ }
16
+ export class PlankaAuthError extends PlankaError {
17
+ constructor(message = "Authentication failed") {
18
+ super(message, "AUTH_FAILED", 401);
19
+ this.name = "PlankaAuthError";
20
+ }
21
+ }
22
+ export class PlankaNotFoundError extends PlankaError {
23
+ constructor(resource, id) {
24
+ super(`${resource} not found: ${id}`, "NOT_FOUND", 404);
25
+ this.name = "PlankaNotFoundError";
26
+ }
27
+ }
28
+ export class PlankaValidationError extends PlankaError {
29
+ constructor(message, details) {
30
+ super(message, "VALIDATION_ERROR", 422, details);
31
+ this.name = "PlankaValidationError";
32
+ }
33
+ }
34
+ export class PlankaPermissionError extends PlankaError {
35
+ constructor(message = "Insufficient permissions") {
36
+ super(message, "PERMISSION_DENIED", 403);
37
+ this.name = "PlankaPermissionError";
38
+ }
39
+ }
40
+ export class PlankaConfigError extends PlankaError {
41
+ constructor(message) {
42
+ super(message, "CONFIG_ERROR", 0);
43
+ this.name = "PlankaConfigError";
44
+ }
45
+ }
46
+ export class PlankaNetworkError extends PlankaError {
47
+ constructor(message, details) {
48
+ super(message, "NETWORK_ERROR", 0, details);
49
+ this.name = "PlankaNetworkError";
50
+ }
51
+ }
52
+ /**
53
+ * Factory function to create typed errors from API responses.
54
+ * @param status HTTP status code
55
+ * @param body Response body (parsed JSON or null)
56
+ * @param context Optional context (e.g., "GET /api/cards/123")
57
+ */
58
+ export function createPlankaError(status, body, context) {
59
+ const message = typeof body === "object" && body !== null && "message" in body
60
+ ? String(body.message)
61
+ : "Unknown error";
62
+ const contextSuffix = context ? ` (${context})` : "";
63
+ switch (status) {
64
+ case 401:
65
+ return new PlankaAuthError(message + contextSuffix);
66
+ case 403:
67
+ return new PlankaPermissionError(message + contextSuffix);
68
+ case 404:
69
+ return new PlankaNotFoundError("Resource", context || "unknown");
70
+ case 422:
71
+ return new PlankaValidationError(message + contextSuffix, body);
72
+ default:
73
+ return new PlankaError(message + contextSuffix, "API_ERROR", status, body);
74
+ }
75
+ }
76
+ /**
77
+ * Type guard for PlankaError instances.
78
+ */
79
+ export function isPlankaError(error) {
80
+ return error instanceof PlankaError;
81
+ }
82
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGlB;IACA;IACA;IAJlB,YACE,OAAe,EACC,IAAY,EACZ,MAAc,EACd,OAAiB;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAU;QAGjC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,YAAY,OAAO,GAAG,uBAAuB;QAC3C,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IAClD,YAAY,QAAgB,EAAE,EAAU;QACtC,KAAK,CAAC,GAAG,QAAQ,eAAe,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,YAAY,OAAO,GAAG,0BAA0B;QAC9C,KAAK,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACjD,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,IAAa,EACb,OAAgB;IAEhB,MAAM,OAAO,GACX,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI;QAC5D,CAAC,CAAC,MAAM,CAAE,IAAgC,CAAC,OAAO,CAAC;QACnD,CAAC,CAAC,eAAe,CAAC;IAEtB,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAErD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,GAAG;YACN,OAAO,IAAI,eAAe,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC;QACtD,KAAK,GAAG;YACN,OAAO,IAAI,qBAAqB,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC;QAC5D,KAAK,GAAG;YACN,OAAO,IAAI,mBAAmB,CAAC,UAAU,EAAE,OAAO,IAAI,SAAS,CAAC,CAAC;QACnE,KAAK,GAAG;YACN,OAAO,IAAI,qBAAqB,CAAC,OAAO,GAAG,aAAa,EAAE,IAAI,CAAC,CAAC;QAClE;YACE,OAAO,IAAI,WAAW,CAAC,OAAO,GAAG,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,KAAK,YAAY,WAAW,CAAC;AACtC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}