tdecollab 0.3.2 → 0.3.3
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/README.md +8 -4
- package/dist/{chunk-6AFNYE7N.js → chunk-BWZT27NL.js} +32 -3
- package/dist/chunk-BWZT27NL.js.map +1 -0
- package/dist/{chunk-GMC75YB2.js → chunk-PNYGNVQ4.js} +2 -2
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/{server-M353VF2O.js → server-MHNYWUKQ.js} +3 -3
- package/dist/tui/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-6AFNYE7N.js.map +0 -1
- /package/dist/{chunk-GMC75YB2.js.map → chunk-PNYGNVQ4.js.map} +0 -0
- /package/dist/{server-M353VF2O.js.map → server-MHNYWUKQ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -46,11 +46,15 @@ GITLAB_BASE_URL=https://gitlab.example.com # 미설정 시 https://gitlab.com
|
|
|
46
46
|
GITLAB_PRIVATE_TOKEN=your-private-token
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
설정 로드 우선순위:
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
| 우선순위 | 위치 | 설명 |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| 1 | 셸 환경변수 / MCP `env` | `export CONFLUENCE_BASE_URL=...` 또는 Claude Desktop 설정의 `env` 섹션 |
|
|
54
|
+
| 2 | `./tdecollab.env` | 현재 작업 디렉토리의 프로젝트별 설정 |
|
|
55
|
+
| 3 | `~/.config/tdecollab/.env` | 사용자 글로벌 기본 설정 |
|
|
56
|
+
|
|
57
|
+
상위 우선순위에 이미 설정된 값은 하위 설정 파일 값으로 덮어쓰지 않습니다.
|
|
54
58
|
|
|
55
59
|
## 사용법
|
|
56
60
|
|
|
@@ -2,6 +2,35 @@ import {
|
|
|
2
2
|
logger
|
|
3
3
|
} from "./chunk-IFYMZLQI.js";
|
|
4
4
|
|
|
5
|
+
// tools/common/env-loader.ts
|
|
6
|
+
import dotenv from "dotenv";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
var loaded = false;
|
|
10
|
+
function getHomeDir() {
|
|
11
|
+
return process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
12
|
+
}
|
|
13
|
+
function loadEnv() {
|
|
14
|
+
const result = { loadedFiles: [], skippedFiles: [] };
|
|
15
|
+
if (loaded) return result;
|
|
16
|
+
loaded = true;
|
|
17
|
+
const candidates = [
|
|
18
|
+
// 우선순위 2: 현재 디렉토리
|
|
19
|
+
path.resolve(process.cwd(), "tdecollab.env"),
|
|
20
|
+
// 우선순위 3: 사용자 글로벌
|
|
21
|
+
path.join(getHomeDir(), ".config", "tdecollab", ".env")
|
|
22
|
+
];
|
|
23
|
+
for (const filepath of candidates) {
|
|
24
|
+
const out = dotenv.config({ path: filepath, override: false });
|
|
25
|
+
if (out.error) {
|
|
26
|
+
result.skippedFiles.push(filepath);
|
|
27
|
+
} else {
|
|
28
|
+
result.loadedFiles.push(filepath);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
|
|
5
34
|
// tools/confluence/api/content.ts
|
|
6
35
|
var ConfluenceContentApi = class {
|
|
7
36
|
constructor(client) {
|
|
@@ -277,8 +306,7 @@ function createConfluenceClient(config) {
|
|
|
277
306
|
}
|
|
278
307
|
|
|
279
308
|
// tools/common/config.ts
|
|
280
|
-
|
|
281
|
-
dotenv.config();
|
|
309
|
+
loadEnv();
|
|
282
310
|
function getEnvOrThrow(key, description) {
|
|
283
311
|
const value = process.env[key];
|
|
284
312
|
if (!value) {
|
|
@@ -724,6 +752,7 @@ function createGitlabClient(config) {
|
|
|
724
752
|
}
|
|
725
753
|
|
|
726
754
|
export {
|
|
755
|
+
loadEnv,
|
|
727
756
|
ConfluenceContentApi,
|
|
728
757
|
ConfluenceSpaceApi,
|
|
729
758
|
ConfluenceSearchApi,
|
|
@@ -741,4 +770,4 @@ export {
|
|
|
741
770
|
GitlabPipelineApi,
|
|
742
771
|
createGitlabClient
|
|
743
772
|
};
|
|
744
|
-
//# sourceMappingURL=chunk-
|
|
773
|
+
//# sourceMappingURL=chunk-BWZT27NL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../tools/common/env-loader.ts","../tools/confluence/api/content.ts","../tools/confluence/api/space.ts","../tools/confluence/api/search.ts","../tools/common/http-client.ts","../tools/common/errors.ts","../tools/confluence/api/client.ts","../tools/common/config.ts","../tools/confluence/converters/md-to-storage.ts","../tools/confluence/converters/storage-to-md.ts","../tools/jira/api/issue.ts","../tools/jira/api/search.ts","../tools/jira/api/client.ts","../tools/gitlab/api/merge-request.ts","../tools/gitlab/api/pipeline.ts","../tools/gitlab/api/client.ts"],"sourcesContent":["import dotenv from 'dotenv';\nimport path from 'path';\nimport os from 'os';\n\n// 환경변수 로딩 우선순위:\n// 1. 셸 환경변수 (이미 process.env 에 존재하므로 자동 우선)\n// 2. 현재 작업 디렉토리의 tdecollab.env\n// 3. ~/.config/tdecollab/.env (사용자 글로벌 설정)\n//\n// dotenv 기본 동작이 override: false 이므로,\n// 이미 process.env 에 있는 키는 덮어쓰지 않는다.\n// 따라서 우선순위 높은 출처(env vars)부터 로드하면 자연스럽게 우선순위가 적용된다.\n\nlet loaded = false;\n\nexport interface LoadEnvResult {\n loadedFiles: string[];\n skippedFiles: string[];\n}\n\nfunction getHomeDir(): string {\n return process.env.HOME || process.env.USERPROFILE || os.homedir();\n}\n\nexport function loadEnv(): LoadEnvResult {\n const result: LoadEnvResult = { loadedFiles: [], skippedFiles: [] };\n if (loaded) return result;\n loaded = true;\n\n const candidates = [\n // 우선순위 2: 현재 디렉토리\n path.resolve(process.cwd(), 'tdecollab.env'),\n // 우선순위 3: 사용자 글로벌\n path.join(getHomeDir(), '.config', 'tdecollab', '.env'),\n ];\n\n for (const filepath of candidates) {\n const out = dotenv.config({ path: filepath, override: false });\n if (out.error) {\n // 파일이 없으면 자연스럽게 skip (오류로 취급하지 않음)\n result.skippedFiles.push(filepath);\n } else {\n result.loadedFiles.push(filepath);\n }\n }\n\n return result;\n}\n\n// 디버그용 — 어떤 파일이 로드되었는지 확인할 때 사용\nexport function getEnvLoadDebug(): string[] {\n return loaded ? ['env-loader: 1회 호출됨'] : ['env-loader: 호출되지 않음'];\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluencePageResponse, CreatePageParams, UpdatePageParams, ConfluenceLabel, ConfluenceAttachmentResponse } from '../types.js';\n\n\nexport class ConfluenceContentApi {\n constructor(private client: AxiosInstance) { }\n\n async getPage(id: string, expand?: string[]): Promise<ConfluencePageResponse> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space,metadata.labels';\n const response = await this.client.get(`/rest/api/content/${id}`, {\n params: { expand: expandParam }\n });\n return response.data;\n }\n\n async getPageByTitle(spaceKey: string, title: string, expand?: string[]): Promise<ConfluencePageResponse | null> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space';\n const response = await this.client.get('/rest/api/content', {\n params: {\n spaceKey,\n title,\n expand: expandParam,\n limit: 1\n }\n });\n\n if (response.data.results && response.data.results.length > 0) {\n return response.data.results[0];\n }\n return null;\n }\n\n async createPage(params: CreatePageParams): Promise<ConfluencePageResponse> {\n const data: any = {\n type: 'page',\n title: params.title,\n space: { key: params.spaceKey },\n body: {\n storage: {\n value: params.body,\n representation: 'storage'\n }\n }\n };\n\n if (params.parentId) {\n data.ancestors = [{ id: params.parentId }];\n }\n\n const response = await this.client.post('/rest/api/content', data);\n\n // add labels if provided\n if (params.labels && params.labels.length > 0) {\n await this.addLabels(response.data.id, params.labels);\n // refetch to include labels in response if needed, \n // but simpler to just return the create response.\n // Or we can construct the object.\n }\n\n return response.data;\n }\n\n async updatePage(params: UpdatePageParams): Promise<ConfluencePageResponse> {\n const data = {\n version: { number: params.version + 1 },\n title: params.title,\n type: 'page',\n body: {\n storage: {\n value: params.body,\n representation: 'storage'\n }\n }\n };\n\n const response = await this.client.put(`/rest/api/content/${params.id}`, data);\n return response.data;\n }\n\n async deletePage(id: string): Promise<void> {\n await this.client.delete(`/rest/api/content/${id}`);\n }\n\n async getChildPages(id: string, start = 0, limit = 25): Promise<ConfluencePageResponse[]> {\n const response = await this.client.get(`/rest/api/content/${id}/child/page`, {\n params: { start, limit }\n });\n return response.data.results;\n }\n\n // Label helper inside content api or separate? \n // Let's implement basic label addition here since it's used in create.\n // Actually, label logic is in label.ts, but due to circular dependency or convenience...\n // Let's implement it here privately or import it.\n // Better to keep it separate as per plan, but `this.client` is available here.\n // I'll implement a simple one here or use the separate class later. \n // For now, simple implementation to support createPage.\n private async addLabels(id: string, labels: string[]): Promise<void> {\n const data = labels.map(name => ({ prefix: 'global', name }));\n await this.client.post(`/rest/api/content/${id}/label`, data);\n }\n\n // Attachment 관련 메서드 (upsert: 기존 파일이 있으면 업데이트, 없으면 신규 업로드)\n async uploadAttachment(pageId: string, filename: string, fileContent: Buffer, contentType?: string): Promise<ConfluenceAttachmentResponse> {\n const FormData = (await import('form-data')).default;\n\n // 기존 첨부파일 존재 여부 확인\n const existingAttachments = await this.getAttachments(pageId, filename);\n const existing = existingAttachments.find(a => a.title === filename);\n\n const form = new FormData();\n form.append('file', fileContent, {\n filename: filename,\n contentType: contentType || 'application/octet-stream'\n });\n\n const headers = {\n ...form.getHeaders(),\n 'X-Atlassian-Token': 'nocheck',\n 'Accept': 'application/json',\n };\n\n let response;\n if (existing) {\n // 기존 파일 업데이트 (POST to /data endpoint)\n response = await this.client.post(\n `/rest/api/content/${pageId}/child/attachment/${existing.id}/data`,\n form,\n { headers }\n );\n } else {\n // 신규 업로드\n response = await this.client.post(\n `/rest/api/content/${pageId}/child/attachment`,\n form,\n { headers }\n );\n }\n\n // Confluence API returns { results: [Attachment] } \n if (response.data && response.data.results && response.data.results.length > 0) {\n return response.data.results[0];\n }\n return response.data;\n }\n\n async getAttachments(pageId: string, filename?: string): Promise<ConfluenceAttachmentResponse[]> {\n const response = await this.client.get(`/rest/api/content/${pageId}/child/attachment`, {\n params: {\n filename,\n expand: 'version'\n }\n });\n return response.data.results;\n }\n\n async downloadAttachment(downloadUrl: string): Promise<Buffer> {\n const response = await this.client.get(downloadUrl, {\n responseType: 'arraybuffer'\n });\n return Buffer.from(response.data);\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceSpaceResponse } from '../types.js';\n\nexport class ConfluenceSpaceApi {\n constructor(private client: AxiosInstance) { }\n\n async getSpaces(type: string = 'global', start = 0, limit = 25): Promise<ConfluenceSpaceResponse[]> {\n const response = await this.client.get('/rest/api/space', {\n params: { type, start, limit }\n });\n return response.data.results;\n }\n\n async getSpace(spaceKey: string): Promise<ConfluenceSpaceResponse> {\n const response = await this.client.get(`/rest/api/space/${spaceKey}`);\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceSearchResponse } from '../types.js';\n\nexport class ConfluenceSearchApi {\n constructor(private client: AxiosInstance) { }\n\n async searchByCql(cql: string, start = 0, limit = 25, expand?: string[]): Promise<ConfluenceSearchResponse> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space,metadata.labels';\n const response = await this.client.get('/rest/api/content/search', {\n params: {\n cql,\n start,\n limit,\n expand: expandParam\n }\n });\n\n return response.data;\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { ApiError, AuthError, NotFoundError, ConflictError } from './errors.js';\nimport { logger } from './logger.js';\nimport { ServiceConfig } from './types.js';\n\nexport function createHttpClient(config: ServiceConfig): AxiosInstance {\n const client = axios.create({\n baseURL: config.baseUrl,\n timeout: 30000, // 30초 타임아웃\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n // 요청 인터셉터: 인증 헤더 주입 및 로깅\n client.interceptors.request.use((reqConfig) => {\n // 1. 토큰 기반 Bearer 인증 (Confluence/JIRA PAT 권장 방식)\n if (config.auth.token && !reqConfig.headers.Authorization && !reqConfig.headers['PRIVATE-TOKEN']) {\n // GitLab은 PRIVATE-TOKEN 헤더를 선호하므로 제외\n reqConfig.headers.Authorization = `Bearer ${config.auth.token}`;\n }\n // 2. Basic 인증 (Username + Password/Token) - Bearer가 없을 때만 사용\n else if (config.auth.username && config.auth.token && !reqConfig.headers.Authorization) {\n const token = Buffer.from(`${config.auth.username}:${config.auth.token}`).toString('base64');\n reqConfig.headers.Authorization = `Basic ${token}`;\n }\n\n logger.debug(`[HTTP Request] ${reqConfig.method?.toUpperCase()} ${reqConfig.url}`, {\n headers: reqConfig.headers,\n params: reqConfig.params,\n data: reqConfig.data,\n });\n\n return reqConfig;\n });\n\n // 응답 인터셉터: 에러 핸들링 및 로깅\n client.interceptors.response.use(\n (response: AxiosResponse) => {\n logger.debug(`[HTTP Response] ${response.status} ${response.config.method?.toUpperCase()} ${response.config.url}`, {\n headers: response.headers,\n data: response.data,\n });\n return response;\n },\n (error: AxiosError) => {\n if (error.response) {\n const status = error.response.status;\n const method = error.config?.method?.toUpperCase();\n const url = error.config?.url;\n const message = (error.response.data as any)?.message || error.message;\n\n logger.error(`[HTTP Error] ${status} ${method} ${url}`, {\n message,\n responseData: error.response.data,\n requestHeaders: error.config?.headers,\n });\n\n // 상태 코드별 커스텀 에러 매핑\n if (status === 401 || status === 403) {\n throw new AuthError(`인증 실패: ${message}`);\n }\n if (status === 404) {\n throw new NotFoundError('리소스', url || 'unknown');\n }\n if (status === 409) {\n throw new ConflictError(`충돌 발생: ${message}`);\n }\n\n throw new ApiError(status, message, error.response.data);\n } else if (error.request) {\n logger.error(`[HTTP] No Response: ${error.message}`);\n throw new ApiError(0, `서버로부터 응답이 없습니다: ${error.message}`);\n } else {\n logger.error(`[HTTP] Request Error: ${error.message}`);\n throw new ApiError(0, `요청 설정 중 오류 발생: ${error.message}`);\n }\n }\n );\n\n return client;\n}\n","// TDE Collab 기본 에러 클래스\nexport class TdeCollabError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n// API 요청 실패 에러\nexport class ApiError extends TdeCollabError {\n constructor(\n public statusCode: number,\n message: string,\n public data?: any\n ) {\n super(`API 요청 실패 (${statusCode}): ${message}`);\n }\n}\n\n// 인증 실패 에러\nexport class AuthError extends TdeCollabError {\n constructor(message: string = '인증에 실패했습니다') {\n super(message);\n }\n}\n\n// 리소스 미발견 에러\nexport class NotFoundError extends TdeCollabError {\n constructor(resource: string, id: string) {\n super(`${resource} '${id}'를 찾을 수 없습니다`);\n }\n}\n\n// 리소스 충돌 에러\nexport class ConflictError extends TdeCollabError {\n constructor(message: string) {\n super(message);\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createConfluenceClient(config: ConfluenceConfig): AxiosInstance {\n // Confluence API base context path handling\n // If user provides 'https://example.atlassian.net/wiki', we should use that.\n // API path usually appends '/rest/api/content' etc.\n\n // Ensure config.baseUrl includes '/wiki' if it's a cloud instance, usually users put it in env.\n // But standard is commonly base domain.\n // We'll trust the config for now, but client consumers should append specific endpoints.\n // Typically, Confluence API is at /wiki/rest/api if cloud, or /rest/api if server.\n // Let's assume baseUrl in config points to the root of the instance, e.g. https://site.atlassian.net/wiki\n\n return createHttpClient(config);\n}\n","import { ConfluenceConfig, GitlabConfig, JiraConfig } from './types.js';\nimport { logger } from './logger.js';\nimport { loadEnv } from './env-loader.js';\n\n// 환경변수 로드 (우선순위: shell env > ./tdecollab.env > ~/.config/tdecollab/.env)\nloadEnv();\n\n// 환경변수 조회 및 미설정 시 에러 발생\nfunction getEnvOrThrow(key: string, description: string): string {\n const value = process.env[key];\n if (!value) {\n const errorMsg = `환경변수 '${key}'가 설정되지 않았습니다. (${description})`;\n logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n return value;\n}\n\n// Confluence 설정 로드 (PAT 인증 권장)\nexport function loadConfluenceConfig(): ConfluenceConfig & { mermaidMacroName: string, inlineCodeStyle: string } {\n const baseUrl = getEnvOrThrow('CONFLUENCE_BASE_URL', 'Confluence 기본 URL');\n // PAT 사용 시 username은 불필요 (Basic Auth 사용 시에만 필요)\n const username = process.env.CONFLUENCE_USERNAME;\n const token = getEnvOrThrow('CONFLUENCE_API_TOKEN', 'Confluence PAT 토큰');\n \n // Mermaid 매크로 이름 (기본값: mermaiddiagram)\n const mermaidMacroName = process.env.CONFLUENCE_MERMAID_MACRO_NAME || 'mermaiddiagram';\n\n // 인라인 코드 강조 스타일 (기본값: 붉은색 굵게)\n const inlineCodeStyle = process.env.CONFLUENCE_INLINE_CODE_STYLE || 'color: #d04437; font-weight: bold;';\n\n return {\n baseUrl,\n auth: {\n username,\n token,\n },\n mermaidMacroName,\n inlineCodeStyle,\n };\n}\n\n// AI 서비스 설정 로드\nexport function loadAIConfig() {\n return {\n openaiApiKey: process.env.OPENAI_API_KEY,\n anthropicApiKey: process.env.ANTHROPIC_API_KEY,\n defaultProvider: process.env.AI_PROVIDER || 'openai',\n defaultModel: process.env.AI_MODEL || 'gpt-4o',\n };\n}\n\n// JIRA 설정 로드 (PAT 인증 권장)\nexport function loadJiraConfig(): JiraConfig {\n const baseUrl = getEnvOrThrow('JIRA_BASE_URL', 'JIRA 기본 URL');\n // PAT 사용 시 username은 불필요\n const username = process.env.JIRA_USERNAME;\n const token = getEnvOrThrow('JIRA_API_TOKEN', 'JIRA PAT 토큰');\n\n return {\n baseUrl,\n auth: {\n username,\n token,\n },\n };\n}\n\n// GitLab 설정 로드\nexport function loadGitlabConfig(): GitlabConfig {\n const baseUrl = process.env.GITLAB_BASE_URL || 'https://gitlab.com';\n const token = getEnvOrThrow('GITLAB_PRIVATE_TOKEN', 'GitLab Private Token');\n\n return {\n baseUrl,\n auth: {\n token,\n },\n };\n}\n","import MarkdownIt from 'markdown-it';\nimport { loadConfluenceConfig } from '../../common/config.js';\n\nexport class MarkdownToStorageConverter {\n private md: MarkdownIt;\n private mermaidMacroName: string;\n private inlineCodeStyle: string;\n\n constructor() {\n const config = loadConfluenceConfig();\n this.mermaidMacroName = config.mermaidMacroName;\n this.inlineCodeStyle = config.inlineCodeStyle;\n\n this.md = new MarkdownIt({\n html: true,\n linkify: true,\n breaks: true,\n xhtmlOut: true // Confluence XML 파서와의 호환성을 위해 XHTML 출력 활성화\n });\n\n // Custom renderer for code blocks\n this.md.renderer.rules.fence = (tokens, idx) => {\n const token = tokens[idx];\n const code = token.content.trim();\n const lang = token.info.trim().toLowerCase();\n\n // Mermaid 처리 (기존 로직 유지)\n if (lang === 'mermaid') {\n return `<ac:structured-macro ac:name=\"${this.mermaidMacroName}\" ac:schema-version=\"1\">\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n }\n\n // PlantUML 처리 → plantuml 매크로로 변환\n if (lang === 'plantuml') {\n return `<ac:structured-macro ac:name=\"plantuml\" ac:schema-version=\"1\">\n <ac:parameter ac:name=\"atlassian-macro-output-type\">INLINE</ac:parameter>\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n }\n\n // 일반 코드 블록\n return `<ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\">\n <ac:parameter ac:name=\"language\">${lang || 'text'}</ac:parameter>\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n };\n\n // Custom renderer for images\n this.md.renderer.rules.image = (tokens, idx, options, env, self) => {\n const token = tokens[idx];\n const src = token.attrGet('src') || '';\n const alt = token.content || '';\n\n // Handle URL vs Local file\n const isExternal = src.startsWith('http://') || src.startsWith('https://');\n\n // 외부 URL이면 URL 매크로, 아니면 첨부파일 매크로\n const altAttr = alt ? ` ac:alt=\"${this.md.utils.escapeHtml(alt)}\"` : '';\n if (isExternal) {\n return `<ac:image${altAttr}><ri:url ri:value=\"${src}\" /></ac:image>`;\n } else {\n // filename can just be the basename of the src path\n const filename = src.split('/').pop() || src;\n return `<ac:image${altAttr}><ri:attachment ri:filename=\"${filename}\" /></ac:image>`;\n }\n };\n\n // Custom renderer for inline code\n this.md.renderer.rules.code_inline = (tokens, idx) => {\n const token = tokens[idx];\n const content = this.md.utils.escapeHtml(token.content);\n return `<code style=\"${this.inlineCodeStyle}\">${content}</code>`;\n };\n\n // Task List 처리 (markdown-it 플러그인 없이 수동 처리 예시 - 실제로는 플러그인 도입 권장)\n }\n\n convert(markdown: string): string {\n return this.md.render(markdown);\n }\n\n extractLocalImages(markdown: string): string[] {\n const tokens = this.md.parse(markdown, {});\n const localImages = new Set<string>();\n\n const walk = (tokens: any[]) => {\n for (const token of tokens) {\n if (token.type === 'image') {\n const src = token.attrGet('src') || '';\n if (!src.startsWith('http://') && !src.startsWith('https://')) {\n localImages.add(src);\n }\n }\n if (token.children) {\n walk(token.children);\n }\n }\n };\n\n walk(tokens);\n return Array.from(localImages);\n }\n}\n","import TurndownService from 'turndown';\nimport { gfm } from 'turndown-plugin-gfm';\nimport { JSDOM } from 'jsdom';\n\nexport class StorageToMarkdownConverter {\n private turndown: TurndownService;\n\n constructor() {\n this.turndown = new TurndownService({\n headingStyle: 'atx',\n hr: '---',\n bulletListMarker: '-',\n codeBlockStyle: 'fenced'\n });\n\n this.turndown.use(gfm);\n this.setupRules();\n }\n\n private setupRules() {\n // Table 변환 규칙 강화 (정렬 정보 보존)\n this.turndown.addRule('tables', {\n filter: ['table'],\n replacement: (content, node) => {\n const element = node as HTMLTableElement;\n const rows = Array.from(element.rows);\n if (rows.length === 0) return '';\n\n let mdTable = '\\n\\n';\n\n rows.forEach((row, index) => {\n const cells = Array.from(row.cells);\n const cellContents = cells.map(cell => {\n // 셀 내부의 개행은 공백으로 치환하여 테이블 깨짐 방지\n return this.turndown.turndown(cell.innerHTML).replace(/\\n/g, ' ').trim();\n });\n\n mdTable += `| ${cellContents.join(' | ')} |\\n`;\n\n // 헤더 행 구분선 (정렬 정보 포함)\n if (index === 0) {\n const separators = cells.map(cell => {\n const style = (cell as HTMLElement).getAttribute('style') || '';\n const align = style.match(/text-align:\\s*(\\w+)/i)?.[1]?.toLowerCase();\n if (align === 'center') return ':---:';\n if (align === 'right') return '---:';\n if (align === 'left') return ':---';\n return '---';\n });\n mdTable += `| ${separators.join(' | ')} |\\n`;\n }\n });\n\n return mdTable + '\\n';\n }\n });\n\n // Confluence 매크로 (변환된 div 태그) 처리\n this.turndown.addRule('confluenceMacro', {\n filter: (node) => {\n return node.nodeName === 'DIV' && node.getAttribute('data-macro-name-tag') !== null;\n },\n replacement: (content, node) => {\n const element = node as HTMLElement;\n const macroName = element.getAttribute('data-macro-name');\n\n if (macroName === 'code') {\n const lang = element.querySelector('[data-macro-param-name=\"language\"]')?.textContent || 'text';\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n // 임시 CDATA 태그 제거\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`${lang}\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n if (macroName === 'mermaid' || macroName === 'mermaiddiagram' || macroName === 'capable-mermaid' || macroName === 'mermaid-macro') {\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n // 임시 CDATA 태그 제거\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`mermaid\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n if (macroName === 'plantuml') {\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`plantuml\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n return `\\n<!-- Macro: ${macroName} -->\\n`;\n }\n });\n }\n\n convert(storageHtml: string, imageUrlMap?: Map<string, string>): string {\n if (!storageHtml) return '';\n\n // 1. Confluence 전용 태그를 표준 HTML 태그로 치환 (JSDOM 호환성)\n // CDATA 섹션을 텍스트로 보존하기 위해 임시 치환\n let processedHtml = storageHtml\n .replace(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/gi, (match, p1) => {\n return `__CDATA_START__${p1}__CDATA_END__`;\n })\n .replace(/<ac:structured-macro\\s+ac:name=\"([^\"]*)\"/gi, '<div data-macro-name-tag data-macro-name=\"$1\"')\n .replace(/<\\/ac:structured-macro>/gi, '</div>')\n .replace(/<ac:parameter\\s+ac:name=\"([^\"]*)\"/gi, '<div data-macro-param-tag data-macro-param-name=\"$1\"')\n .replace(/<\\/ac:parameter>/gi, '</div>')\n .replace(/<ac:plain-text-body>/gi, '<pre data-macro-body>')\n .replace(/<\\/ac:plain-text-body>/gi, '</pre>')\n .replace(/<ac:image([^>]*)>[\\s\\S]*?<ri:attachment\\s+ri:filename=\"([^\"]*)\"\\s*\\/?>[\\s\\S]*?<\\/ac:image>/gi, (match, attrs, filename) => {\n const altMatch = attrs.match(/ac:alt=\"([^\"]*)\"/i);\n const alt = altMatch ? altMatch[1] : filename;\n return `<img src=\"${filename}\" alt=\"${alt}\" />`;\n })\n .replace(/<ac:image([^>]*)>[\\s\\S]*?<ri:url\\s+ri:value=\"([^\"]*)\"\\s*\\/?>[\\s\\S]*?<\\/ac:image>/gi, (match, attrs, url) => {\n const altMatch = attrs.match(/ac:alt=\"([^\"]*)\"/i);\n const alt = altMatch ? altMatch[1] : '';\n return `<img src=\"${url}\" alt=\"${alt}\" />`;\n });\n\n // 2. JSDOM 파싱\n const dom = new JSDOM(processedHtml);\n const document = dom.window.document;\n\n // 이미지 처리\n if (imageUrlMap && imageUrlMap.size > 0) {\n const images = document.querySelectorAll('img');\n images.forEach(img => {\n const src = img.getAttribute('src');\n if (src && imageUrlMap.has(src)) {\n img.setAttribute('src', imageUrlMap.get(src)!);\n }\n });\n }\n\n // 3. Turndown 변환\n let markdown = this.turndown.turndown(document.body.innerHTML).trim();\n\n // 4. 헤딩 내 숫자 뒤 점 이스케이프 제거 (예: `## 1\\.` → `## 1.`)\n markdown = markdown.replace(/^(#{1,6}\\s.*?)\\\\\\./gm, '$1.');\n\n return markdown + '\\n';\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraIssueResponse, CreateIssueParams, UpdateIssueParams } from '../types.js';\n\nexport class JiraIssueApi {\n constructor(private client: AxiosInstance) {}\n\n async getIssue(issueKey: string, fields?: string[], expand?: string[]): Promise<JiraIssueResponse> {\n const params: Record<string, string> = {};\n if (fields && fields.length > 0) {\n params.fields = fields.join(',');\n }\n if (expand && expand.length > 0) {\n params.expand = expand.join(',');\n }\n const response = await this.client.get(`/rest/api/2/issue/${issueKey}`, { params });\n return response.data;\n }\n\n async createIssue(params: CreateIssueParams): Promise<JiraIssueResponse> {\n const fields: Record<string, unknown> = {\n project: { key: params.projectKey },\n summary: params.summary,\n issuetype: { name: params.issueType },\n };\n\n if (params.description) fields.description = params.description;\n if (params.assignee) fields.assignee = { name: params.assignee };\n if (params.priority) fields.priority = { name: params.priority };\n if (params.labels) fields.labels = params.labels;\n if (params.components) {\n fields.components = params.components.map((name) => ({ name }));\n }\n if (params.parentKey) {\n fields.parent = { key: params.parentKey };\n }\n if (params.customFields) {\n Object.assign(fields, params.customFields);\n }\n\n const response = await this.client.post('/rest/api/2/issue', { fields });\n return response.data;\n }\n\n async updateIssue(issueKey: string, params: UpdateIssueParams): Promise<void> {\n const fields: Record<string, unknown> = {};\n\n if (params.summary) fields.summary = params.summary;\n if (params.description !== undefined) fields.description = params.description;\n if (params.assignee !== undefined) fields.assignee = params.assignee ? { name: params.assignee } : null;\n if (params.priority) fields.priority = { name: params.priority };\n if (params.labels) fields.labels = params.labels;\n if (params.components) {\n fields.components = params.components.map((name) => ({ name }));\n }\n if (params.customFields) {\n Object.assign(fields, params.customFields);\n }\n\n await this.client.put(`/rest/api/2/issue/${issueKey}`, { fields });\n }\n\n async deleteIssue(issueKey: string, deleteSubtasks = false): Promise<void> {\n await this.client.delete(`/rest/api/2/issue/${issueKey}`, {\n params: { deleteSubtasks },\n });\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraSearchResponse } from '../types.js';\n\nexport class JiraSearchApi {\n constructor(private client: AxiosInstance) {}\n\n async searchByJql(\n jql: string,\n startAt = 0,\n maxResults = 50,\n fields?: string[],\n ): Promise<JiraSearchResponse> {\n const params: Record<string, unknown> = {\n jql,\n startAt,\n maxResults,\n };\n if (fields && fields.length > 0) {\n params.fields = fields.join(',');\n }\n const response = await this.client.get('/rest/api/2/search', { params });\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createJiraClient(config: JiraConfig): AxiosInstance {\n return createHttpClient(config);\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabMergeRequest, GitlabNote } from '../types.js';\n\nexport class GitlabMergeRequestApi {\n constructor(private client: AxiosInstance) {}\n\n async getMergeRequests(\n projectId: number,\n params?: { state?: string; scope?: string; labels?: string; perPage?: number },\n ): Promise<GitlabMergeRequest[]> {\n const response = await this.client.get(`/projects/${projectId}/merge_requests`, {\n params: {\n state: params?.state || 'opened',\n scope: params?.scope,\n labels: params?.labels,\n per_page: params?.perPage || 20,\n },\n });\n return response.data;\n }\n\n async getMergeRequest(projectId: number, mrIid: number): Promise<GitlabMergeRequest> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}`,\n );\n return response.data;\n }\n\n async getMergeRequestChanges(projectId: number, mrIid: number): Promise<GitlabMergeRequest> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/changes`,\n );\n return response.data;\n }\n\n async createMergeRequest(\n projectId: number,\n data: {\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_id?: number;\n reviewer_ids?: number[];\n labels?: string;\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.post(`/projects/${projectId}/merge_requests`, data);\n return response.data;\n }\n\n async updateMergeRequest(\n projectId: number,\n mrIid: number,\n data: {\n title?: string;\n description?: string;\n assignee_id?: number;\n reviewer_ids?: number[];\n labels?: string;\n state_event?: 'close' | 'reopen';\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.put(\n `/projects/${projectId}/merge_requests/${mrIid}`,\n data,\n );\n return response.data;\n }\n\n async mergeMergeRequest(\n projectId: number,\n mrIid: number,\n params?: {\n merge_commit_message?: string;\n squash?: boolean;\n should_remove_source_branch?: boolean;\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.put(\n `/projects/${projectId}/merge_requests/${mrIid}/merge`,\n params,\n );\n return response.data;\n }\n\n async getMergeRequestNotes(projectId: number, mrIid: number): Promise<GitlabNote[]> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/notes`,\n );\n return response.data;\n }\n\n async addMergeRequestNote(\n projectId: number,\n mrIid: number,\n body: string,\n ): Promise<GitlabNote> {\n const response = await this.client.post(\n `/projects/${projectId}/merge_requests/${mrIid}/notes`,\n { body },\n );\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabPipeline, GitlabJob } from '../types.js';\n\nexport class GitlabPipelineApi {\n constructor(private client: AxiosInstance) {}\n\n async getPipelines(\n projectId: number,\n params?: { status?: string; ref?: string; perPage?: number },\n ): Promise<GitlabPipeline[]> {\n const response = await this.client.get(`/projects/${projectId}/pipelines`, {\n params: {\n status: params?.status,\n ref: params?.ref,\n per_page: params?.perPage || 20,\n },\n });\n return response.data;\n }\n\n async getPipeline(projectId: number, pipelineId: number): Promise<GitlabPipeline> {\n const response = await this.client.get(\n `/projects/${projectId}/pipelines/${pipelineId}`,\n );\n return response.data;\n }\n\n async getPipelineJobs(projectId: number, pipelineId: number): Promise<GitlabJob[]> {\n const response = await this.client.get(\n `/projects/${projectId}/pipelines/${pipelineId}/jobs`,\n );\n return response.data;\n }\n\n async getMergeRequestPipelines(\n projectId: number,\n mrIid: number,\n ): Promise<GitlabPipeline[]> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/pipelines`,\n );\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createGitlabClient(config: GitlabConfig): AxiosInstance {\n const client = createHttpClient({\n ...config,\n baseUrl: `${config.baseUrl}/api/v4`,\n });\n\n // GitLab Self-hosted는 PRIVATE-TOKEN 헤더 사용\n client.defaults.headers.common['PRIVATE-TOKEN'] = config.auth.token!;\n\n return client;\n}\n"],"mappings":"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","names":["tokens"]}
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
loadConfluenceConfig,
|
|
24
24
|
loadGitlabConfig,
|
|
25
25
|
loadJiraConfig
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-BWZT27NL.js";
|
|
27
27
|
import {
|
|
28
28
|
logger
|
|
29
29
|
} from "./chunk-IFYMZLQI.js";
|
|
@@ -1105,4 +1105,4 @@ async function runServer() {
|
|
|
1105
1105
|
export {
|
|
1106
1106
|
runServer
|
|
1107
1107
|
};
|
|
1108
|
-
//# sourceMappingURL=chunk-
|
|
1108
|
+
//# sourceMappingURL=chunk-PNYGNVQ4.js.map
|
package/dist/cli.js
CHANGED
|
@@ -21,9 +21,10 @@ import {
|
|
|
21
21
|
createGitlabClient,
|
|
22
22
|
createJiraClient,
|
|
23
23
|
loadConfluenceConfig,
|
|
24
|
+
loadEnv,
|
|
24
25
|
loadGitlabConfig,
|
|
25
26
|
loadJiraConfig
|
|
26
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-BWZT27NL.js";
|
|
27
28
|
import {
|
|
28
29
|
logger
|
|
29
30
|
} from "./chunk-IFYMZLQI.js";
|
|
@@ -831,8 +832,7 @@ function registerGitlabCommands(program2) {
|
|
|
831
832
|
}
|
|
832
833
|
|
|
833
834
|
// tools/cli.ts
|
|
834
|
-
|
|
835
|
-
dotenv.config();
|
|
835
|
+
loadEnv();
|
|
836
836
|
function loadPackageVersion() {
|
|
837
837
|
try {
|
|
838
838
|
const here = path2.dirname(fileURLToPath(import.meta.url));
|
|
@@ -869,7 +869,7 @@ registerConfluenceCommands(program);
|
|
|
869
869
|
registerJiraCommands(program);
|
|
870
870
|
registerGitlabCommands(program);
|
|
871
871
|
program.command("mcp").description("Run MCP Server").action(async () => {
|
|
872
|
-
const { runServer } = await import("./server-
|
|
872
|
+
const { runServer } = await import("./server-MHNYWUKQ.js");
|
|
873
873
|
await runServer();
|
|
874
874
|
});
|
|
875
875
|
program.parse(args);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../tools/cli.ts","../tools/confluence/commands/index.ts","../tools/jira/commands/index.ts","../tools/gitlab/commands/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { registerConfluenceCommands } from './confluence/commands/index.js';\nimport { registerJiraCommands } from './jira/commands/index.js';\nimport { registerGitlabCommands } from './gitlab/commands/index.js';\nimport { logger } from './common/logger.js';\nimport dotenv from 'dotenv';\n\n// 환경변수 로드\ndotenv.config();\n\n// package.json 에서 버전 동적 로드 (배포된 dist 의 상위에 위치)\nfunction loadPackageVersion(): string {\n try {\n const here = path.dirname(fileURLToPath(import.meta.url));\n // 빌드된 dist/cli.js → ../package.json\n // 개발(tsx tools/cli.ts) → ../../package.json\n for (const candidate of [\n path.resolve(here, '..', 'package.json'),\n path.resolve(here, '..', '..', 'package.json'),\n ]) {\n if (fs.existsSync(candidate)) {\n const pkg = JSON.parse(fs.readFileSync(candidate, 'utf-8'));\n if (pkg.name === 'tdecollab' && pkg.version) return pkg.version as string;\n }\n }\n } catch {\n // fallthrough\n }\n return '0.0.0';\n}\n\n// 인자 정규화 (pnpm/tsx 환경에서 넘어올 수 있는 불필요한 '--' 처리)\nlet args = process.argv;\nif (args[2] === '--') {\n args = [args[0], args[1], ...args.slice(3)];\n}\n\n// 인자 없이 실행되면 TUI 모드로 진입\nif (args.length <= 2) {\n await import('./tui/index.js');\n // TUI 가 alternate screen 을 점유하므로 commander 등록은 스킵\n process.exit(0);\n}\n\nconst program = new Command();\n\nprogram\n .name('tdecollab')\n .description('TDE Collaboration CLI')\n .version(loadPackageVersion(), '-V, --version', '버전 정보 출력')\n .option('-v, --verbose', '상세 로그 출력')\n .option('-d, --debug', '디버그 로그 출력')\n .enablePositionalOptions()\n .hook('preAction', (thisCommand) => {\n const opts = program.opts();\n if (opts.verbose || opts.debug) {\n logger.setLevel('debug');\n logger.debug('Verbose/Debug mode enabled');\n }\n });\n\n// 모듈별 커맨드 등록\nregisterConfluenceCommands(program);\nregisterJiraCommands(program);\nregisterGitlabCommands(program);\n\n// MCP 서버 커맨드\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(args);\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 let baseDir = process.cwd();\n if (options.output) {\n baseDir = path.dirname(path.resolve(process.cwd(), options.output));\n }\n\n const imgDir = path.resolve(baseDir, options.imageDir);\n const downloader = new ImageDownloader(api, {\n outputDir: imgDir,\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 // 절대 경로를 baseDir 기준 상대 경로로 변환 (Markdown url 경로용)\n for (const [key, absolutePath] of imageUrlMap.entries()) {\n let relPath = path.relative(baseDir, absolutePath);\n relPath = relPath.split(path.sep).join('/'); // URL 구분자 통일\n imageUrlMap.set(key, relPath);\n }\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 let markdownDirPath = process.cwd();\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownDirPath = path.dirname(filePath);\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\n // 로컬 이미지 첨부파일 업로드 처리\n if (options.file) {\n const localImages = mdToStorage.extractLocalImages(markdownContent);\n if (localImages.length > 0) {\n console.log(chalk.blue(`로컬 이미지 첨부파일 업로드 시작 (${localImages.length}개)...`));\n for (const imgSrc of localImages) {\n try {\n const imagePath = path.resolve(markdownDirPath, imgSrc);\n if (fs.existsSync(imagePath)) {\n const fileBuffer = fs.readFileSync(imagePath);\n const filename = path.basename(imgSrc);\n let contentType = 'application/octet-stream';\n if (filename.endsWith('.png')) contentType = 'image/png';\n else if (filename.endsWith('.jpg') || filename.endsWith('.jpeg')) contentType = 'image/jpeg';\n else if (filename.endsWith('.svg')) contentType = 'image/svg+xml';\n else if (filename.endsWith('.gif')) contentType = 'image/gif';\n\n await api.uploadAttachment(page.id, filename, fileBuffer, contentType);\n console.log(chalk.green(` - 업로드 완료: ${filename}`));\n } else {\n console.error(chalk.yellow(` - 이미지 파일을 찾을 수 없습니다: ${imagePath}`));\n }\n } catch (uploadErr: any) {\n console.error(chalk.red(` - 업로드 실패 (${imgSrc}): ${uploadErr.message}`));\n }\n }\n }\n }\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n pageCmd.command('update <pageId>')\n .description('페이지 내용 업데이트')\n .option('-t, --title <title>', '변경할 제목 (생략 시 기존 제목 유지)')\n .option('-c, --content <content>', '내용 (Markdown 텍스트)')\n .option('-f, --file <path>', '내용 파일 경로 (Markdown)')\n .action(async (pageId, options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const mdToStorage = new MarkdownToStorageConverter();\n\n try {\n const currentPage = await api.getPage(pageId, ['version', 'title']);\n const currentVersion = currentPage.version?.number ?? 1;\n const currentTitle = currentPage.title;\n\n let markdownContent = '';\n let markdownDirPath = process.cwd();\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownDirPath = path.dirname(filePath);\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 updatedPage = await api.updatePage({\n id: pageId,\n title: options.title || currentTitle,\n body: mdToStorage.convert(markdownContent),\n version: currentVersion,\n });\n\n console.log(chalk.green(`페이지 업데이트 완료: ${updatedPage.title} (ID: ${updatedPage.id})`));\n console.log(`버전: v${currentVersion} → v${currentVersion + 1}`);\n console.log(`URL: ${updatedPage._links?.base}${updatedPage._links?.webui}`);\n\n // 로컬 이미지 첨부파일 업로드 처리 (upsert)\n if (options.file) {\n const localImages = mdToStorage.extractLocalImages(markdownContent);\n if (localImages.length > 0) {\n console.log(chalk.blue(`로컬 이미지 첨부파일 업로드 시작 (${localImages.length}개)...`));\n for (const imgSrc of localImages) {\n try {\n const imagePath = path.resolve(markdownDirPath, imgSrc);\n if (fs.existsSync(imagePath)) {\n const fileBuffer = fs.readFileSync(imagePath);\n const filename = path.basename(imgSrc);\n let contentType = 'application/octet-stream';\n if (filename.endsWith('.png')) contentType = 'image/png';\n else if (filename.endsWith('.jpg') || filename.endsWith('.jpeg')) contentType = 'image/jpeg';\n else if (filename.endsWith('.svg')) contentType = 'image/svg+xml';\n else if (filename.endsWith('.gif')) contentType = 'image/gif';\n await api.uploadAttachment(updatedPage.id, filename, fileBuffer, contentType);\n console.log(chalk.green(` - 업로드 완료: ${filename}`));\n } else {\n console.error(chalk.yellow(` - 이미지 파일을 찾을 수 없습니다: ${imagePath}`));\n }\n } catch (uploadErr: any) {\n console.error(chalk.red(` - 업로드 실패 (${imgSrc}): ${uploadErr.message}`));\n }\n }\n }\n }\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":["fs","path","program","chalk","Table","program","chalk","Table","program","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../tools/cli.ts","../tools/confluence/commands/index.ts","../tools/jira/commands/index.ts","../tools/gitlab/commands/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { registerConfluenceCommands } from './confluence/commands/index.js';\nimport { registerJiraCommands } from './jira/commands/index.js';\nimport { registerGitlabCommands } from './gitlab/commands/index.js';\nimport { logger } from './common/logger.js';\nimport { loadEnv } from './common/env-loader.js';\n\n// 환경변수 로드 (우선순위: shell env > ./tdecollab.env > ~/.config/tdecollab/.env)\nloadEnv();\n\n// package.json 에서 버전 동적 로드 (배포된 dist 의 상위에 위치)\nfunction loadPackageVersion(): string {\n try {\n const here = path.dirname(fileURLToPath(import.meta.url));\n // 빌드된 dist/cli.js → ../package.json\n // 개발(tsx tools/cli.ts) → ../../package.json\n for (const candidate of [\n path.resolve(here, '..', 'package.json'),\n path.resolve(here, '..', '..', 'package.json'),\n ]) {\n if (fs.existsSync(candidate)) {\n const pkg = JSON.parse(fs.readFileSync(candidate, 'utf-8'));\n if (pkg.name === 'tdecollab' && pkg.version) return pkg.version as string;\n }\n }\n } catch {\n // fallthrough\n }\n return '0.0.0';\n}\n\n// 인자 정규화 (pnpm/tsx 환경에서 넘어올 수 있는 불필요한 '--' 처리)\nlet args = process.argv;\nif (args[2] === '--') {\n args = [args[0], args[1], ...args.slice(3)];\n}\n\n// 인자 없이 실행되면 TUI 모드로 진입\nif (args.length <= 2) {\n await import('./tui/index.js');\n // TUI 가 alternate screen 을 점유하므로 commander 등록은 스킵\n process.exit(0);\n}\n\nconst program = new Command();\n\nprogram\n .name('tdecollab')\n .description('TDE Collaboration CLI')\n .version(loadPackageVersion(), '-V, --version', '버전 정보 출력')\n .option('-v, --verbose', '상세 로그 출력')\n .option('-d, --debug', '디버그 로그 출력')\n .enablePositionalOptions()\n .hook('preAction', (thisCommand) => {\n const opts = program.opts();\n if (opts.verbose || opts.debug) {\n logger.setLevel('debug');\n logger.debug('Verbose/Debug mode enabled');\n }\n });\n\n// 모듈별 커맨드 등록\nregisterConfluenceCommands(program);\nregisterJiraCommands(program);\nregisterGitlabCommands(program);\n\n// MCP 서버 커맨드\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(args);\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 let baseDir = process.cwd();\n if (options.output) {\n baseDir = path.dirname(path.resolve(process.cwd(), options.output));\n }\n\n const imgDir = path.resolve(baseDir, options.imageDir);\n const downloader = new ImageDownloader(api, {\n outputDir: imgDir,\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 // 절대 경로를 baseDir 기준 상대 경로로 변환 (Markdown url 경로용)\n for (const [key, absolutePath] of imageUrlMap.entries()) {\n let relPath = path.relative(baseDir, absolutePath);\n relPath = relPath.split(path.sep).join('/'); // URL 구분자 통일\n imageUrlMap.set(key, relPath);\n }\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 let markdownDirPath = process.cwd();\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownDirPath = path.dirname(filePath);\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\n // 로컬 이미지 첨부파일 업로드 처리\n if (options.file) {\n const localImages = mdToStorage.extractLocalImages(markdownContent);\n if (localImages.length > 0) {\n console.log(chalk.blue(`로컬 이미지 첨부파일 업로드 시작 (${localImages.length}개)...`));\n for (const imgSrc of localImages) {\n try {\n const imagePath = path.resolve(markdownDirPath, imgSrc);\n if (fs.existsSync(imagePath)) {\n const fileBuffer = fs.readFileSync(imagePath);\n const filename = path.basename(imgSrc);\n let contentType = 'application/octet-stream';\n if (filename.endsWith('.png')) contentType = 'image/png';\n else if (filename.endsWith('.jpg') || filename.endsWith('.jpeg')) contentType = 'image/jpeg';\n else if (filename.endsWith('.svg')) contentType = 'image/svg+xml';\n else if (filename.endsWith('.gif')) contentType = 'image/gif';\n\n await api.uploadAttachment(page.id, filename, fileBuffer, contentType);\n console.log(chalk.green(` - 업로드 완료: ${filename}`));\n } else {\n console.error(chalk.yellow(` - 이미지 파일을 찾을 수 없습니다: ${imagePath}`));\n }\n } catch (uploadErr: any) {\n console.error(chalk.red(` - 업로드 실패 (${imgSrc}): ${uploadErr.message}`));\n }\n }\n }\n }\n } catch (e: any) {\n console.error(chalk.red(`생성 실패: ${e.message}`));\n }\n });\n\n pageCmd.command('update <pageId>')\n .description('페이지 내용 업데이트')\n .option('-t, --title <title>', '변경할 제목 (생략 시 기존 제목 유지)')\n .option('-c, --content <content>', '내용 (Markdown 텍스트)')\n .option('-f, --file <path>', '내용 파일 경로 (Markdown)')\n .action(async (pageId, options) => {\n const client = initClient();\n const api = new ConfluenceContentApi(client);\n const mdToStorage = new MarkdownToStorageConverter();\n\n try {\n const currentPage = await api.getPage(pageId, ['version', 'title']);\n const currentVersion = currentPage.version?.number ?? 1;\n const currentTitle = currentPage.title;\n\n let markdownContent = '';\n let markdownDirPath = process.cwd();\n\n if (options.file) {\n try {\n const filePath = path.resolve(process.cwd(), options.file);\n markdownDirPath = path.dirname(filePath);\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 updatedPage = await api.updatePage({\n id: pageId,\n title: options.title || currentTitle,\n body: mdToStorage.convert(markdownContent),\n version: currentVersion,\n });\n\n console.log(chalk.green(`페이지 업데이트 완료: ${updatedPage.title} (ID: ${updatedPage.id})`));\n console.log(`버전: v${currentVersion} → v${currentVersion + 1}`);\n console.log(`URL: ${updatedPage._links?.base}${updatedPage._links?.webui}`);\n\n // 로컬 이미지 첨부파일 업로드 처리 (upsert)\n if (options.file) {\n const localImages = mdToStorage.extractLocalImages(markdownContent);\n if (localImages.length > 0) {\n console.log(chalk.blue(`로컬 이미지 첨부파일 업로드 시작 (${localImages.length}개)...`));\n for (const imgSrc of localImages) {\n try {\n const imagePath = path.resolve(markdownDirPath, imgSrc);\n if (fs.existsSync(imagePath)) {\n const fileBuffer = fs.readFileSync(imagePath);\n const filename = path.basename(imgSrc);\n let contentType = 'application/octet-stream';\n if (filename.endsWith('.png')) contentType = 'image/png';\n else if (filename.endsWith('.jpg') || filename.endsWith('.jpeg')) contentType = 'image/jpeg';\n else if (filename.endsWith('.svg')) contentType = 'image/svg+xml';\n else if (filename.endsWith('.gif')) contentType = 'image/gif';\n await api.uploadAttachment(updatedPage.id, filename, fileBuffer, contentType);\n console.log(chalk.green(` - 업로드 완료: ${filename}`));\n } else {\n console.error(chalk.yellow(` - 이미지 파일을 찾을 수 없습니다: ${imagePath}`));\n }\n } catch (uploadErr: any) {\n console.error(chalk.red(` - 업로드 실패 (${imgSrc}): ${uploadErr.message}`));\n }\n }\n }\n }\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":["fs","path","program","chalk","Table","program","chalk","Table","program","path","fs"]}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runServer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PNYGNVQ4.js";
|
|
5
5
|
import "./chunk-JI2YUE7N.js";
|
|
6
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
loadEnv
|
|
8
|
+
} from "./chunk-BWZT27NL.js";
|
|
7
9
|
import "./chunk-IFYMZLQI.js";
|
|
8
10
|
|
|
9
11
|
// tools/index.ts
|
|
12
|
+
loadEnv();
|
|
10
13
|
runServer().catch((error) => {
|
|
11
14
|
console.error("Fatal error in MCP Server entry point:", error);
|
|
12
15
|
process.exit(1);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../tools/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { runServer } from './mcp/server.js';\n\n\nrunServer().catch((error) => {\n console.error('Fatal error in MCP Server entry point:', error);\n process.exit(1);\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../tools/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { loadEnv } from './common/env-loader.js';\nimport { runServer } from './mcp/server.js';\n\n// 환경변수 로드 (우선순위: shell env > ./tdecollab.env > ~/.config/tdecollab/.env)\nloadEnv();\n\nrunServer().catch((error) => {\n console.error('Fatal error in MCP Server entry point:', error);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;AAKA,QAAQ;AAER,UAAU,EAAE,MAAM,CAAC,UAAU;AACzB,UAAQ,MAAM,0CAA0C,KAAK;AAC7D,UAAQ,KAAK,CAAC;AAClB,CAAC;","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PNYGNVQ4.js";
|
|
4
4
|
import "./chunk-JI2YUE7N.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-BWZT27NL.js";
|
|
6
6
|
import "./chunk-IFYMZLQI.js";
|
|
7
7
|
export {
|
|
8
8
|
runServer
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=server-
|
|
10
|
+
//# sourceMappingURL=server-MHNYWUKQ.js.map
|
package/dist/tui/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../tools/confluence/api/content.ts","../tools/confluence/api/space.ts","../tools/confluence/api/search.ts","../tools/common/http-client.ts","../tools/common/errors.ts","../tools/confluence/api/client.ts","../tools/common/config.ts","../tools/confluence/converters/md-to-storage.ts","../tools/confluence/converters/storage-to-md.ts","../tools/jira/api/issue.ts","../tools/jira/api/search.ts","../tools/jira/api/client.ts","../tools/gitlab/api/merge-request.ts","../tools/gitlab/api/pipeline.ts","../tools/gitlab/api/client.ts"],"sourcesContent":["import { AxiosInstance } from 'axios';\nimport { ConfluencePageResponse, CreatePageParams, UpdatePageParams, ConfluenceLabel, ConfluenceAttachmentResponse } from '../types.js';\n\n\nexport class ConfluenceContentApi {\n constructor(private client: AxiosInstance) { }\n\n async getPage(id: string, expand?: string[]): Promise<ConfluencePageResponse> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space,metadata.labels';\n const response = await this.client.get(`/rest/api/content/${id}`, {\n params: { expand: expandParam }\n });\n return response.data;\n }\n\n async getPageByTitle(spaceKey: string, title: string, expand?: string[]): Promise<ConfluencePageResponse | null> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space';\n const response = await this.client.get('/rest/api/content', {\n params: {\n spaceKey,\n title,\n expand: expandParam,\n limit: 1\n }\n });\n\n if (response.data.results && response.data.results.length > 0) {\n return response.data.results[0];\n }\n return null;\n }\n\n async createPage(params: CreatePageParams): Promise<ConfluencePageResponse> {\n const data: any = {\n type: 'page',\n title: params.title,\n space: { key: params.spaceKey },\n body: {\n storage: {\n value: params.body,\n representation: 'storage'\n }\n }\n };\n\n if (params.parentId) {\n data.ancestors = [{ id: params.parentId }];\n }\n\n const response = await this.client.post('/rest/api/content', data);\n\n // add labels if provided\n if (params.labels && params.labels.length > 0) {\n await this.addLabels(response.data.id, params.labels);\n // refetch to include labels in response if needed, \n // but simpler to just return the create response.\n // Or we can construct the object.\n }\n\n return response.data;\n }\n\n async updatePage(params: UpdatePageParams): Promise<ConfluencePageResponse> {\n const data = {\n version: { number: params.version + 1 },\n title: params.title,\n type: 'page',\n body: {\n storage: {\n value: params.body,\n representation: 'storage'\n }\n }\n };\n\n const response = await this.client.put(`/rest/api/content/${params.id}`, data);\n return response.data;\n }\n\n async deletePage(id: string): Promise<void> {\n await this.client.delete(`/rest/api/content/${id}`);\n }\n\n async getChildPages(id: string, start = 0, limit = 25): Promise<ConfluencePageResponse[]> {\n const response = await this.client.get(`/rest/api/content/${id}/child/page`, {\n params: { start, limit }\n });\n return response.data.results;\n }\n\n // Label helper inside content api or separate? \n // Let's implement basic label addition here since it's used in create.\n // Actually, label logic is in label.ts, but due to circular dependency or convenience...\n // Let's implement it here privately or import it.\n // Better to keep it separate as per plan, but `this.client` is available here.\n // I'll implement a simple one here or use the separate class later. \n // For now, simple implementation to support createPage.\n private async addLabels(id: string, labels: string[]): Promise<void> {\n const data = labels.map(name => ({ prefix: 'global', name }));\n await this.client.post(`/rest/api/content/${id}/label`, data);\n }\n\n // Attachment 관련 메서드 (upsert: 기존 파일이 있으면 업데이트, 없으면 신규 업로드)\n async uploadAttachment(pageId: string, filename: string, fileContent: Buffer, contentType?: string): Promise<ConfluenceAttachmentResponse> {\n const FormData = (await import('form-data')).default;\n\n // 기존 첨부파일 존재 여부 확인\n const existingAttachments = await this.getAttachments(pageId, filename);\n const existing = existingAttachments.find(a => a.title === filename);\n\n const form = new FormData();\n form.append('file', fileContent, {\n filename: filename,\n contentType: contentType || 'application/octet-stream'\n });\n\n const headers = {\n ...form.getHeaders(),\n 'X-Atlassian-Token': 'nocheck',\n 'Accept': 'application/json',\n };\n\n let response;\n if (existing) {\n // 기존 파일 업데이트 (POST to /data endpoint)\n response = await this.client.post(\n `/rest/api/content/${pageId}/child/attachment/${existing.id}/data`,\n form,\n { headers }\n );\n } else {\n // 신규 업로드\n response = await this.client.post(\n `/rest/api/content/${pageId}/child/attachment`,\n form,\n { headers }\n );\n }\n\n // Confluence API returns { results: [Attachment] } \n if (response.data && response.data.results && response.data.results.length > 0) {\n return response.data.results[0];\n }\n return response.data;\n }\n\n async getAttachments(pageId: string, filename?: string): Promise<ConfluenceAttachmentResponse[]> {\n const response = await this.client.get(`/rest/api/content/${pageId}/child/attachment`, {\n params: {\n filename,\n expand: 'version'\n }\n });\n return response.data.results;\n }\n\n async downloadAttachment(downloadUrl: string): Promise<Buffer> {\n const response = await this.client.get(downloadUrl, {\n responseType: 'arraybuffer'\n });\n return Buffer.from(response.data);\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceSpaceResponse } from '../types.js';\n\nexport class ConfluenceSpaceApi {\n constructor(private client: AxiosInstance) { }\n\n async getSpaces(type: string = 'global', start = 0, limit = 25): Promise<ConfluenceSpaceResponse[]> {\n const response = await this.client.get('/rest/api/space', {\n params: { type, start, limit }\n });\n return response.data.results;\n }\n\n async getSpace(spaceKey: string): Promise<ConfluenceSpaceResponse> {\n const response = await this.client.get(`/rest/api/space/${spaceKey}`);\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceSearchResponse } from '../types.js';\n\nexport class ConfluenceSearchApi {\n constructor(private client: AxiosInstance) { }\n\n async searchByCql(cql: string, start = 0, limit = 25, expand?: string[]): Promise<ConfluenceSearchResponse> {\n const expandParam = expand ? expand.join(',') : 'body.storage,version,space,metadata.labels';\n const response = await this.client.get('/rest/api/content/search', {\n params: {\n cql,\n start,\n limit,\n expand: expandParam\n }\n });\n\n return response.data;\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { ApiError, AuthError, NotFoundError, ConflictError } from './errors.js';\nimport { logger } from './logger.js';\nimport { ServiceConfig } from './types.js';\n\nexport function createHttpClient(config: ServiceConfig): AxiosInstance {\n const client = axios.create({\n baseURL: config.baseUrl,\n timeout: 30000, // 30초 타임아웃\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n // 요청 인터셉터: 인증 헤더 주입 및 로깅\n client.interceptors.request.use((reqConfig) => {\n // 1. 토큰 기반 Bearer 인증 (Confluence/JIRA PAT 권장 방식)\n if (config.auth.token && !reqConfig.headers.Authorization && !reqConfig.headers['PRIVATE-TOKEN']) {\n // GitLab은 PRIVATE-TOKEN 헤더를 선호하므로 제외\n reqConfig.headers.Authorization = `Bearer ${config.auth.token}`;\n }\n // 2. Basic 인증 (Username + Password/Token) - Bearer가 없을 때만 사용\n else if (config.auth.username && config.auth.token && !reqConfig.headers.Authorization) {\n const token = Buffer.from(`${config.auth.username}:${config.auth.token}`).toString('base64');\n reqConfig.headers.Authorization = `Basic ${token}`;\n }\n\n logger.debug(`[HTTP Request] ${reqConfig.method?.toUpperCase()} ${reqConfig.url}`, {\n headers: reqConfig.headers,\n params: reqConfig.params,\n data: reqConfig.data,\n });\n\n return reqConfig;\n });\n\n // 응답 인터셉터: 에러 핸들링 및 로깅\n client.interceptors.response.use(\n (response: AxiosResponse) => {\n logger.debug(`[HTTP Response] ${response.status} ${response.config.method?.toUpperCase()} ${response.config.url}`, {\n headers: response.headers,\n data: response.data,\n });\n return response;\n },\n (error: AxiosError) => {\n if (error.response) {\n const status = error.response.status;\n const method = error.config?.method?.toUpperCase();\n const url = error.config?.url;\n const message = (error.response.data as any)?.message || error.message;\n\n logger.error(`[HTTP Error] ${status} ${method} ${url}`, {\n message,\n responseData: error.response.data,\n requestHeaders: error.config?.headers,\n });\n\n // 상태 코드별 커스텀 에러 매핑\n if (status === 401 || status === 403) {\n throw new AuthError(`인증 실패: ${message}`);\n }\n if (status === 404) {\n throw new NotFoundError('리소스', url || 'unknown');\n }\n if (status === 409) {\n throw new ConflictError(`충돌 발생: ${message}`);\n }\n\n throw new ApiError(status, message, error.response.data);\n } else if (error.request) {\n logger.error(`[HTTP] No Response: ${error.message}`);\n throw new ApiError(0, `서버로부터 응답이 없습니다: ${error.message}`);\n } else {\n logger.error(`[HTTP] Request Error: ${error.message}`);\n throw new ApiError(0, `요청 설정 중 오류 발생: ${error.message}`);\n }\n }\n );\n\n return client;\n}\n","// TDE Collab 기본 에러 클래스\nexport class TdeCollabError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n// API 요청 실패 에러\nexport class ApiError extends TdeCollabError {\n constructor(\n public statusCode: number,\n message: string,\n public data?: any\n ) {\n super(`API 요청 실패 (${statusCode}): ${message}`);\n }\n}\n\n// 인증 실패 에러\nexport class AuthError extends TdeCollabError {\n constructor(message: string = '인증에 실패했습니다') {\n super(message);\n }\n}\n\n// 리소스 미발견 에러\nexport class NotFoundError extends TdeCollabError {\n constructor(resource: string, id: string) {\n super(`${resource} '${id}'를 찾을 수 없습니다`);\n }\n}\n\n// 리소스 충돌 에러\nexport class ConflictError extends TdeCollabError {\n constructor(message: string) {\n super(message);\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { ConfluenceConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createConfluenceClient(config: ConfluenceConfig): AxiosInstance {\n // Confluence API base context path handling\n // If user provides 'https://example.atlassian.net/wiki', we should use that.\n // API path usually appends '/rest/api/content' etc.\n\n // Ensure config.baseUrl includes '/wiki' if it's a cloud instance, usually users put it in env.\n // But standard is commonly base domain.\n // We'll trust the config for now, but client consumers should append specific endpoints.\n // Typically, Confluence API is at /wiki/rest/api if cloud, or /rest/api if server.\n // Let's assume baseUrl in config points to the root of the instance, e.g. https://site.atlassian.net/wiki\n\n return createHttpClient(config);\n}\n","import dotenv from 'dotenv';\nimport { ConfluenceConfig, GitlabConfig, JiraConfig } from './types.js';\nimport { logger } from './logger.js';\n\ndotenv.config();\n\n// 환경변수 조회 및 미설정 시 에러 발생\nfunction getEnvOrThrow(key: string, description: string): string {\n const value = process.env[key];\n if (!value) {\n const errorMsg = `환경변수 '${key}'가 설정되지 않았습니다. (${description})`;\n logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n return value;\n}\n\n// Confluence 설정 로드 (PAT 인증 권장)\nexport function loadConfluenceConfig(): ConfluenceConfig & { mermaidMacroName: string, inlineCodeStyle: string } {\n const baseUrl = getEnvOrThrow('CONFLUENCE_BASE_URL', 'Confluence 기본 URL');\n // PAT 사용 시 username은 불필요 (Basic Auth 사용 시에만 필요)\n const username = process.env.CONFLUENCE_USERNAME;\n const token = getEnvOrThrow('CONFLUENCE_API_TOKEN', 'Confluence PAT 토큰');\n \n // Mermaid 매크로 이름 (기본값: mermaiddiagram)\n const mermaidMacroName = process.env.CONFLUENCE_MERMAID_MACRO_NAME || 'mermaiddiagram';\n\n // 인라인 코드 강조 스타일 (기본값: 붉은색 굵게)\n const inlineCodeStyle = process.env.CONFLUENCE_INLINE_CODE_STYLE || 'color: #d04437; font-weight: bold;';\n\n return {\n baseUrl,\n auth: {\n username,\n token,\n },\n mermaidMacroName,\n inlineCodeStyle,\n };\n}\n\n// AI 서비스 설정 로드\nexport function loadAIConfig() {\n return {\n openaiApiKey: process.env.OPENAI_API_KEY,\n anthropicApiKey: process.env.ANTHROPIC_API_KEY,\n defaultProvider: process.env.AI_PROVIDER || 'openai',\n defaultModel: process.env.AI_MODEL || 'gpt-4o',\n };\n}\n\n// JIRA 설정 로드 (PAT 인증 권장)\nexport function loadJiraConfig(): JiraConfig {\n const baseUrl = getEnvOrThrow('JIRA_BASE_URL', 'JIRA 기본 URL');\n // PAT 사용 시 username은 불필요\n const username = process.env.JIRA_USERNAME;\n const token = getEnvOrThrow('JIRA_API_TOKEN', 'JIRA PAT 토큰');\n\n return {\n baseUrl,\n auth: {\n username,\n token,\n },\n };\n}\n\n// GitLab 설정 로드\nexport function loadGitlabConfig(): GitlabConfig {\n const baseUrl = process.env.GITLAB_BASE_URL || 'https://gitlab.com';\n const token = getEnvOrThrow('GITLAB_PRIVATE_TOKEN', 'GitLab Private Token');\n\n return {\n baseUrl,\n auth: {\n token,\n },\n };\n}\n","import MarkdownIt from 'markdown-it';\nimport { loadConfluenceConfig } from '../../common/config.js';\n\nexport class MarkdownToStorageConverter {\n private md: MarkdownIt;\n private mermaidMacroName: string;\n private inlineCodeStyle: string;\n\n constructor() {\n const config = loadConfluenceConfig();\n this.mermaidMacroName = config.mermaidMacroName;\n this.inlineCodeStyle = config.inlineCodeStyle;\n\n this.md = new MarkdownIt({\n html: true,\n linkify: true,\n breaks: true,\n xhtmlOut: true // Confluence XML 파서와의 호환성을 위해 XHTML 출력 활성화\n });\n\n // Custom renderer for code blocks\n this.md.renderer.rules.fence = (tokens, idx) => {\n const token = tokens[idx];\n const code = token.content.trim();\n const lang = token.info.trim().toLowerCase();\n\n // Mermaid 처리 (기존 로직 유지)\n if (lang === 'mermaid') {\n return `<ac:structured-macro ac:name=\"${this.mermaidMacroName}\" ac:schema-version=\"1\">\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n }\n\n // PlantUML 처리 → plantuml 매크로로 변환\n if (lang === 'plantuml') {\n return `<ac:structured-macro ac:name=\"plantuml\" ac:schema-version=\"1\">\n <ac:parameter ac:name=\"atlassian-macro-output-type\">INLINE</ac:parameter>\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n }\n\n // 일반 코드 블록\n return `<ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\">\n <ac:parameter ac:name=\"language\">${lang || 'text'}</ac:parameter>\n <ac:plain-text-body><![CDATA[${code}]]></ac:plain-text-body>\n</ac:structured-macro>`;\n };\n\n // Custom renderer for images\n this.md.renderer.rules.image = (tokens, idx, options, env, self) => {\n const token = tokens[idx];\n const src = token.attrGet('src') || '';\n const alt = token.content || '';\n\n // Handle URL vs Local file\n const isExternal = src.startsWith('http://') || src.startsWith('https://');\n\n // 외부 URL이면 URL 매크로, 아니면 첨부파일 매크로\n const altAttr = alt ? ` ac:alt=\"${this.md.utils.escapeHtml(alt)}\"` : '';\n if (isExternal) {\n return `<ac:image${altAttr}><ri:url ri:value=\"${src}\" /></ac:image>`;\n } else {\n // filename can just be the basename of the src path\n const filename = src.split('/').pop() || src;\n return `<ac:image${altAttr}><ri:attachment ri:filename=\"${filename}\" /></ac:image>`;\n }\n };\n\n // Custom renderer for inline code\n this.md.renderer.rules.code_inline = (tokens, idx) => {\n const token = tokens[idx];\n const content = this.md.utils.escapeHtml(token.content);\n return `<code style=\"${this.inlineCodeStyle}\">${content}</code>`;\n };\n\n // Task List 처리 (markdown-it 플러그인 없이 수동 처리 예시 - 실제로는 플러그인 도입 권장)\n }\n\n convert(markdown: string): string {\n return this.md.render(markdown);\n }\n\n extractLocalImages(markdown: string): string[] {\n const tokens = this.md.parse(markdown, {});\n const localImages = new Set<string>();\n\n const walk = (tokens: any[]) => {\n for (const token of tokens) {\n if (token.type === 'image') {\n const src = token.attrGet('src') || '';\n if (!src.startsWith('http://') && !src.startsWith('https://')) {\n localImages.add(src);\n }\n }\n if (token.children) {\n walk(token.children);\n }\n }\n };\n\n walk(tokens);\n return Array.from(localImages);\n }\n}\n","import TurndownService from 'turndown';\nimport { gfm } from 'turndown-plugin-gfm';\nimport { JSDOM } from 'jsdom';\n\nexport class StorageToMarkdownConverter {\n private turndown: TurndownService;\n\n constructor() {\n this.turndown = new TurndownService({\n headingStyle: 'atx',\n hr: '---',\n bulletListMarker: '-',\n codeBlockStyle: 'fenced'\n });\n\n this.turndown.use(gfm);\n this.setupRules();\n }\n\n private setupRules() {\n // Table 변환 규칙 강화 (정렬 정보 보존)\n this.turndown.addRule('tables', {\n filter: ['table'],\n replacement: (content, node) => {\n const element = node as HTMLTableElement;\n const rows = Array.from(element.rows);\n if (rows.length === 0) return '';\n\n let mdTable = '\\n\\n';\n\n rows.forEach((row, index) => {\n const cells = Array.from(row.cells);\n const cellContents = cells.map(cell => {\n // 셀 내부의 개행은 공백으로 치환하여 테이블 깨짐 방지\n return this.turndown.turndown(cell.innerHTML).replace(/\\n/g, ' ').trim();\n });\n\n mdTable += `| ${cellContents.join(' | ')} |\\n`;\n\n // 헤더 행 구분선 (정렬 정보 포함)\n if (index === 0) {\n const separators = cells.map(cell => {\n const style = (cell as HTMLElement).getAttribute('style') || '';\n const align = style.match(/text-align:\\s*(\\w+)/i)?.[1]?.toLowerCase();\n if (align === 'center') return ':---:';\n if (align === 'right') return '---:';\n if (align === 'left') return ':---';\n return '---';\n });\n mdTable += `| ${separators.join(' | ')} |\\n`;\n }\n });\n\n return mdTable + '\\n';\n }\n });\n\n // Confluence 매크로 (변환된 div 태그) 처리\n this.turndown.addRule('confluenceMacro', {\n filter: (node) => {\n return node.nodeName === 'DIV' && node.getAttribute('data-macro-name-tag') !== null;\n },\n replacement: (content, node) => {\n const element = node as HTMLElement;\n const macroName = element.getAttribute('data-macro-name');\n\n if (macroName === 'code') {\n const lang = element.querySelector('[data-macro-param-name=\"language\"]')?.textContent || 'text';\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n // 임시 CDATA 태그 제거\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`${lang}\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n if (macroName === 'mermaid' || macroName === 'mermaiddiagram' || macroName === 'capable-mermaid' || macroName === 'mermaid-macro') {\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n // 임시 CDATA 태그 제거\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`mermaid\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n if (macroName === 'plantuml') {\n let body = element.querySelector('[data-macro-body]')?.textContent || '';\n body = body.replace(/__CDATA_START__/g, '').replace(/__CDATA_END__/g, '');\n return `\\n\\`\\`\\`plantuml\\n${body.trim()}\\n\\`\\`\\`\\n`;\n }\n\n return `\\n<!-- Macro: ${macroName} -->\\n`;\n }\n });\n }\n\n convert(storageHtml: string, imageUrlMap?: Map<string, string>): string {\n if (!storageHtml) return '';\n\n // 1. Confluence 전용 태그를 표준 HTML 태그로 치환 (JSDOM 호환성)\n // CDATA 섹션을 텍스트로 보존하기 위해 임시 치환\n let processedHtml = storageHtml\n .replace(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/gi, (match, p1) => {\n return `__CDATA_START__${p1}__CDATA_END__`;\n })\n .replace(/<ac:structured-macro\\s+ac:name=\"([^\"]*)\"/gi, '<div data-macro-name-tag data-macro-name=\"$1\"')\n .replace(/<\\/ac:structured-macro>/gi, '</div>')\n .replace(/<ac:parameter\\s+ac:name=\"([^\"]*)\"/gi, '<div data-macro-param-tag data-macro-param-name=\"$1\"')\n .replace(/<\\/ac:parameter>/gi, '</div>')\n .replace(/<ac:plain-text-body>/gi, '<pre data-macro-body>')\n .replace(/<\\/ac:plain-text-body>/gi, '</pre>')\n .replace(/<ac:image([^>]*)>[\\s\\S]*?<ri:attachment\\s+ri:filename=\"([^\"]*)\"\\s*\\/?>[\\s\\S]*?<\\/ac:image>/gi, (match, attrs, filename) => {\n const altMatch = attrs.match(/ac:alt=\"([^\"]*)\"/i);\n const alt = altMatch ? altMatch[1] : filename;\n return `<img src=\"${filename}\" alt=\"${alt}\" />`;\n })\n .replace(/<ac:image([^>]*)>[\\s\\S]*?<ri:url\\s+ri:value=\"([^\"]*)\"\\s*\\/?>[\\s\\S]*?<\\/ac:image>/gi, (match, attrs, url) => {\n const altMatch = attrs.match(/ac:alt=\"([^\"]*)\"/i);\n const alt = altMatch ? altMatch[1] : '';\n return `<img src=\"${url}\" alt=\"${alt}\" />`;\n });\n\n // 2. JSDOM 파싱\n const dom = new JSDOM(processedHtml);\n const document = dom.window.document;\n\n // 이미지 처리\n if (imageUrlMap && imageUrlMap.size > 0) {\n const images = document.querySelectorAll('img');\n images.forEach(img => {\n const src = img.getAttribute('src');\n if (src && imageUrlMap.has(src)) {\n img.setAttribute('src', imageUrlMap.get(src)!);\n }\n });\n }\n\n // 3. Turndown 변환\n let markdown = this.turndown.turndown(document.body.innerHTML).trim();\n\n // 4. 헤딩 내 숫자 뒤 점 이스케이프 제거 (예: `## 1\\.` → `## 1.`)\n markdown = markdown.replace(/^(#{1,6}\\s.*?)\\\\\\./gm, '$1.');\n\n return markdown + '\\n';\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraIssueResponse, CreateIssueParams, UpdateIssueParams } from '../types.js';\n\nexport class JiraIssueApi {\n constructor(private client: AxiosInstance) {}\n\n async getIssue(issueKey: string, fields?: string[], expand?: string[]): Promise<JiraIssueResponse> {\n const params: Record<string, string> = {};\n if (fields && fields.length > 0) {\n params.fields = fields.join(',');\n }\n if (expand && expand.length > 0) {\n params.expand = expand.join(',');\n }\n const response = await this.client.get(`/rest/api/2/issue/${issueKey}`, { params });\n return response.data;\n }\n\n async createIssue(params: CreateIssueParams): Promise<JiraIssueResponse> {\n const fields: Record<string, unknown> = {\n project: { key: params.projectKey },\n summary: params.summary,\n issuetype: { name: params.issueType },\n };\n\n if (params.description) fields.description = params.description;\n if (params.assignee) fields.assignee = { name: params.assignee };\n if (params.priority) fields.priority = { name: params.priority };\n if (params.labels) fields.labels = params.labels;\n if (params.components) {\n fields.components = params.components.map((name) => ({ name }));\n }\n if (params.parentKey) {\n fields.parent = { key: params.parentKey };\n }\n if (params.customFields) {\n Object.assign(fields, params.customFields);\n }\n\n const response = await this.client.post('/rest/api/2/issue', { fields });\n return response.data;\n }\n\n async updateIssue(issueKey: string, params: UpdateIssueParams): Promise<void> {\n const fields: Record<string, unknown> = {};\n\n if (params.summary) fields.summary = params.summary;\n if (params.description !== undefined) fields.description = params.description;\n if (params.assignee !== undefined) fields.assignee = params.assignee ? { name: params.assignee } : null;\n if (params.priority) fields.priority = { name: params.priority };\n if (params.labels) fields.labels = params.labels;\n if (params.components) {\n fields.components = params.components.map((name) => ({ name }));\n }\n if (params.customFields) {\n Object.assign(fields, params.customFields);\n }\n\n await this.client.put(`/rest/api/2/issue/${issueKey}`, { fields });\n }\n\n async deleteIssue(issueKey: string, deleteSubtasks = false): Promise<void> {\n await this.client.delete(`/rest/api/2/issue/${issueKey}`, {\n params: { deleteSubtasks },\n });\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraSearchResponse } from '../types.js';\n\nexport class JiraSearchApi {\n constructor(private client: AxiosInstance) {}\n\n async searchByJql(\n jql: string,\n startAt = 0,\n maxResults = 50,\n fields?: string[],\n ): Promise<JiraSearchResponse> {\n const params: Record<string, unknown> = {\n jql,\n startAt,\n maxResults,\n };\n if (fields && fields.length > 0) {\n params.fields = fields.join(',');\n }\n const response = await this.client.get('/rest/api/2/search', { params });\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { JiraConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createJiraClient(config: JiraConfig): AxiosInstance {\n return createHttpClient(config);\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabMergeRequest, GitlabNote } from '../types.js';\n\nexport class GitlabMergeRequestApi {\n constructor(private client: AxiosInstance) {}\n\n async getMergeRequests(\n projectId: number,\n params?: { state?: string; scope?: string; labels?: string; perPage?: number },\n ): Promise<GitlabMergeRequest[]> {\n const response = await this.client.get(`/projects/${projectId}/merge_requests`, {\n params: {\n state: params?.state || 'opened',\n scope: params?.scope,\n labels: params?.labels,\n per_page: params?.perPage || 20,\n },\n });\n return response.data;\n }\n\n async getMergeRequest(projectId: number, mrIid: number): Promise<GitlabMergeRequest> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}`,\n );\n return response.data;\n }\n\n async getMergeRequestChanges(projectId: number, mrIid: number): Promise<GitlabMergeRequest> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/changes`,\n );\n return response.data;\n }\n\n async createMergeRequest(\n projectId: number,\n data: {\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_id?: number;\n reviewer_ids?: number[];\n labels?: string;\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.post(`/projects/${projectId}/merge_requests`, data);\n return response.data;\n }\n\n async updateMergeRequest(\n projectId: number,\n mrIid: number,\n data: {\n title?: string;\n description?: string;\n assignee_id?: number;\n reviewer_ids?: number[];\n labels?: string;\n state_event?: 'close' | 'reopen';\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.put(\n `/projects/${projectId}/merge_requests/${mrIid}`,\n data,\n );\n return response.data;\n }\n\n async mergeMergeRequest(\n projectId: number,\n mrIid: number,\n params?: {\n merge_commit_message?: string;\n squash?: boolean;\n should_remove_source_branch?: boolean;\n },\n ): Promise<GitlabMergeRequest> {\n const response = await this.client.put(\n `/projects/${projectId}/merge_requests/${mrIid}/merge`,\n params,\n );\n return response.data;\n }\n\n async getMergeRequestNotes(projectId: number, mrIid: number): Promise<GitlabNote[]> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/notes`,\n );\n return response.data;\n }\n\n async addMergeRequestNote(\n projectId: number,\n mrIid: number,\n body: string,\n ): Promise<GitlabNote> {\n const response = await this.client.post(\n `/projects/${projectId}/merge_requests/${mrIid}/notes`,\n { body },\n );\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabPipeline, GitlabJob } from '../types.js';\n\nexport class GitlabPipelineApi {\n constructor(private client: AxiosInstance) {}\n\n async getPipelines(\n projectId: number,\n params?: { status?: string; ref?: string; perPage?: number },\n ): Promise<GitlabPipeline[]> {\n const response = await this.client.get(`/projects/${projectId}/pipelines`, {\n params: {\n status: params?.status,\n ref: params?.ref,\n per_page: params?.perPage || 20,\n },\n });\n return response.data;\n }\n\n async getPipeline(projectId: number, pipelineId: number): Promise<GitlabPipeline> {\n const response = await this.client.get(\n `/projects/${projectId}/pipelines/${pipelineId}`,\n );\n return response.data;\n }\n\n async getPipelineJobs(projectId: number, pipelineId: number): Promise<GitlabJob[]> {\n const response = await this.client.get(\n `/projects/${projectId}/pipelines/${pipelineId}/jobs`,\n );\n return response.data;\n }\n\n async getMergeRequestPipelines(\n projectId: number,\n mrIid: number,\n ): Promise<GitlabPipeline[]> {\n const response = await this.client.get(\n `/projects/${projectId}/merge_requests/${mrIid}/pipelines`,\n );\n return response.data;\n }\n}\n","import { AxiosInstance } from 'axios';\nimport { GitlabConfig } from '../../common/types.js';\nimport { createHttpClient } from '../../common/http-client.js';\n\nexport function createGitlabClient(config: GitlabConfig): AxiosInstance {\n const client = createHttpClient({\n ...config,\n baseUrl: `${config.baseUrl}/api/v4`,\n });\n\n // GitLab Self-hosted는 PRIVATE-TOKEN 헤더 사용\n client.defaults.headers.common['PRIVATE-TOKEN'] = config.auth.token!;\n\n return client;\n}\n"],"mappings":"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","names":["tokens"]}
|
|
File without changes
|
|
File without changes
|