kanban-lite 1.0.9 → 1.0.13

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 (38) hide show
  1. package/dist/cli.js +1015 -407
  2. package/dist/extension.js +897 -347
  3. package/dist/mcp-server.js +550 -189
  4. package/dist/sdk/index.cjs +1223 -0
  5. package/dist/sdk/index.mjs +1168 -0
  6. package/dist/sdk/sdk/KanbanSDK.d.ts +39 -21
  7. package/dist/sdk/sdk/index.d.ts +4 -3
  8. package/dist/sdk/sdk/migration.d.ts +6 -0
  9. package/dist/sdk/sdk/types.d.ts +3 -5
  10. package/dist/sdk/shared/config.d.ts +23 -10
  11. package/dist/sdk/shared/types.d.ts +18 -4
  12. package/dist/standalone-webview/index.js +27 -27
  13. package/dist/standalone-webview/index.js.map +1 -1
  14. package/dist/standalone-webview/style.css +1 -1
  15. package/dist/standalone.js +831 -328
  16. package/dist/webview/index.js +45 -45
  17. package/dist/webview/index.js.map +1 -1
  18. package/dist/webview/style.css +1 -1
  19. package/package.json +4 -3
  20. package/src/cli/index.ts +217 -95
  21. package/src/extension/KanbanPanel.ts +49 -22
  22. package/src/mcp-server/index.ts +138 -62
  23. package/src/sdk/KanbanSDK.ts +283 -77
  24. package/src/sdk/__tests__/KanbanSDK.test.ts +5 -5
  25. package/src/sdk/__tests__/migration.test.ts +269 -0
  26. package/src/sdk/__tests__/multi-board.test.ts +449 -0
  27. package/src/sdk/index.ts +4 -3
  28. package/src/sdk/migration.ts +52 -0
  29. package/src/sdk/types.ts +3 -6
  30. package/src/shared/config.ts +144 -22
  31. package/src/shared/types.ts +14 -5
  32. package/src/standalone/__tests__/server.integration.test.ts +38 -37
  33. package/src/standalone/server.ts +239 -21
  34. package/src/webview/App.tsx +17 -7
  35. package/src/webview/components/Toolbar.tsx +99 -3
  36. package/src/webview/store/index.ts +11 -3
  37. package/.kanban/backlog/1-test1.md +0 -30
  38. package/.kanban.json +0 -42
@@ -0,0 +1,449 @@
1
+ import * as fs from 'node:fs'
2
+ import * as os from 'node:os'
3
+ import * as path from 'node:path'
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
5
+ import { KanbanSDK } from '../KanbanSDK'
6
+ import { DEFAULT_COLUMNS } from '../../shared/types'
7
+ import type { KanbanConfig } from '../../shared/config'
8
+
9
+ function createV2Config(overrides?: Partial<KanbanConfig>): KanbanConfig {
10
+ return {
11
+ version: 2,
12
+ boards: {
13
+ default: {
14
+ name: 'Default',
15
+ columns: [...DEFAULT_COLUMNS],
16
+ nextCardId: 1,
17
+ defaultStatus: 'backlog',
18
+ defaultPriority: 'medium'
19
+ }
20
+ },
21
+ defaultBoard: 'default',
22
+ featuresDirectory: '.kanban',
23
+ aiAgent: 'claude',
24
+ defaultPriority: 'medium',
25
+ defaultStatus: 'backlog',
26
+ showPriorityBadges: true,
27
+ showAssignee: true,
28
+ showDueDate: true,
29
+ showLabels: true,
30
+ showBuildWithAI: true,
31
+ showFileName: false,
32
+ compactMode: false,
33
+ markdownEditorMode: false,
34
+ ...overrides
35
+ }
36
+ }
37
+
38
+ describe('Multi-board SDK operations', () => {
39
+ let workspaceDir: string
40
+ let featuresDir: string
41
+ let sdk: KanbanSDK
42
+
43
+ beforeEach(() => {
44
+ workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kanban-multi-board-'))
45
+ featuresDir = path.join(workspaceDir, '.kanban')
46
+ fs.mkdirSync(featuresDir, { recursive: true })
47
+ // Write v2 config
48
+ const config = createV2Config()
49
+ fs.writeFileSync(path.join(workspaceDir, '.kanban.json'), JSON.stringify(config, null, 2))
50
+ sdk = new KanbanSDK(featuresDir)
51
+ })
52
+
53
+ afterEach(() => {
54
+ fs.rmSync(workspaceDir, { recursive: true, force: true })
55
+ })
56
+
57
+ describe('listBoards', () => {
58
+ it('should return boards from config', () => {
59
+ const boards = sdk.listBoards()
60
+ expect(boards).toHaveLength(1)
61
+ expect(boards[0].id).toBe('default')
62
+ expect(boards[0].name).toBe('Default')
63
+ })
64
+
65
+ it('should return multiple boards when configured', () => {
66
+ const config = createV2Config()
67
+ config.boards['sprint'] = {
68
+ name: 'Sprint Board',
69
+ columns: [...DEFAULT_COLUMNS],
70
+ nextCardId: 1,
71
+ defaultStatus: 'backlog',
72
+ defaultPriority: 'medium'
73
+ }
74
+ fs.writeFileSync(path.join(workspaceDir, '.kanban.json'), JSON.stringify(config, null, 2))
75
+
76
+ const boards = sdk.listBoards()
77
+ expect(boards).toHaveLength(2)
78
+ const boardIds = boards.map(b => b.id).sort()
79
+ expect(boardIds).toEqual(['default', 'sprint'])
80
+ })
81
+ })
82
+
83
+ describe('createBoard', () => {
84
+ it('should create a board dir and add to config', () => {
85
+ const board = sdk.createBoard('sprint', 'Sprint Board')
86
+
87
+ expect(board.id).toBe('sprint')
88
+ expect(board.name).toBe('Sprint Board')
89
+
90
+ // Verify config was updated
91
+ const raw = JSON.parse(fs.readFileSync(path.join(workspaceDir, '.kanban.json'), 'utf-8'))
92
+ expect(raw.boards.sprint).toBeDefined()
93
+ expect(raw.boards.sprint.name).toBe('Sprint Board')
94
+ expect(raw.boards.sprint.columns).toEqual(DEFAULT_COLUMNS)
95
+ expect(raw.boards.sprint.nextCardId).toBe(1)
96
+ })
97
+
98
+ it('should create a board with custom options', () => {
99
+ const customColumns = [
100
+ { id: 'new', name: 'New', color: '#ff0000' },
101
+ { id: 'wip', name: 'WIP', color: '#00ff00' },
102
+ { id: 'finished', name: 'Finished', color: '#0000ff' }
103
+ ]
104
+ const board = sdk.createBoard('custom', 'Custom Board', {
105
+ description: 'A custom board',
106
+ columns: customColumns,
107
+ defaultStatus: 'new',
108
+ defaultPriority: 'high'
109
+ })
110
+
111
+ expect(board.id).toBe('custom')
112
+ expect(board.name).toBe('Custom Board')
113
+ expect(board.description).toBe('A custom board')
114
+
115
+ const raw = JSON.parse(fs.readFileSync(path.join(workspaceDir, '.kanban.json'), 'utf-8'))
116
+ expect(raw.boards.custom.columns).toEqual(customColumns)
117
+ expect(raw.boards.custom.defaultStatus).toBe('new')
118
+ expect(raw.boards.custom.defaultPriority).toBe('high')
119
+ })
120
+
121
+ it('should throw if board already exists', () => {
122
+ expect(() => sdk.createBoard('default', 'Another Default')).toThrow('Board already exists: default')
123
+ })
124
+ })
125
+
126
+ describe('deleteBoard', () => {
127
+ it('should remove an empty board', async () => {
128
+ sdk.createBoard('temp', 'Temporary')
129
+
130
+ // Create the board directory so deletion can clean it up
131
+ fs.mkdirSync(path.join(featuresDir, 'boards', 'temp'), { recursive: true })
132
+
133
+ await sdk.deleteBoard('temp')
134
+
135
+ const boards = sdk.listBoards()
136
+ expect(boards.find(b => b.id === 'temp')).toBeUndefined()
137
+
138
+ const raw = JSON.parse(fs.readFileSync(path.join(workspaceDir, '.kanban.json'), 'utf-8'))
139
+ expect(raw.boards.temp).toBeUndefined()
140
+ })
141
+
142
+ it('should throw when deleting the default board', async () => {
143
+ await expect(sdk.deleteBoard('default')).rejects.toThrow('Cannot delete the default board')
144
+ })
145
+
146
+ it('should throw when deleting a non-existent board', async () => {
147
+ await expect(sdk.deleteBoard('nonexistent')).rejects.toThrow('Board not found')
148
+ })
149
+
150
+ it('should throw when deleting a board with cards', async () => {
151
+ sdk.createBoard('has-cards', 'Has Cards')
152
+ await sdk.createCard({ content: '# Card', boardId: 'has-cards' })
153
+
154
+ await expect(sdk.deleteBoard('has-cards')).rejects.toThrow('card(s) still exist')
155
+ })
156
+ })
157
+
158
+ describe('getBoard', () => {
159
+ it('should return board config', () => {
160
+ const board = sdk.getBoard('default')
161
+
162
+ expect(board.name).toBe('Default')
163
+ expect(board.columns).toEqual(DEFAULT_COLUMNS)
164
+ expect(board.nextCardId).toBeGreaterThanOrEqual(1)
165
+ expect(board.defaultStatus).toBe('backlog')
166
+ expect(board.defaultPriority).toBe('medium')
167
+ })
168
+
169
+ it('should throw for non-existent board', () => {
170
+ expect(() => sdk.getBoard('nonexistent')).toThrow("Board 'nonexistent' not found")
171
+ })
172
+ })
173
+
174
+ describe('createCard with boardId', () => {
175
+ it('should create a card file in the correct board dir', async () => {
176
+ sdk.createBoard('sprint', 'Sprint')
177
+
178
+ const card = await sdk.createCard({
179
+ content: '# Sprint Task',
180
+ status: 'todo',
181
+ boardId: 'sprint'
182
+ })
183
+
184
+ expect(card.boardId).toBe('sprint')
185
+ expect(card.status).toBe('todo')
186
+ expect(card.filePath).toContain(path.join('boards', 'sprint', 'todo'))
187
+ expect(fs.existsSync(card.filePath)).toBe(true)
188
+ })
189
+
190
+ it('should use default board when boardId is not specified', async () => {
191
+ const card = await sdk.createCard({ content: '# Default Card' })
192
+
193
+ expect(card.boardId).toBe('default')
194
+ expect(card.filePath).toContain(path.join('boards', 'default'))
195
+ expect(fs.existsSync(card.filePath)).toBe(true)
196
+ })
197
+ })
198
+
199
+ describe('listCards with boardId', () => {
200
+ it('should only return cards from the specified board', async () => {
201
+ sdk.createBoard('sprint', 'Sprint')
202
+
203
+ await sdk.createCard({ content: '# Default Card', boardId: 'default' })
204
+ await sdk.createCard({ content: '# Sprint Card', boardId: 'sprint' })
205
+
206
+ const defaultCards = await sdk.listCards(undefined, 'default')
207
+ expect(defaultCards).toHaveLength(1)
208
+ expect(defaultCards[0].content).toContain('Default Card')
209
+
210
+ const sprintCards = await sdk.listCards(undefined, 'sprint')
211
+ expect(sprintCards).toHaveLength(1)
212
+ expect(sprintCards[0].content).toContain('Sprint Card')
213
+ })
214
+
215
+ it('should return empty array for board with no cards', async () => {
216
+ sdk.createBoard('empty', 'Empty Board')
217
+
218
+ const cards = await sdk.listCards(undefined, 'empty')
219
+ expect(cards).toEqual([])
220
+ })
221
+ })
222
+
223
+ describe('moveCard with boardId', () => {
224
+ it('should move a card within a board', async () => {
225
+ const card = await sdk.createCard({
226
+ content: '# Move Me',
227
+ status: 'backlog',
228
+ boardId: 'default'
229
+ })
230
+
231
+ const moved = await sdk.moveCard(card.id, 'in-progress', undefined, 'default')
232
+
233
+ expect(moved.status).toBe('in-progress')
234
+ expect(moved.filePath).toContain(path.join('boards', 'default', 'in-progress'))
235
+ expect(fs.existsSync(moved.filePath)).toBe(true)
236
+ })
237
+ })
238
+
239
+ describe('transferCard', () => {
240
+ it('should move a card file between boards', async () => {
241
+ sdk.createBoard('sprint', 'Sprint')
242
+
243
+ const card = await sdk.createCard({
244
+ content: '# Transfer Me',
245
+ status: 'backlog',
246
+ boardId: 'default'
247
+ })
248
+ const oldPath = card.filePath
249
+ expect(oldPath).toContain(path.join('boards', 'default'))
250
+
251
+ const transferred = await sdk.transferCard(card.id, 'default', 'sprint')
252
+
253
+ expect(transferred.boardId).toBe('sprint')
254
+ expect(transferred.filePath).toContain(path.join('boards', 'sprint'))
255
+ expect(fs.existsSync(transferred.filePath)).toBe(true)
256
+ expect(fs.existsSync(oldPath)).toBe(false)
257
+ })
258
+
259
+ it('should use target board default status when no targetStatus provided', async () => {
260
+ sdk.createBoard('sprint', 'Sprint')
261
+
262
+ const card = await sdk.createCard({
263
+ content: '# Transfer Default Status',
264
+ status: 'todo',
265
+ boardId: 'default'
266
+ })
267
+
268
+ const transferred = await sdk.transferCard(card.id, 'default', 'sprint')
269
+
270
+ // Sprint board defaultStatus is 'backlog' (inherited from default columns)
271
+ expect(transferred.status).toBe('backlog')
272
+ })
273
+
274
+ it('should use specified targetStatus', async () => {
275
+ sdk.createBoard('sprint', 'Sprint')
276
+
277
+ const card = await sdk.createCard({
278
+ content: '# Transfer With Status',
279
+ status: 'backlog',
280
+ boardId: 'default'
281
+ })
282
+
283
+ const transferred = await sdk.transferCard(card.id, 'default', 'sprint', 'in-progress')
284
+
285
+ expect(transferred.status).toBe('in-progress')
286
+ expect(transferred.filePath).toContain(path.join('boards', 'sprint', 'in-progress'))
287
+ })
288
+
289
+ it('should throw for non-existent source board', async () => {
290
+ await expect(sdk.transferCard('1', 'nonexistent', 'default')).rejects.toThrow('Board not found')
291
+ })
292
+
293
+ it('should throw for non-existent target board', async () => {
294
+ await expect(sdk.transferCard('1', 'default', 'nonexistent')).rejects.toThrow('Board not found')
295
+ })
296
+ })
297
+
298
+ describe('per-board card IDs', () => {
299
+ it('should assign independent numeric IDs per board', async () => {
300
+ sdk.createBoard('sprint', 'Sprint')
301
+
302
+ const defaultCard = await sdk.createCard({
303
+ content: '# Default Card',
304
+ boardId: 'default'
305
+ })
306
+ const sprintCard = await sdk.createCard({
307
+ content: '# Sprint Card',
308
+ boardId: 'sprint'
309
+ })
310
+
311
+ // Both boards start at ID 1, so both should get "1" as their first card ID
312
+ expect(defaultCard.id).toBe('1')
313
+ expect(sprintCard.id).toBe('1')
314
+
315
+ // They should be in different directories
316
+ expect(defaultCard.filePath).toContain(path.join('boards', 'default'))
317
+ expect(sprintCard.filePath).toContain(path.join('boards', 'sprint'))
318
+ })
319
+ })
320
+
321
+ describe('listColumns with boardId', () => {
322
+ it('should return board-specific columns', () => {
323
+ sdk.createBoard('sprint', 'Sprint', {
324
+ columns: [
325
+ { id: 'new', name: 'New', color: '#ff0000' },
326
+ { id: 'wip', name: 'WIP', color: '#00ff00' }
327
+ ]
328
+ })
329
+
330
+ const defaultColumns = sdk.listColumns('default')
331
+ expect(defaultColumns).toEqual(DEFAULT_COLUMNS)
332
+
333
+ const sprintColumns = sdk.listColumns('sprint')
334
+ expect(sprintColumns).toHaveLength(2)
335
+ expect(sprintColumns[0].id).toBe('new')
336
+ expect(sprintColumns[1].id).toBe('wip')
337
+ })
338
+
339
+ it('should return default board columns when boardId is omitted', () => {
340
+ const columns = sdk.listColumns()
341
+ expect(columns).toEqual(DEFAULT_COLUMNS)
342
+ })
343
+ })
344
+
345
+ describe('addColumn with boardId', () => {
346
+ it('should add a column to a specific board', () => {
347
+ sdk.createBoard('sprint', 'Sprint')
348
+
349
+ const columns = sdk.addColumn({ id: 'staging', name: 'Staging', color: '#aabbcc' }, 'sprint')
350
+
351
+ // Sprint board inherits default columns + the new one
352
+ expect(columns.find(c => c.id === 'staging')).toBeDefined()
353
+
354
+ // Default board should not have the new column
355
+ const defaultColumns = sdk.listColumns('default')
356
+ expect(defaultColumns.find(c => c.id === 'staging')).toBeUndefined()
357
+ })
358
+
359
+ it('should throw if column already exists in that board', () => {
360
+ expect(() => sdk.addColumn({ id: 'backlog', name: 'Backlog Again', color: '#000' }, 'default'))
361
+ .toThrow('Column already exists: backlog')
362
+ })
363
+ })
364
+
365
+ describe('_isCompletedStatus logic', () => {
366
+ it('should set completedAt when moving to the last column', async () => {
367
+ // Default columns: backlog, todo, in-progress, review, done
368
+ // "done" is the last column
369
+ const card = await sdk.createCard({
370
+ content: '# Complete Me',
371
+ status: 'review',
372
+ boardId: 'default'
373
+ })
374
+ expect(card.completedAt).toBeNull()
375
+
376
+ const moved = await sdk.moveCard(card.id, 'done', undefined, 'default')
377
+ expect(moved.completedAt).not.toBeNull()
378
+ })
379
+
380
+ it('should clear completedAt when moving away from the last column', async () => {
381
+ const card = await sdk.createCard({
382
+ content: '# Uncomplete Me',
383
+ status: 'done',
384
+ boardId: 'default'
385
+ })
386
+ expect(card.completedAt).not.toBeNull()
387
+
388
+ const moved = await sdk.moveCard(card.id, 'backlog', undefined, 'default')
389
+ expect(moved.completedAt).toBeNull()
390
+ })
391
+
392
+ it('should use the last column of a custom board for completed status', async () => {
393
+ sdk.createBoard('custom', 'Custom', {
394
+ columns: [
395
+ { id: 'open', name: 'Open', color: '#ff0000' },
396
+ { id: 'closed', name: 'Closed', color: '#00ff00' }
397
+ ],
398
+ defaultStatus: 'open'
399
+ })
400
+
401
+ const card = await sdk.createCard({
402
+ content: '# Custom Complete',
403
+ status: 'open',
404
+ boardId: 'custom'
405
+ })
406
+ expect(card.completedAt).toBeNull()
407
+
408
+ const moved = await sdk.moveCard(card.id, 'closed', undefined, 'custom')
409
+ expect(moved.completedAt).not.toBeNull()
410
+ })
411
+ })
412
+
413
+ describe('board isolation', () => {
414
+ it('should not find cards across boards with getCard', async () => {
415
+ sdk.createBoard('sprint', 'Sprint')
416
+
417
+ const card = await sdk.createCard({
418
+ content: '# Only In Default',
419
+ boardId: 'default'
420
+ })
421
+
422
+ // Should find in default board
423
+ const found = await sdk.getCard(card.id, 'default')
424
+ expect(found).not.toBeNull()
425
+ expect(found?.id).toBe(card.id)
426
+
427
+ // Should not find in sprint board
428
+ const notFound = await sdk.getCard(card.id, 'sprint')
429
+ expect(notFound).toBeNull()
430
+ })
431
+
432
+ it('should keep cards in separate board directories on disk', async () => {
433
+ sdk.createBoard('sprint', 'Sprint')
434
+
435
+ await sdk.createCard({ content: '# Default Task', boardId: 'default' })
436
+ await sdk.createCard({ content: '# Sprint Task', boardId: 'sprint' })
437
+
438
+ const defaultBoardDir = path.join(featuresDir, 'boards', 'default')
439
+ const sprintBoardDir = path.join(featuresDir, 'boards', 'sprint')
440
+
441
+ // Each board dir should have its own card files
442
+ const defaultFiles = fs.readdirSync(path.join(defaultBoardDir, 'backlog')).filter(f => f.endsWith('.md'))
443
+ const sprintFiles = fs.readdirSync(path.join(sprintBoardDir, 'backlog')).filter(f => f.endsWith('.md'))
444
+
445
+ expect(defaultFiles).toHaveLength(1)
446
+ expect(sprintFiles).toHaveLength(1)
447
+ })
448
+ })
449
+ })
package/src/sdk/index.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export { KanbanSDK } from './KanbanSDK'
2
2
  export { parseFeatureFile, serializeFeature } from './parser'
3
3
  export { getFeatureFilePath, ensureDirectories, ensureStatusSubfolders, moveFeatureFile, renameFeatureFile, getStatusFromPath } from './fileUtils'
4
+ export { migrateFileSystemToMultiBoard } from './migration'
4
5
  export type { CreateCardInput } from './types'
5
- export type { KanbanConfig } from '../shared/config'
6
- export type { CardDisplaySettings } from '../shared/types'
7
- export { readConfig, writeConfig, configToSettings, settingsToConfig } from '../shared/config'
6
+ export type { KanbanConfig, BoardConfig } from '../shared/config'
7
+ export type { CardDisplaySettings, BoardInfo } from '../shared/types'
8
+ export { readConfig, writeConfig, configToSettings, settingsToConfig, getBoardConfig, getDefaultBoardId } from '../shared/config'
8
9
  export type { Feature, FeatureStatus, Priority, KanbanColumn } from '../shared/types'
9
10
  export { getTitleFromContent, generateFeatureFilename, DEFAULT_COLUMNS } from '../shared/types'
@@ -0,0 +1,52 @@
1
+ import * as fs from 'fs/promises'
2
+ import * as path from 'path'
3
+
4
+ /**
5
+ * Migrate a v1 single-board file system layout to v2 multi-board layout.
6
+ * Moves status subdirectories from .kanban/{status}/ into .kanban/boards/default/{status}/.
7
+ * Idempotent: if boards/ already exists, this is a no-op.
8
+ */
9
+ export async function migrateFileSystemToMultiBoard(featuresDir: string): Promise<void> {
10
+ const boardsDir = path.join(featuresDir, 'boards')
11
+ const defaultBoardDir = path.join(boardsDir, 'default')
12
+
13
+ // Check if already migrated
14
+ try {
15
+ await fs.access(boardsDir)
16
+ return // boards/ already exists, skip
17
+ } catch {
18
+ // Not yet migrated, proceed
19
+ }
20
+
21
+ await fs.mkdir(defaultBoardDir, { recursive: true })
22
+
23
+ let entries: import('fs').Dirent[]
24
+ try {
25
+ entries = await fs.readdir(featuresDir, { withFileTypes: true }) as import('fs').Dirent[]
26
+ } catch {
27
+ return // featuresDir doesn't exist yet
28
+ }
29
+
30
+ // Move each subdirectory that looks like a status folder
31
+ for (const entry of entries) {
32
+ if (!entry.isDirectory()) continue
33
+ if (entry.name === 'boards' || entry.name.startsWith('.')) continue
34
+
35
+ const src = path.join(featuresDir, entry.name)
36
+ const dest = path.join(defaultBoardDir, entry.name)
37
+ await fs.rename(src, dest)
38
+ }
39
+
40
+ // Move any root-level .md files into default/backlog/
41
+ const rootMdFiles = entries.filter(e => e.isFile() && e.name.endsWith('.md'))
42
+ if (rootMdFiles.length > 0) {
43
+ const backlogDir = path.join(defaultBoardDir, 'backlog')
44
+ await fs.mkdir(backlogDir, { recursive: true })
45
+ for (const file of rootMdFiles) {
46
+ await fs.rename(
47
+ path.join(featuresDir, file.name),
48
+ path.join(backlogDir, file.name)
49
+ )
50
+ }
51
+ }
52
+ }
package/src/sdk/types.ts CHANGED
@@ -1,15 +1,12 @@
1
- import type { FeatureStatus, KanbanColumn, Priority } from '../shared/types'
1
+ import type { Priority } from '../shared/types'
2
2
 
3
3
  export interface CreateCardInput {
4
4
  content: string
5
- status?: FeatureStatus
5
+ status?: string
6
6
  priority?: Priority
7
7
  assignee?: string | null
8
8
  dueDate?: string | null
9
9
  labels?: string[]
10
10
  attachments?: string[]
11
- }
12
-
13
- export interface BoardConfig {
14
- columns: KanbanColumn[]
11
+ boardId?: string
15
12
  }