tdecollab 0.1.3 → 0.2.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/dist/{chunk-K5LQBRHJ.js → chunk-2IQ4QMK3.js} +391 -2
- package/dist/chunk-2IQ4QMK3.js.map +1 -0
- package/dist/chunk-T73I3OT6.js +964 -0
- package/dist/chunk-T73I3OT6.js.map +1 -0
- package/dist/cli.js +574 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/server-HS774DWY.js +9 -0
- package/package.json +1 -1
- package/dist/chunk-CNARZOBV.js +0 -308
- package/dist/chunk-CNARZOBV.js.map +0 -1
- package/dist/chunk-K5LQBRHJ.js.map +0 -1
- package/dist/server-VBNZQFGP.js +0 -9
- /package/dist/{server-VBNZQFGP.js.map → server-HS774DWY.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/confluence/commands/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registerConfluenceCommands } from './confluence/commands/index.js';\nimport dotenv from 'dotenv';\n\n// Load environment variables\ndotenv.config();\n\nconst program = new Command();\n\nprogram\n .name('tdecollab')\n .description('TDE Collaboration CLI')\n .version('0.1.0');\n\n// Register module commands\nregisterConfluenceCommands(program);\n\nprogram\n .command('mcp')\n .description('Run MCP Server')\n .action(async () => {\n const { runServer } = await import('./mcp/server.js');\n await runServer();\n });\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { ConfluenceContentApi } from '../api/content.js';\nimport { ConfluenceSpaceApi } from '../api/space.js';\nimport { ConfluenceSearchApi } from '../api/search.js';\nimport { ConfluenceLabelApi } from '../api/label.js';\nimport { createConfluenceClient } from '../api/client.js';\nimport { MarkdownToStorageConverter } from '../converters/md-to-storage.js';\nimport { StorageToMarkdownConverter } from '../converters/storage-to-md.js';\nimport { loadConfluenceConfig } from '../../common/config.js';\nimport { logger } from '../../common/logger.js';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function registerConfluenceCommands(program: Command) {\n const confluenceCmd = program.command('confluence')\n .description('Confluence 관리');\n\n // 공통 초기화 함수\n const initClient = () => {\n try {\n const config = loadConfluenceConfig();\n return createConfluenceClient(config);\n } catch (e: any) {\n console.error(chalk.red(`설정 로드 실패: ${e.message}`));\n process.exit(1);\n }\n };\n\n // --- Page Commands ---\n const pageCmd = confluenceCmd.command('page').description('페이지 관리');\n\n pageCmd.command('get <pageId>')\n .description('페이지 조회')\n .option('-r, --raw', 'Raw Storage Format 출력')\n .option('-q, --quiet', '메타데이터 생략')\n .option('-d, --download-images', '이미지 다운로드')\n .option('--image-dir <path>', '이미지 저장 디렉토리', './images')\n .option('-o, --output <file>', 'Markdown을 파일로 저장')\n .action(async (pageId, options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const config = loadConfluenceConfig();\n\n try {\n const page = await api.getPage(pageId);\n\n if (!options.quiet) {\n console.log(chalk.bold(`Title: ${page.title}`));\n console.log(chalk.gray(`ID: ${page.id}`));\n console.log(`Space: ${page.space?.name} (${page.space?.key})`);\n console.log(`URL: ${page._links?.base}${page._links?.webui}`);\n }\n\n let content = '';\n\n if (options.raw) {\n if (!options.quiet) console.log(chalk.dim('--- Content (Storage Format) ---'));\n if (page.body?.storage?.value) {\n content = page.body.storage.value;\n } else {\n if (!options.quiet) console.log(chalk.yellow('(No content)'));\n }\n } else {\n if (!options.quiet) console.log(chalk.dim('--- Content (Markdown) ---'));\n if (page.body?.storage?.value) {\n let imageUrlMap: Map<string, string> | undefined;\n\n // 이미지 다운로드 옵션이 활성화된 경우\n if (options.downloadImages) {\n const { ImageDownloader } = await import('../utils/image-downloader.js');\n const downloader = new ImageDownloader(api, {\n outputDir: path.resolve(process.cwd(), options.imageDir),\n pageId: page.id,\n baseUrl: config.baseUrl\n });\n\n console.log(chalk.blue('이미지 다운로드 중...'));\n imageUrlMap = await downloader.downloadAllImages(page.body.storage.value);\n }\n\n const storageToMd = new StorageToMarkdownConverter();\n content = storageToMd.convert(page.body.storage.value, imageUrlMap);\n } else {\n if (!options.quiet) console.log(chalk.yellow('(No content)'));\n }\n }\n\n // 파일로 저장 또는 콘솔 출력\n if (options.output) {\n const outputPath = path.resolve(process.cwd(), options.output);\n fs.writeFileSync(outputPath, content, 'utf-8');\n console.log(chalk.green(`파일 저장 완료: ${outputPath}`));\n } else {\n console.log(content);\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n pageCmd.command('create')\n .requiredOption('-s, --space <key>', '스페이스 키')\n .requiredOption('-t, --title <title>', '제목')\n .option('-c, --content <content>', '내용 (Markdown 텍스트)')\n .option('-f, --file <path>', '내용 파일 경로 (Markdown)')\n .option('-p, --parent <id>', '부모 페이지 ID')\n .description('페이지 생성')\n .action(async (options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const mdToStorage = new MarkdownToStorageConverter();\n\n try {\n let markdownContent = '';\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownContent = fs.readFileSync(filePath, 'utf-8');\n } catch (e: any) {\n console.error(chalk.red(`파일 읽기 실패: ${e.message}`));\n process.exit(1);\n }\n } else if (options.content) {\n markdownContent = options.content;\n } else {\n console.error(chalk.red('오류: --content 또는 --file 옵션 중 하나는 필수입니다.'));\n process.exit(1);\n }\n\n const page = await api.createPage({\n spaceKey: options.space,\n title: options.title,\n body: mdToStorage.convert(markdownContent),\n parentId: options.parent\n });\n console.log(chalk.green(`페이지 생성 완료: ${page.title} (ID: ${page.id})`));\n console.log(`URL: ${page._links?.base}${page._links?.webui}`);\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n // --- Space Commands ---\n const spaceCmd = confluenceCmd.command('space').description('스페이스 관리');\n\n spaceCmd.command('list')\n .description('스페이스 목록 조회')\n .action(async () => {\n const client = initClient();\n const api = new ConfluenceSpaceApi(client);\n try {\n const spaces = await api.getSpaces();\n const table = new Table({\n head: ['Key', 'Name', 'Type', 'ID'],\n style: { head: ['cyan'] }\n });\n spaces.forEach(s => table.push([s.key, s.name, s.type, s.id.toString()]));\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`목록 조회 실패: ${e.message}`));\n }\n });\n\n // --- Search Commands ---\n confluenceCmd.command('search <cql>')\n .description('CQL 검색')\n .action(async (cql) => {\n const client = initClient();\n const api = new ConfluenceSearchApi(client);\n try {\n const result = await api.searchByCql(cql);\n console.log(chalk.bold(`검색 결과: ${result.size}건 (총 ${result.totalSize}건)`));\n const table = new Table({\n head: ['ID', 'Title', 'Space', 'URL'],\n style: { head: ['cyan'] }\n });\n result.results.forEach(p => table.push([\n p.id,\n p.title,\n p.space?.key || '',\n `${p._links?.base}${p._links?.webui}`\n ]));\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`검색 실패: ${e.message}`));\n }\n });\n}\n"],"mappings":"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","names":["program"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/confluence/commands/index.ts","../src/jira/commands/index.ts","../src/gitlab/commands/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registerConfluenceCommands } from './confluence/commands/index.js';\nimport { registerJiraCommands } from './jira/commands/index.js';\nimport { registerGitlabCommands } from './gitlab/commands/index.js';\nimport dotenv from 'dotenv';\n\n// Load environment variables\ndotenv.config();\n\nconst program = new Command();\n\nprogram\n .name('tdecollab')\n .description('TDE Collaboration CLI')\n .version('0.1.0');\n\n// Register module commands\nregisterConfluenceCommands(program);\nregisterJiraCommands(program);\nregisterGitlabCommands(program);\n\nprogram\n .command('mcp')\n .description('Run MCP Server')\n .action(async () => {\n const { runServer } = await import('./mcp/server.js');\n await runServer();\n });\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { ConfluenceContentApi } from '../api/content.js';\nimport { ConfluenceSpaceApi } from '../api/space.js';\nimport { ConfluenceSearchApi } from '../api/search.js';\nimport { ConfluenceLabelApi } from '../api/label.js';\nimport { createConfluenceClient } from '../api/client.js';\nimport { MarkdownToStorageConverter } from '../converters/md-to-storage.js';\nimport { StorageToMarkdownConverter } from '../converters/storage-to-md.js';\nimport { loadConfluenceConfig } from '../../common/config.js';\nimport { logger } from '../../common/logger.js';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function registerConfluenceCommands(program: Command) {\n const confluenceCmd = program.command('confluence')\n .description('Confluence 관리');\n\n // 공통 초기화 함수\n const initClient = () => {\n try {\n const config = loadConfluenceConfig();\n return createConfluenceClient(config);\n } catch (e: any) {\n console.error(chalk.red(`설정 로드 실패: ${e.message}`));\n process.exit(1);\n }\n };\n\n // --- Page Commands ---\n const pageCmd = confluenceCmd.command('page').description('페이지 관리');\n\n pageCmd.command('get <pageId>')\n .description('페이지 조회')\n .option('-r, --raw', 'Raw Storage Format 출력')\n .option('-q, --quiet', '메타데이터 생략')\n .option('-d, --download-images', '이미지 다운로드')\n .option('--image-dir <path>', '이미지 저장 디렉토리', './images')\n .option('-o, --output <file>', 'Markdown을 파일로 저장')\n .action(async (pageId, options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const config = loadConfluenceConfig();\n\n try {\n const page = await api.getPage(pageId);\n\n if (!options.quiet) {\n console.log(chalk.bold(`Title: ${page.title}`));\n console.log(chalk.gray(`ID: ${page.id}`));\n console.log(`Space: ${page.space?.name} (${page.space?.key})`);\n console.log(`URL: ${page._links?.base}${page._links?.webui}`);\n }\n\n let content = '';\n\n if (options.raw) {\n if (!options.quiet) console.log(chalk.dim('--- Content (Storage Format) ---'));\n if (page.body?.storage?.value) {\n content = page.body.storage.value;\n } else {\n if (!options.quiet) console.log(chalk.yellow('(No content)'));\n }\n } else {\n if (!options.quiet) console.log(chalk.dim('--- Content (Markdown) ---'));\n if (page.body?.storage?.value) {\n let imageUrlMap: Map<string, string> | undefined;\n\n // 이미지 다운로드 옵션이 활성화된 경우\n if (options.downloadImages) {\n const { ImageDownloader } = await import('../utils/image-downloader.js');\n const downloader = new ImageDownloader(api, {\n outputDir: path.resolve(process.cwd(), options.imageDir),\n pageId: page.id,\n baseUrl: config.baseUrl\n });\n\n console.log(chalk.blue('이미지 다운로드 중...'));\n imageUrlMap = await downloader.downloadAllImages(page.body.storage.value);\n }\n\n const storageToMd = new StorageToMarkdownConverter();\n content = storageToMd.convert(page.body.storage.value, imageUrlMap);\n } else {\n if (!options.quiet) console.log(chalk.yellow('(No content)'));\n }\n }\n\n // 파일로 저장 또는 콘솔 출력\n if (options.output) {\n const outputPath = path.resolve(process.cwd(), options.output);\n fs.writeFileSync(outputPath, content, 'utf-8');\n console.log(chalk.green(`파일 저장 완료: ${outputPath}`));\n } else {\n console.log(content);\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n pageCmd.command('create')\n .requiredOption('-s, --space <key>', '스페이스 키')\n .requiredOption('-t, --title <title>', '제목')\n .option('-c, --content <content>', '내용 (Markdown 텍스트)')\n .option('-f, --file <path>', '내용 파일 경로 (Markdown)')\n .option('-p, --parent <id>', '부모 페이지 ID')\n .description('페이지 생성')\n .action(async (options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const mdToStorage = new MarkdownToStorageConverter();\n\n try {\n let markdownContent = '';\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownContent = fs.readFileSync(filePath, 'utf-8');\n } catch (e: any) {\n console.error(chalk.red(`파일 읽기 실패: ${e.message}`));\n process.exit(1);\n }\n } else if (options.content) {\n markdownContent = options.content;\n } else {\n console.error(chalk.red('오류: --content 또는 --file 옵션 중 하나는 필수입니다.'));\n process.exit(1);\n }\n\n const page = await api.createPage({\n spaceKey: options.space,\n title: options.title,\n body: mdToStorage.convert(markdownContent),\n parentId: options.parent\n });\n console.log(chalk.green(`페이지 생성 완료: ${page.title} (ID: ${page.id})`));\n console.log(`URL: ${page._links?.base}${page._links?.webui}`);\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n // --- Space Commands ---\n const spaceCmd = confluenceCmd.command('space').description('스페이스 관리');\n\n spaceCmd.command('list')\n .description('스페이스 목록 조회')\n .action(async () => {\n const client = initClient();\n const api = new ConfluenceSpaceApi(client);\n try {\n const spaces = await api.getSpaces();\n const table = new Table({\n head: ['Key', 'Name', 'Type', 'ID'],\n style: { head: ['cyan'] }\n });\n spaces.forEach(s => table.push([s.key, s.name, s.type, s.id.toString()]));\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`목록 조회 실패: ${e.message}`));\n }\n });\n\n // --- Search Commands ---\n confluenceCmd.command('search <cql>')\n .description('CQL 검색')\n .action(async (cql) => {\n const client = initClient();\n const api = new ConfluenceSearchApi(client);\n try {\n const result = await api.searchByCql(cql);\n console.log(chalk.bold(`검색 결과: ${result.size}건 (총 ${result.totalSize}건)`));\n const table = new Table({\n head: ['ID', 'Title', 'Space', 'URL'],\n style: { head: ['cyan'] }\n });\n result.results.forEach(p => table.push([\n p.id,\n p.title,\n p.space?.key || '',\n `${p._links?.base}${p._links?.webui}`\n ]));\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`검색 실패: ${e.message}`));\n }\n });\n}\n","import { Command } from 'commander';\nimport { JiraIssueApi } from '../api/issue.js';\nimport { JiraSearchApi } from '../api/search.js';\nimport { JiraTransitionApi } from '../api/transition.js';\nimport { JiraCommentApi } from '../api/comment.js';\nimport { JiraProjectApi } from '../api/project.js';\nimport { createJiraClient } from '../api/client.js';\nimport { loadJiraConfig } from '../../common/config.js';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function registerJiraCommands(program: Command) {\n const jiraCmd = program.command('jira').description('JIRA 관리');\n\n const initClient = () => {\n try {\n const config = loadJiraConfig();\n return createJiraClient(config);\n } catch (e: any) {\n console.error(chalk.red(`설정 로드 실패: ${e.message}`));\n process.exit(1);\n }\n };\n\n // --- Issue Commands ---\n const issueCmd = jiraCmd.command('issue').description('이슈 관리');\n\n issueCmd\n .command('get <issueKey>')\n .description('이슈 조회')\n .action(async (issueKey) => {\n const client = initClient();\n const api = new JiraIssueApi(client);\n try {\n const issue = await api.getIssue(issueKey);\n const f = issue.fields;\n\n console.log(chalk.bold(`[${issue.key}] ${f.summary}`));\n console.log(chalk.gray(`Status: ${f.status?.name || 'N/A'}`));\n console.log(`Type: ${f.issuetype?.name || 'N/A'}`);\n console.log(`Priority: ${f.priority?.name || 'N/A'}`);\n console.log(`Assignee: ${f.assignee?.displayName || '미배정'}`);\n console.log(`Reporter: ${f.reporter?.displayName || 'N/A'}`);\n console.log(`Labels: ${f.labels?.join(', ') || '없음'}`);\n console.log(`Created: ${f.created || 'N/A'}`);\n console.log(`Updated: ${f.updated || 'N/A'}`);\n\n if (f.description) {\n console.log(chalk.dim('\\n--- Description ---'));\n console.log(f.description);\n }\n\n if (f.subtasks && f.subtasks.length > 0) {\n console.log(chalk.dim('\\n--- Subtasks ---'));\n f.subtasks.forEach((st) => {\n console.log(` - [${st.key}] ${st.fields.summary} (${st.fields.status.name})`);\n });\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n issueCmd\n .command('create')\n .requiredOption('-p, --project <key>', '프로젝트 키')\n .requiredOption('-s, --summary <summary>', '이슈 제목')\n .requiredOption('-t, --type <type>', '이슈 유형 (Task, Bug, Story 등)')\n .option('-d, --description <desc>', '이슈 설명')\n .option('-a, --assignee <name>', '담당자')\n .option('--priority <priority>', '우선순위')\n .option('-l, --labels <labels>', '라벨 (쉼표 구분)')\n .option('--parent <key>', '상위 이슈 키 (Sub-task)')\n .description('이슈 생성')\n .action(async (options) => {\n const client = initClient();\n const api = new JiraIssueApi(client);\n try {\n const issue = await api.createIssue({\n projectKey: options.project,\n summary: options.summary,\n issueType: options.type,\n description: options.description,\n assignee: options.assignee,\n priority: options.priority,\n labels: options.labels?.split(',').map((l: string) => l.trim()),\n parentKey: options.parent,\n });\n const config = loadJiraConfig();\n console.log(chalk.green(`이슈 생성 완료: ${issue.key}`));\n console.log(`URL: ${config.baseUrl}/browse/${issue.key}`);\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n issueCmd\n .command('update <issueKey>')\n .option('-s, --summary <summary>', '제목')\n .option('-d, --description <desc>', '설명')\n .option('-a, --assignee <name>', '담당자')\n .option('--priority <priority>', '우선순위')\n .option('-l, --labels <labels>', '라벨 (쉼표 구분)')\n .description('이슈 수정')\n .action(async (issueKey, options) => {\n const client = initClient();\n const api = new JiraIssueApi(client);\n try {\n await api.updateIssue(issueKey, {\n summary: options.summary,\n description: options.description,\n assignee: options.assignee,\n priority: options.priority,\n labels: options.labels?.split(',').map((l: string) => l.trim()),\n });\n console.log(chalk.green(`이슈 수정 완료: ${issueKey}`));\n } catch (e: any) {\n console.error(chalk.red(`수정 실패: ${e.message}`));\n }\n });\n\n issueCmd\n .command('transition <issueKey>')\n .option('-l, --list', '가능한 트랜지션 조회')\n .option('-t, --transition <id>', '트랜지션 실행')\n .description('이슈 상태 변경')\n .action(async (issueKey, options) => {\n const client = initClient();\n const api = new JiraTransitionApi(client);\n try {\n if (options.list || !options.transition) {\n const transitions = await api.getTransitions(issueKey);\n const table = new Table({\n head: ['ID', 'Name', 'To'],\n style: { head: ['cyan'] },\n });\n transitions.forEach((t) => table.push([t.id, t.name, t.to.name]));\n console.log(table.toString());\n } else {\n await api.doTransition(issueKey, options.transition);\n console.log(chalk.green(`트랜지션 완료: ${issueKey}`));\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- Search Command ---\n jiraCmd\n .command('search <jql>')\n .option('-n, --max <number>', '최대 결과 수', '20')\n .description('JQL 검색')\n .action(async (jql, options) => {\n const client = initClient();\n const api = new JiraSearchApi(client);\n try {\n const result = await api.searchByJql(jql, 0, parseInt(options.max));\n console.log(chalk.bold(`검색 결과: ${result.issues.length}건 (총 ${result.total}건)`));\n const table = new Table({\n head: ['Key', 'Summary', 'Status', 'Assignee'],\n style: { head: ['cyan'] },\n });\n result.issues.forEach((i) =>\n table.push([\n i.key,\n i.fields.summary.substring(0, 60),\n i.fields.status?.name || 'N/A',\n i.fields.assignee?.displayName || '미배정',\n ]),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`검색 실패: ${e.message}`));\n }\n });\n\n // --- Comment Commands ---\n const commentCmd = jiraCmd.command('comment').description('코멘트 관리');\n\n commentCmd\n .command('list <issueKey>')\n .description('코멘트 목록 조회')\n .action(async (issueKey) => {\n const client = initClient();\n const api = new JiraCommentApi(client);\n try {\n const result = await api.getComments(issueKey);\n result.comments.forEach((c) => {\n console.log(chalk.bold(`[${c.id}] ${c.author.displayName} (${c.created})`));\n console.log(c.body);\n console.log(chalk.dim('---'));\n });\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n commentCmd\n .command('add <issueKey> <body>')\n .description('코멘트 추가')\n .action(async (issueKey, body) => {\n const client = initClient();\n const api = new JiraCommentApi(client);\n try {\n const comment = await api.addComment(issueKey, body);\n console.log(chalk.green(`코멘트 추가 완료 (ID: ${comment.id})`));\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- Project Commands ---\n const projectCmd = jiraCmd.command('project').description('프로젝트 관리');\n\n projectCmd\n .command('list')\n .description('프로젝트 목록 조회')\n .action(async () => {\n const client = initClient();\n const api = new JiraProjectApi(client);\n try {\n const projects = await api.getProjects();\n const table = new Table({\n head: ['Key', 'Name', 'Lead'],\n style: { head: ['cyan'] },\n });\n projects.forEach((p) =>\n table.push([p.key, p.name, p.lead?.displayName || 'N/A']),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n projectCmd\n .command('get <projectKey>')\n .description('프로젝트 상세 조회')\n .action(async (projectKey) => {\n const client = initClient();\n const api = new JiraProjectApi(client);\n try {\n const project = await api.getProject(projectKey);\n console.log(chalk.bold(`${project.name} (${project.key})`));\n console.log(`Lead: ${project.lead?.displayName || 'N/A'}`);\n if (project.issueTypes) {\n console.log(\n `Issue Types: ${project.issueTypes.map((t) => t.name).join(', ')}`,\n );\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- Board Commands ---\n const boardCmd = jiraCmd.command('board').description('Agile 보드 관리');\n\n boardCmd\n .command('list')\n .option('-p, --project <key>', '프로젝트 키')\n .description('보드 목록 조회')\n .action(async (options) => {\n const client = initClient();\n const api = new JiraProjectApi(client);\n try {\n const result = await api.getBoards(options.project);\n const table = new Table({\n head: ['ID', 'Name', 'Type'],\n style: { head: ['cyan'] },\n });\n result.values.forEach((b) => table.push([b.id.toString(), b.name, b.type]));\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n boardCmd\n .command('sprints <boardId>')\n .option('-s, --state <state>', '상태 필터 (active, closed, future)')\n .description('스프린트 목록 조회')\n .action(async (boardId, options) => {\n const client = initClient();\n const api = new JiraProjectApi(client);\n try {\n const result = await api.getSprints(parseInt(boardId), options.state);\n const table = new Table({\n head: ['ID', 'Name', 'State', 'Goal'],\n style: { head: ['cyan'] },\n });\n result.values.forEach((s) =>\n table.push([s.id.toString(), s.name, s.state, s.goal || '']),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n}\n","import { Command } from 'commander';\nimport { GitlabProjectApi } from '../api/project.js';\nimport { GitlabMergeRequestApi } from '../api/merge-request.js';\nimport { GitlabPipelineApi } from '../api/pipeline.js';\nimport { GitlabBranchApi } from '../api/branch.js';\nimport { GitlabRepositoryApi } from '../api/repository.js';\nimport { createGitlabClient } from '../api/client.js';\nimport { loadGitlabConfig } from '../../common/config.js';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function registerGitlabCommands(program: Command) {\n const gitlabCmd = program.command('gitlab').description('GitLab 관리');\n\n const initClient = () => {\n try {\n const config = loadGitlabConfig();\n return createGitlabClient(config);\n } catch (e: any) {\n console.error(chalk.red(`설정 로드 실패: ${e.message}`));\n process.exit(1);\n }\n };\n\n // --- Project Commands ---\n const projectCmd = gitlabCmd.command('project').description('프로젝트 관리');\n\n projectCmd\n .command('list')\n .option('-s, --search <query>', '프로젝트명 검색')\n .option('--owned', '소유 프로젝트만')\n .option('--membership', '멤버십 프로젝트만')\n .description('프로젝트 목록 조회')\n .action(async (options) => {\n const client = initClient();\n const api = new GitlabProjectApi(client);\n try {\n const projects = await api.getProjects({\n search: options.search,\n owned: options.owned,\n membership: options.membership,\n });\n const table = new Table({\n head: ['ID', 'Name', 'Visibility', 'Default Branch', 'Last Activity'],\n style: { head: ['cyan'] },\n });\n projects.forEach((p) =>\n table.push([\n p.id.toString(),\n p.name_with_namespace,\n p.visibility,\n p.default_branch || 'N/A',\n p.last_activity_at?.substring(0, 10) || 'N/A',\n ]),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n projectCmd\n .command('get <projectId>')\n .description('프로젝트 상세 조회')\n .action(async (projectId) => {\n const client = initClient();\n const api = new GitlabProjectApi(client);\n try {\n const p = await api.getProject(parseInt(projectId));\n console.log(chalk.bold(p.name_with_namespace));\n console.log(`ID: ${p.id}`);\n console.log(`Path: ${p.path_with_namespace}`);\n console.log(`Default Branch: ${p.default_branch}`);\n console.log(`Visibility: ${p.visibility}`);\n console.log(`Web URL: ${p.web_url}`);\n console.log(`SSH URL: ${p.ssh_url_to_repo}`);\n console.log(`HTTP URL: ${p.http_url_to_repo}`);\n console.log(`Last Activity: ${p.last_activity_at}`);\n if (p.description) console.log(`Description: ${p.description}`);\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- MR Commands ---\n const mrCmd = gitlabCmd.command('mr').description('Merge Request 관리');\n\n mrCmd\n .command('list <projectId>')\n .option('-s, --state <state>', '상태 필터 (opened/closed/merged/all)', 'opened')\n .option('--scope <scope>', '범위 (created_by_me/assigned_to_me)')\n .description('MR 목록 조회')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n const mrs = await api.getMergeRequests(parseInt(projectId), {\n state: options.state,\n scope: options.scope,\n });\n const table = new Table({\n head: ['IID', 'Title', 'State', 'Source → Target', 'Author'],\n style: { head: ['cyan'] },\n });\n mrs.forEach((m) =>\n table.push([\n `!${m.iid}`,\n m.title.substring(0, 50),\n m.state,\n `${m.source_branch} → ${m.target_branch}`,\n m.author?.name || 'N/A',\n ]),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n mrCmd\n .command('get <projectId> <mrIid>')\n .option('-c, --changes', '변경 파일 포함')\n .description('MR 상세 조회')\n .action(async (projectId, mrIid, options) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n const mr = options.changes\n ? await api.getMergeRequestChanges(parseInt(projectId), parseInt(mrIid))\n : await api.getMergeRequest(parseInt(projectId), parseInt(mrIid));\n\n console.log(chalk.bold(`[!${mr.iid}] ${mr.title}`));\n console.log(`State: ${mr.state}`);\n console.log(`Source: ${mr.source_branch} → Target: ${mr.target_branch}`);\n console.log(`Author: ${mr.author?.name || 'N/A'}`);\n console.log(`Assignee: ${mr.assignee?.name || '미배정'}`);\n console.log(`Merge Status: ${mr.merge_status}`);\n console.log(`Has Conflicts: ${mr.has_conflicts}`);\n console.log(`Pipeline: ${mr.pipeline?.status || 'N/A'}`);\n console.log(`URL: ${mr.web_url}`);\n\n if (mr.description) {\n console.log(chalk.dim('\\n--- Description ---'));\n console.log(mr.description);\n }\n\n if (mr.changes && mr.changes.length > 0) {\n console.log(chalk.dim(`\\n--- Changes (${mr.changes.length}개 파일) ---`));\n mr.changes.forEach((c) => {\n const prefix = c.new_file\n ? '[NEW]'\n : c.deleted_file\n ? '[DEL]'\n : c.renamed_file\n ? '[REN]'\n : '[MOD]';\n console.log(` ${prefix} ${c.new_path}`);\n });\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n mrCmd\n .command('create <projectId>')\n .requiredOption('--source <branch>', '소스 브랜치')\n .requiredOption('--target <branch>', '타겟 브랜치')\n .requiredOption('--title <text>', 'MR 제목')\n .option('-d, --description <text>', 'MR 설명')\n .description('MR 생성')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n const mr = await api.createMergeRequest(parseInt(projectId), {\n source_branch: options.source,\n target_branch: options.target,\n title: options.title,\n description: options.description,\n });\n console.log(chalk.green(`MR 생성 완료: !${mr.iid}`));\n console.log(`URL: ${mr.web_url}`);\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n mrCmd\n .command('merge <projectId> <mrIid>')\n .option('--squash', '스쿼시 머지')\n .option('--remove-source-branch', '소스 브랜치 삭제')\n .description('MR 머지')\n .action(async (projectId, mrIid, options) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n const mr = await api.mergeMergeRequest(parseInt(projectId), parseInt(mrIid), {\n squash: options.squash,\n should_remove_source_branch: options.removeSourceBranch,\n });\n console.log(chalk.green(`MR !${mrIid} 머지 완료`));\n console.log(`State: ${mr.state}`);\n } catch (e: any) {\n console.error(chalk.red(`머지 실패: ${e.message}`));\n }\n });\n\n mrCmd\n .command('close <projectId> <mrIid>')\n .description('MR 닫기')\n .action(async (projectId, mrIid) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n await api.updateMergeRequest(parseInt(projectId), parseInt(mrIid), {\n state_event: 'close',\n });\n console.log(chalk.green(`MR !${mrIid} 닫기 완료`));\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n mrCmd\n .command('comment <projectId> <mrIid>')\n .requiredOption('-b, --body <text>', '코멘트 내용')\n .description('MR 코멘트 추가')\n .action(async (projectId, mrIid, options) => {\n const client = initClient();\n const api = new GitlabMergeRequestApi(client);\n try {\n const note = await api.addMergeRequestNote(\n parseInt(projectId),\n parseInt(mrIid),\n options.body,\n );\n console.log(chalk.green(`코멘트 추가 완료 (ID: ${note.id})`));\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- Pipeline Commands ---\n const pipelineCmd = gitlabCmd.command('pipeline').description('파이프라인 관리');\n\n pipelineCmd\n .command('list <projectId>')\n .option('-s, --status <status>', '상태 필터')\n .option('-r, --ref <branch>', '브랜치/태그 필터')\n .description('파이프라인 목록 조회')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabPipelineApi(client);\n try {\n const pipelines = await api.getPipelines(parseInt(projectId), {\n status: options.status,\n ref: options.ref,\n });\n const table = new Table({\n head: ['ID', 'Status', 'Ref', 'SHA', 'Created'],\n style: { head: ['cyan'] },\n });\n pipelines.forEach((p) =>\n table.push([\n p.id.toString(),\n p.status,\n p.ref,\n p.sha.substring(0, 8),\n p.created_at?.substring(0, 10) || 'N/A',\n ]),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n pipelineCmd\n .command('get <projectId> <pipelineId>')\n .option('-j, --jobs', '작업 목록 포함')\n .description('파이프라인 상세 조회')\n .action(async (projectId, pipelineId, options) => {\n const client = initClient();\n const api = new GitlabPipelineApi(client);\n try {\n const p = await api.getPipeline(parseInt(projectId), parseInt(pipelineId));\n console.log(chalk.bold(`Pipeline #${p.id}`));\n console.log(`Status: ${p.status}`);\n console.log(`Ref: ${p.ref}`);\n console.log(`SHA: ${p.sha}`);\n console.log(`Duration: ${p.duration ? p.duration + 's' : 'N/A'}`);\n console.log(`URL: ${p.web_url}`);\n\n if (options.jobs) {\n const jobs = await api.getPipelineJobs(\n parseInt(projectId),\n parseInt(pipelineId),\n );\n console.log(chalk.dim(`\\n--- Jobs (${jobs.length}개) ---`));\n const table = new Table({\n head: ['Stage', 'Name', 'Status', 'Duration'],\n style: { head: ['cyan'] },\n });\n jobs.forEach((j) =>\n table.push([\n j.stage,\n j.name,\n j.status,\n j.duration ? j.duration + 's' : 'N/A',\n ]),\n );\n console.log(table.toString());\n }\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n // --- Branch Commands ---\n const branchCmd = gitlabCmd.command('branch').description('브랜치 관리');\n\n branchCmd\n .command('list <projectId>')\n .option('-s, --search <query>', '검색 키워드')\n .description('브랜치 목록 조회')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabBranchApi(client);\n try {\n const branches = await api.getBranches(parseInt(projectId), {\n search: options.search,\n });\n const table = new Table({\n head: ['Name', 'Commit', 'Message', 'Protected', 'Default'],\n style: { head: ['cyan'] },\n });\n branches.forEach((b) =>\n table.push([\n b.name,\n b.commit.short_id,\n b.commit.message.split('\\n')[0].substring(0, 40),\n b.protected ? 'Yes' : 'No',\n b.default ? 'Yes' : 'No',\n ]),\n );\n console.log(table.toString());\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n branchCmd\n .command('get <projectId> <branchName>')\n .description('브랜치 상세 조회')\n .action(async (projectId, branchName) => {\n const client = initClient();\n const api = new GitlabBranchApi(client);\n try {\n const b = await api.getBranch(parseInt(projectId), branchName);\n console.log(chalk.bold(b.name));\n console.log(`Default: ${b.default}`);\n console.log(`Protected: ${b.protected}`);\n console.log(`Merged: ${b.merged}`);\n console.log(`Commit: ${b.commit.id}`);\n console.log(`Message: ${b.commit.message}`);\n console.log(`Author: ${b.commit.author_name}`);\n console.log(`Date: ${b.commit.authored_date}`);\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n branchCmd\n .command('create <projectId>')\n .requiredOption('-n, --name <branch>', '브랜치 이름')\n .requiredOption('-r, --ref <ref>', '기준 ref')\n .description('브랜치 생성')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabBranchApi(client);\n try {\n const b = await api.createBranch(\n parseInt(projectId),\n options.name,\n options.ref,\n );\n console.log(chalk.green(`브랜치 생성 완료: ${b.name}`));\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n branchCmd\n .command('delete <projectId> <branchName>')\n .description('브랜치 삭제')\n .action(async (projectId, branchName) => {\n const client = initClient();\n const api = new GitlabBranchApi(client);\n try {\n await api.deleteBranch(parseInt(projectId), branchName);\n console.log(chalk.green(`브랜치 삭제 완료: ${branchName}`));\n } catch (e: any) {\n console.error(chalk.red(`삭제 실패: ${e.message}`));\n }\n });\n\n // --- File Commands ---\n const fileCmd = gitlabCmd.command('file').description('파일 관리');\n\n fileCmd\n .command('get <projectId> <filePath>')\n .option('-r, --ref <ref>', '브랜치/태그/커밋')\n .description('파일 내용 조회')\n .action(async (projectId, filePath, options) => {\n const client = initClient();\n const api = new GitlabRepositoryApi(client);\n try {\n const file = await api.getFile(parseInt(projectId), filePath, options.ref);\n console.log(chalk.bold(file.file_path));\n console.log(chalk.gray(`Size: ${file.size} bytes | Ref: ${file.ref}`));\n console.log(chalk.dim('---'));\n console.log(file.content);\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n\n fileCmd\n .command('tree <projectId>')\n .option('-p, --path <dir>', '디렉토리 경로')\n .option('-r, --ref <ref>', '브랜치/태그')\n .option('--recursive', '재귀 조회')\n .description('디렉토리 트리 조회')\n .action(async (projectId, options) => {\n const client = initClient();\n const api = new GitlabRepositoryApi(client);\n try {\n const entries = await api.getTree(parseInt(projectId), {\n path: options.path,\n ref: options.ref,\n recursive: options.recursive,\n });\n entries.forEach((e) => {\n const icon = e.type === 'tree' ? '📁' : '📄';\n console.log(`${icon} ${e.path}`);\n });\n } catch (e: any) {\n console.error(chalk.red(`Error: ${e.message}`));\n }\n });\n}\n"],"mappings":"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","names":["program","chalk","Table","program","chalk","Table","program"]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-CNARZOBV.js
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfluenceContentApi,
|
|
3
|
-
ConfluenceSearchApi,
|
|
4
|
-
ConfluenceSpaceApi,
|
|
5
|
-
MarkdownToStorageConverter,
|
|
6
|
-
StorageToMarkdownConverter,
|
|
7
|
-
createConfluenceClient,
|
|
8
|
-
loadConfluenceConfig
|
|
9
|
-
} from "./chunk-K5LQBRHJ.js";
|
|
10
|
-
import {
|
|
11
|
-
logger
|
|
12
|
-
} from "./chunk-SJ7KPK6Q.js";
|
|
13
|
-
|
|
14
|
-
// src/mcp/server.ts
|
|
15
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
-
|
|
18
|
-
// src/confluence/tools/index.ts
|
|
19
|
-
import { z } from "zod";
|
|
20
|
-
|
|
21
|
-
// src/confluence/api/label.ts
|
|
22
|
-
var ConfluenceLabelApi = class {
|
|
23
|
-
constructor(client) {
|
|
24
|
-
this.client = client;
|
|
25
|
-
}
|
|
26
|
-
async getLabels(pageId) {
|
|
27
|
-
const response = await this.client.get(`/rest/api/content/${pageId}/label`);
|
|
28
|
-
return response.data.results;
|
|
29
|
-
}
|
|
30
|
-
async addLabels(pageId, labels) {
|
|
31
|
-
const data = labels.map((name) => ({ prefix: "global", name }));
|
|
32
|
-
await this.client.post(`/rest/api/content/${pageId}/label`, data);
|
|
33
|
-
}
|
|
34
|
-
async removeLabel(pageId, labelName) {
|
|
35
|
-
await this.client.delete(`/rest/api/content/${pageId}/label`, {
|
|
36
|
-
params: { name: labelName }
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// src/confluence/tools/index.ts
|
|
42
|
-
function registerConfluenceTools(server) {
|
|
43
|
-
try {
|
|
44
|
-
const config = loadConfluenceConfig();
|
|
45
|
-
const client = createConfluenceClient(config);
|
|
46
|
-
const contentApi = new ConfluenceContentApi(client);
|
|
47
|
-
const spaceApi = new ConfluenceSpaceApi(client);
|
|
48
|
-
const searchApi = new ConfluenceSearchApi(client);
|
|
49
|
-
const labelApi = new ConfluenceLabelApi(client);
|
|
50
|
-
const mdToStorage = new MarkdownToStorageConverter();
|
|
51
|
-
const storageToMd = new StorageToMarkdownConverter();
|
|
52
|
-
server.tool(
|
|
53
|
-
"confluence_get_page",
|
|
54
|
-
"TDE Confluence \uD398\uC774\uC9C0 \uC0C1\uC138 \uC870\uD68C. \uD398\uC774\uC9C0 \uB0B4\uC6A9\uC744 Markdown\uC73C\uB85C \uBCC0\uD658\uD558\uC5EC \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
55
|
-
{
|
|
56
|
-
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
57
|
-
downloadImages: z.boolean().optional().describe("\uC774\uBBF8\uC9C0 \uB2E4\uC6B4\uB85C\uB4DC \uC5EC\uBD80"),
|
|
58
|
-
imageDir: z.string().optional().describe("\uC774\uBBF8\uC9C0 \uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uAE30\uBCF8\uAC12: ./images)")
|
|
59
|
-
},
|
|
60
|
-
async ({ pageId, downloadImages, imageDir }) => {
|
|
61
|
-
const page = await contentApi.getPage(pageId);
|
|
62
|
-
let md = "";
|
|
63
|
-
let imageInfo = "";
|
|
64
|
-
if (page.body?.storage?.value) {
|
|
65
|
-
let imageUrlMap;
|
|
66
|
-
if (downloadImages) {
|
|
67
|
-
const { ImageDownloader } = await import("./image-downloader-D57KFAIQ.js");
|
|
68
|
-
const downloader = new ImageDownloader(contentApi, {
|
|
69
|
-
outputDir: imageDir || "./images",
|
|
70
|
-
pageId: page.id,
|
|
71
|
-
baseUrl: config.baseUrl
|
|
72
|
-
});
|
|
73
|
-
imageUrlMap = await downloader.downloadAllImages(page.body.storage.value);
|
|
74
|
-
imageInfo = `
|
|
75
|
-
|
|
76
|
-
\uB2E4\uC6B4\uB85C\uB4DC\uB41C \uC774\uBBF8\uC9C0: ${imageUrlMap.size}\uAC1C`;
|
|
77
|
-
}
|
|
78
|
-
md = storageToMd.convert(page.body.storage.value, imageUrlMap);
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
content: [
|
|
82
|
-
{
|
|
83
|
-
type: "text",
|
|
84
|
-
text: `Title: ${page.title}
|
|
85
|
-
ID: ${page.id}
|
|
86
|
-
Space: ${page.space?.name} (${page.space?.key})
|
|
87
|
-
URL: ${page._links?.base}${page._links?.webui}${imageInfo}
|
|
88
|
-
|
|
89
|
-
${md}`
|
|
90
|
-
}
|
|
91
|
-
]
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
server.tool(
|
|
96
|
-
"confluence_create_page",
|
|
97
|
-
"TDE Confluence\uC5D0 \uC0C8 \uD398\uC774\uC9C0\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4. Markdown \uD615\uC2DD\uC758 \uB0B4\uC6A9\uC744 Confluence Storage Format\uC73C\uB85C \uC790\uB3D9 \uBCC0\uD658\uD569\uB2C8\uB2E4.",
|
|
98
|
-
{
|
|
99
|
-
spaceKey: z.string().describe("\uC2A4\uD398\uC774\uC2A4 \uD0A4"),
|
|
100
|
-
title: z.string().describe("\uD398\uC774\uC9C0 \uC81C\uBAA9"),
|
|
101
|
-
content: z.string().describe("\uD398\uC774\uC9C0 \uB0B4\uC6A9 (Markdown)"),
|
|
102
|
-
parentId: z.string().optional().describe("\uBD80\uBAA8 \uD398\uC774\uC9C0 ID"),
|
|
103
|
-
labels: z.array(z.string()).optional().describe("\uB77C\uBCA8 \uBAA9\uB85D")
|
|
104
|
-
},
|
|
105
|
-
async ({ spaceKey, title, content, parentId, labels }) => {
|
|
106
|
-
const storageBody = mdToStorage.convert(content);
|
|
107
|
-
const page = await contentApi.createPage({
|
|
108
|
-
spaceKey,
|
|
109
|
-
title,
|
|
110
|
-
body: storageBody,
|
|
111
|
-
parentId,
|
|
112
|
-
labels
|
|
113
|
-
});
|
|
114
|
-
return {
|
|
115
|
-
content: [
|
|
116
|
-
{
|
|
117
|
-
type: "text",
|
|
118
|
-
text: `\uD398\uC774\uC9C0 \uC0DD\uC131 \uC131\uACF5: ${page.title} (ID: ${page.id})
|
|
119
|
-
URL: ${page._links?.base}${page._links?.webui}`
|
|
120
|
-
}
|
|
121
|
-
]
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
);
|
|
125
|
-
server.tool(
|
|
126
|
-
"confluence_update_page",
|
|
127
|
-
"TDE Confluence \uD398\uC774\uC9C0\uB97C \uC218\uC815\uD569\uB2C8\uB2E4. Markdown \uD615\uC2DD\uC758 \uB0B4\uC6A9\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
128
|
-
{
|
|
129
|
-
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
130
|
-
title: z.string().describe("\uD398\uC774\uC9C0 \uC81C\uBAA9"),
|
|
131
|
-
content: z.string().describe("\uD398\uC774\uC9C0 \uB0B4\uC6A9 (Markdown)"),
|
|
132
|
-
version: z.number().describe("\uD604\uC7AC \uD398\uC774\uC9C0 \uBC84\uC804 (\uCDA9\uB3CC \uBC29\uC9C0\uC6A9)")
|
|
133
|
-
},
|
|
134
|
-
async ({ pageId, title, content, version }) => {
|
|
135
|
-
const storageBody = mdToStorage.convert(content);
|
|
136
|
-
const page = await contentApi.updatePage({
|
|
137
|
-
id: pageId,
|
|
138
|
-
title,
|
|
139
|
-
body: storageBody,
|
|
140
|
-
version
|
|
141
|
-
});
|
|
142
|
-
return {
|
|
143
|
-
content: [
|
|
144
|
-
{
|
|
145
|
-
type: "text",
|
|
146
|
-
text: `\uD398\uC774\uC9C0 \uC218\uC815 \uC131\uACF5: ${page.title} (Version: ${page.version?.number})`
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
server.tool(
|
|
153
|
-
"confluence_search_pages",
|
|
154
|
-
"TDE Confluence\uC5D0\uC11C \uD398\uC774\uC9C0\uB97C \uAC80\uC0C9\uD569\uB2C8\uB2E4. CQL(Confluence Query Language)\uC744 \uC0AC\uC6A9\uD558\uC5EC \uACE0\uAE09 \uAC80\uC0C9\uC774 \uAC00\uB2A5\uD569\uB2C8\uB2E4.",
|
|
155
|
-
{
|
|
156
|
-
cql: z.string().describe('Confluence Query Language (\uC608: title ~ "guide")'),
|
|
157
|
-
limit: z.number().default(10).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
158
|
-
},
|
|
159
|
-
async ({ cql, limit }) => {
|
|
160
|
-
const result = await searchApi.searchByCql(cql, 0, limit);
|
|
161
|
-
const summary = result.results.map((p) => `- [${p.id}] ${p.title} (Space: ${p.space?.key})`).join("\n");
|
|
162
|
-
return {
|
|
163
|
-
content: [
|
|
164
|
-
{
|
|
165
|
-
type: "text",
|
|
166
|
-
text: `\uAC80\uC0C9 \uACB0\uACFC (${result.size}/${result.totalSize}):
|
|
167
|
-
${summary}`
|
|
168
|
-
}
|
|
169
|
-
]
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
);
|
|
173
|
-
server.tool(
|
|
174
|
-
"confluence_get_spaces",
|
|
175
|
-
"TDE Confluence\uC758 \uC2A4\uD398\uC774\uC2A4 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
176
|
-
{
|
|
177
|
-
limit: z.number().default(20).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
178
|
-
},
|
|
179
|
-
async ({ limit }) => {
|
|
180
|
-
const spaces = await spaceApi.getSpaces("global", 0, limit);
|
|
181
|
-
const summary = spaces.map((s) => `- [${s.key}] ${s.name}`).join("\n");
|
|
182
|
-
return {
|
|
183
|
-
content: [{ type: "text", text: `\uC2A4\uD398\uC774\uC2A4 \uBAA9\uB85D:
|
|
184
|
-
${summary}` }]
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
);
|
|
188
|
-
server.tool(
|
|
189
|
-
"confluence_delete_page",
|
|
190
|
-
"TDE Confluence \uD398\uC774\uC9C0\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4.",
|
|
191
|
-
{
|
|
192
|
-
pageId: z.string().describe("\uD398\uC774\uC9C0 ID")
|
|
193
|
-
},
|
|
194
|
-
async ({ pageId }) => {
|
|
195
|
-
await contentApi.deletePage(pageId);
|
|
196
|
-
return {
|
|
197
|
-
content: [
|
|
198
|
-
{
|
|
199
|
-
type: "text",
|
|
200
|
-
text: `\uD398\uC774\uC9C0 \uC0AD\uC81C \uC131\uACF5 (ID: ${pageId})`
|
|
201
|
-
}
|
|
202
|
-
]
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
);
|
|
206
|
-
server.tool(
|
|
207
|
-
"confluence_get_page_tree",
|
|
208
|
-
"TDE Confluence \uD398\uC774\uC9C0\uC758 \uD558\uC704 \uD398\uC774\uC9C0(\uC790\uC2DD \uD398\uC774\uC9C0) \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
209
|
-
{
|
|
210
|
-
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
211
|
-
limit: z.number().default(20).describe("\uACB0\uACFC \uAC1C\uC218 \uC81C\uD55C")
|
|
212
|
-
},
|
|
213
|
-
async ({ pageId, limit }) => {
|
|
214
|
-
const children = await contentApi.getChildPages(pageId, 0, limit);
|
|
215
|
-
const summary = children.map((p) => `- [${p.id}] ${p.title}`).join("\n");
|
|
216
|
-
return {
|
|
217
|
-
content: [
|
|
218
|
-
{
|
|
219
|
-
type: "text",
|
|
220
|
-
text: `\uC790\uC2DD \uD398\uC774\uC9C0 \uBAA9\uB85D (${children.length}):
|
|
221
|
-
${summary}`
|
|
222
|
-
}
|
|
223
|
-
]
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
);
|
|
227
|
-
server.tool(
|
|
228
|
-
"confluence_manage_labels",
|
|
229
|
-
"TDE Confluence \uD398\uC774\uC9C0\uC758 \uB77C\uBCA8\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4. \uB77C\uBCA8 \uC870\uD68C, \uCD94\uAC00, \uC0AD\uC81C \uAE30\uB2A5\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.",
|
|
230
|
-
{
|
|
231
|
-
pageId: z.string().describe("\uD398\uC774\uC9C0 ID"),
|
|
232
|
-
action: z.enum(["list", "add", "remove"]).describe("\uC791\uC5C5 \uC720\uD615"),
|
|
233
|
-
labels: z.array(z.string()).optional().describe("\uCD94\uAC00\uD560 \uB77C\uBCA8 \uBAA9\uB85D (add \uC791\uC5C5 \uC2DC \uD544\uC218)"),
|
|
234
|
-
label: z.string().optional().describe("\uC0AD\uC81C\uD560 \uB77C\uBCA8 (remove \uC791\uC5C5 \uC2DC \uD544\uC218)")
|
|
235
|
-
},
|
|
236
|
-
async ({ pageId, action, labels, label }) => {
|
|
237
|
-
if (action === "list") {
|
|
238
|
-
const result = await labelApi.getLabels(pageId);
|
|
239
|
-
const summary = result.map((l) => l.name).join(", ");
|
|
240
|
-
return {
|
|
241
|
-
content: [{ type: "text", text: `\uB77C\uBCA8 \uBAA9\uB85D: ${summary}` }]
|
|
242
|
-
};
|
|
243
|
-
} else if (action === "add") {
|
|
244
|
-
if (!labels || labels.length === 0) {
|
|
245
|
-
throw new Error("\uB77C\uBCA8 \uBAA9\uB85D\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694.");
|
|
246
|
-
}
|
|
247
|
-
await labelApi.addLabels(pageId, labels);
|
|
248
|
-
return {
|
|
249
|
-
content: [{ type: "text", text: `\uB77C\uBCA8 \uCD94\uAC00 \uC131\uACF5: ${labels.join(", ")}` }]
|
|
250
|
-
};
|
|
251
|
-
} else if (action === "remove") {
|
|
252
|
-
if (!label) {
|
|
253
|
-
throw new Error("\uC0AD\uC81C\uD560 \uB77C\uBCA8\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694.");
|
|
254
|
-
}
|
|
255
|
-
await labelApi.removeLabel(pageId, label);
|
|
256
|
-
return {
|
|
257
|
-
content: [{ type: "text", text: `\uB77C\uBCA8 \uC0AD\uC81C \uC131\uACF5: ${label}` }]
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
return { content: [] };
|
|
261
|
-
}
|
|
262
|
-
);
|
|
263
|
-
server.tool(
|
|
264
|
-
"confluence_convert_content",
|
|
265
|
-
"TDE Confluence \uCEE8\uD150\uCE20 \uD3EC\uB9F7\uC744 \uBCC0\uD658\uD569\uB2C8\uB2E4. Markdown\uACFC Confluence Storage Format \uAC04 \uC591\uBC29\uD5A5 \uBCC0\uD658\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4.",
|
|
266
|
-
{
|
|
267
|
-
content: z.string().describe("\uBCC0\uD658\uD560 \uCEE8\uD150\uCE20"),
|
|
268
|
-
format: z.enum(["storage_to_markdown", "markdown_to_storage"]).describe("\uBCC0\uD658 \uBC29\uD5A5")
|
|
269
|
-
},
|
|
270
|
-
async ({ content, format }) => {
|
|
271
|
-
let result = "";
|
|
272
|
-
if (format === "storage_to_markdown") {
|
|
273
|
-
result = storageToMd.convert(content);
|
|
274
|
-
} else {
|
|
275
|
-
result = mdToStorage.convert(content);
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
content: [{ type: "text", text: result }]
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
} catch (error) {
|
|
283
|
-
logger.warn(`Confluence \uC124\uC815 \uB85C\uB4DC \uC2E4\uD328 \uB610\uB294 \uB3C4\uAD6C \uB4F1\uB85D \uC911 \uC624\uB958 \uBC1C\uC0DD: ${error.message}`);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// src/mcp/server.ts
|
|
288
|
-
async function runServer() {
|
|
289
|
-
try {
|
|
290
|
-
const server = new McpServer({
|
|
291
|
-
name: "TDE Collab",
|
|
292
|
-
version: "1.0.0",
|
|
293
|
-
description: "TDE \uD3EC\uD138(Confluence, JIRA, GitLab) \uD1B5\uD569 \uB3C4\uAD6C. TDE Confluence \uD398\uC774\uC9C0 \uAD00\uB9AC, \uAC80\uC0C9, \uD3B8\uC9D1 \uAE30\uB2A5\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4."
|
|
294
|
-
});
|
|
295
|
-
registerConfluenceTools(server);
|
|
296
|
-
const transport = new StdioServerTransport();
|
|
297
|
-
await server.connect(transport);
|
|
298
|
-
logger.info("TDE Collab MCP Server running on stdio");
|
|
299
|
-
} catch (error) {
|
|
300
|
-
logger.error(`Fatal error in MCP Server: ${error}`);
|
|
301
|
-
process.exit(1);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export {
|
|
306
|
-
runServer
|
|
307
|
-
};
|
|
308
|
-
//# sourceMappingURL=chunk-CNARZOBV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/server.ts","../src/confluence/tools/index.ts","../src/confluence/api/label.ts"],"sourcesContent":["\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerConfluenceTools } from '../confluence/tools/index.js';\nimport { logger } from '../common/logger.js';\n\nexport async function runServer() {\n try {\n const server = new McpServer({\n name: 'TDE Collab',\n version: '1.0.0',\n description: 'TDE 포털(Confluence, JIRA, GitLab) 통합 도구. TDE Confluence 페이지 관리, 검색, 편집 기능을 제공합니다.',\n });\n\n // Confluence 도구 등록\n registerConfluenceTools(server);\n\n // Stdio 전송 계층 연결\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n logger.info('TDE Collab MCP Server running on stdio');\n } catch (error) {\n logger.error(`Fatal error in MCP Server: ${error}`);\n process.exit(1);\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { ConfluenceContentApi } from '../api/content.js';\nimport { ConfluenceSpaceApi } from '../api/space.js';\nimport { ConfluenceSearchApi } from '../api/search.js';\nimport { ConfluenceLabelApi } from '../api/label.js';\nimport { createConfluenceClient } from '../api/client.js';\nimport { MarkdownToStorageConverter } from '../converters/md-to-storage.js';\nimport { StorageToMarkdownConverter } from '../converters/storage-to-md.js';\nimport { loadConfluenceConfig } from '../../common/config.js';\nimport { logger } from '../../common/logger.js';\n\nexport function registerConfluenceTools(server: McpServer) {\n try {\n const config = loadConfluenceConfig();\n const client = createConfluenceClient(config);\n\n const contentApi = new ConfluenceContentApi(client);\n const spaceApi = new ConfluenceSpaceApi(client);\n const searchApi = new ConfluenceSearchApi(client);\n const labelApi = new ConfluenceLabelApi(client);\n\n const mdToStorage = new MarkdownToStorageConverter();\n const storageToMd = new StorageToMarkdownConverter();\n\n // Tools\n\n server.tool(\n 'confluence_get_page',\n 'TDE Confluence 페이지 상세 조회. 페이지 내용을 Markdown으로 변환하여 반환합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n downloadImages: z.boolean().optional().describe('이미지 다운로드 여부'),\n imageDir: z.string().optional().describe('이미지 저장 디렉토리 (기본값: ./images)'),\n },\n async ({ pageId, downloadImages, imageDir }) => {\n const page = await contentApi.getPage(pageId);\n\n let md = '';\n let imageInfo = '';\n\n if (page.body?.storage?.value) {\n let imageUrlMap: Map<string, string> | undefined;\n\n // 이미지 다운로드 옵션이 활성화된 경우\n if (downloadImages) {\n const { ImageDownloader } = await import('../utils/image-downloader.js');\n const downloader = new ImageDownloader(contentApi, {\n outputDir: imageDir || './images',\n pageId: page.id,\n baseUrl: config.baseUrl\n });\n\n imageUrlMap = await downloader.downloadAllImages(page.body.storage.value);\n imageInfo = `\\n\\n다운로드된 이미지: ${imageUrlMap.size}개`;\n }\n\n md = storageToMd.convert(page.body.storage.value, imageUrlMap);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: `Title: ${page.title}\\nID: ${page.id}\\nSpace: ${page.space?.name} (${page.space?.key})\\nURL: ${page._links?.base}${page._links?.webui}${imageInfo}\\n\\n${md}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_create_page',\n 'TDE Confluence에 새 페이지를 생성합니다. Markdown 형식의 내용을 Confluence Storage Format으로 자동 변환합니다.',\n {\n spaceKey: z.string().describe('스페이스 키'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n parentId: z.string().optional().describe('부모 페이지 ID'),\n labels: z.array(z.string()).optional().describe('라벨 목록'),\n },\n async ({ spaceKey, title, content, parentId, labels }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.createPage({\n spaceKey,\n title,\n body: storageBody,\n parentId,\n labels\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 생성 성공: ${page.title} (ID: ${page.id})\\nURL: ${page._links?.base}${page._links?.webui}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_update_page',\n 'TDE Confluence 페이지를 수정합니다. Markdown 형식의 내용으로 업데이트할 수 있습니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n title: z.string().describe('페이지 제목'),\n content: z.string().describe('페이지 내용 (Markdown)'),\n version: z.number().describe('현재 페이지 버전 (충돌 방지용)'),\n },\n async ({ pageId, title, content, version }) => {\n const storageBody = mdToStorage.convert(content);\n const page = await contentApi.updatePage({\n id: pageId,\n title,\n body: storageBody,\n version\n });\n\n return {\n content: [\n {\n type: 'text',\n text: `페이지 수정 성공: ${page.title} (Version: ${page.version?.number})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_search_pages',\n 'TDE Confluence에서 페이지를 검색합니다. CQL(Confluence Query Language)을 사용하여 고급 검색이 가능합니다.',\n {\n cql: z.string().describe('Confluence Query Language (예: title ~ \"guide\")'),\n limit: z.number().default(10).describe('결과 개수 제한'),\n },\n async ({ cql, limit }) => {\n const result = await searchApi.searchByCql(cql, 0, limit);\n const summary = result.results.map(p => `- [${p.id}] ${p.title} (Space: ${p.space?.key})`).join('\\n');\n\n return {\n content: [\n {\n type: 'text',\n text: `검색 결과 (${result.size}/${result.totalSize}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_spaces',\n 'TDE Confluence의 스페이스 목록을 조회합니다.',\n {\n limit: z.number().default(20).describe('결과 개수 제한')\n },\n async ({ limit }) => {\n const spaces = await spaceApi.getSpaces('global', 0, limit);\n const summary = spaces.map(s => `- [${s.key}] ${s.name}`).join('\\n');\n return {\n content: [{ type: 'text', text: `스페이스 목록:\\n${summary}` }]\n };\n }\n );\n\n server.tool(\n 'confluence_delete_page',\n 'TDE Confluence 페이지를 삭제합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n },\n async ({ pageId }) => {\n await contentApi.deletePage(pageId);\n return {\n content: [\n {\n type: 'text',\n text: `페이지 삭제 성공 (ID: ${pageId})`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_get_page_tree',\n 'TDE Confluence 페이지의 하위 페이지(자식 페이지) 목록을 조회합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n limit: z.number().default(20).describe('결과 개수 제한'),\n },\n async ({ pageId, limit }) => {\n const children = await contentApi.getChildPages(pageId, 0, limit);\n const summary = children.map(p => `- [${p.id}] ${p.title}`).join('\\n');\n return {\n content: [\n {\n type: 'text',\n text: `자식 페이지 목록 (${children.length}):\\n${summary}`,\n },\n ],\n };\n }\n );\n\n server.tool(\n 'confluence_manage_labels',\n 'TDE Confluence 페이지의 라벨을 관리합니다. 라벨 조회, 추가, 삭제 기능을 제공합니다.',\n {\n pageId: z.string().describe('페이지 ID'),\n action: z.enum(['list', 'add', 'remove']).describe('작업 유형'),\n labels: z.array(z.string()).optional().describe('추가할 라벨 목록 (add 작업 시 필수)'),\n label: z.string().optional().describe('삭제할 라벨 (remove 작업 시 필수)'),\n },\n async ({ pageId, action, labels, label }) => {\n if (action === 'list') {\n const result = await labelApi.getLabels(pageId);\n const summary = result.map(l => l.name).join(', ');\n return {\n content: [{ type: 'text', text: `라벨 목록: ${summary}` }],\n };\n } else if (action === 'add') {\n if (!labels || labels.length === 0) {\n throw new Error('라벨 목록을 입력해주세요.');\n }\n await labelApi.addLabels(pageId, labels);\n return {\n content: [{ type: 'text', text: `라벨 추가 성공: ${labels.join(', ')}` }],\n };\n } else if (action === 'remove') {\n if (!label) {\n throw new Error('삭제할 라벨을 입력해주세요.');\n }\n await labelApi.removeLabel(pageId, label);\n return {\n content: [{ type: 'text', text: `라벨 삭제 성공: ${label}` }],\n };\n }\n return { content: [] };\n }\n );\n\n server.tool(\n 'confluence_convert_content',\n 'TDE Confluence 컨텐츠 포맷을 변환합니다. Markdown과 Confluence Storage Format 간 양방향 변환을 지원합니다.',\n {\n content: z.string().describe('변환할 컨텐츠'),\n format: z.enum(['storage_to_markdown', 'markdown_to_storage']).describe('변환 방향'),\n },\n async ({ content, format }) => {\n let result = '';\n if (format === 'storage_to_markdown') {\n result = storageToMd.convert(content);\n } else {\n result = mdToStorage.convert(content);\n }\n return {\n content: [{ type: 'text', text: result }],\n };\n }\n );\n\n } catch (error) {\n logger.warn(`Confluence 설정 로드 실패 또는 도구 등록 중 오류 발생: ${(error as Error).message}`);\n // Do not throw, just skip registration if config is missing (optional module pattern)\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceLabel } from '../types.js';\n\nexport class ConfluenceLabelApi {\n constructor(private client: AxiosInstance) { }\n\n async getLabels(pageId: string): Promise<ConfluenceLabel[]> {\n const response = await this.client.get(`/rest/api/content/${pageId}/label`);\n return response.data.results;\n }\n\n async addLabels(pageId: string, labels: string[]): Promise<void> {\n const data = labels.map(name => ({ prefix: 'global', name }));\n await this.client.post(`/rest/api/content/${pageId}/label`, data);\n }\n\n async removeLabel(pageId: string, labelName: string): Promise<void> {\n // Label deletion usually requires query param for name\n // /rest/api/content/{id}/label?name={name}\n await this.client.delete(`/rest/api/content/${pageId}/label`, {\n params: { name: labelName }\n });\n }\n}\n"],"mappings":"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","names":[]}
|