@decencia/ch-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/client.d.ts +15 -0
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/client.js +117 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/commands/archives.d.ts +3 -0
  6. package/dist/commands/archives.d.ts.map +1 -0
  7. package/dist/commands/archives.js +371 -0
  8. package/dist/commands/archives.js.map +1 -0
  9. package/dist/commands/auth.d.ts +3 -0
  10. package/dist/commands/auth.d.ts.map +1 -0
  11. package/dist/commands/auth.js +149 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/dashboard.d.ts +3 -0
  14. package/dist/commands/dashboard.d.ts.map +1 -0
  15. package/dist/commands/dashboard.js +115 -0
  16. package/dist/commands/dashboard.js.map +1 -0
  17. package/dist/commands/db-schema.d.ts +3 -0
  18. package/dist/commands/db-schema.d.ts.map +1 -0
  19. package/dist/commands/db-schema.js +76 -0
  20. package/dist/commands/db-schema.js.map +1 -0
  21. package/dist/commands/dev-status.d.ts +3 -0
  22. package/dist/commands/dev-status.d.ts.map +1 -0
  23. package/dist/commands/dev-status.js +175 -0
  24. package/dist/commands/dev-status.js.map +1 -0
  25. package/dist/commands/init.d.ts +3 -0
  26. package/dist/commands/init.d.ts.map +1 -0
  27. package/dist/commands/init.js +124 -0
  28. package/dist/commands/init.js.map +1 -0
  29. package/dist/commands/invitations.d.ts +3 -0
  30. package/dist/commands/invitations.d.ts.map +1 -0
  31. package/dist/commands/invitations.js +48 -0
  32. package/dist/commands/invitations.js.map +1 -0
  33. package/dist/commands/members.d.ts +3 -0
  34. package/dist/commands/members.d.ts.map +1 -0
  35. package/dist/commands/members.js +93 -0
  36. package/dist/commands/members.js.map +1 -0
  37. package/dist/commands/notifications.d.ts +3 -0
  38. package/dist/commands/notifications.d.ts.map +1 -0
  39. package/dist/commands/notifications.js +163 -0
  40. package/dist/commands/notifications.js.map +1 -0
  41. package/dist/commands/prd.d.ts +3 -0
  42. package/dist/commands/prd.d.ts.map +1 -0
  43. package/dist/commands/prd.js +74 -0
  44. package/dist/commands/prd.js.map +1 -0
  45. package/dist/commands/projects.d.ts +3 -0
  46. package/dist/commands/projects.d.ts.map +1 -0
  47. package/dist/commands/projects.js +215 -0
  48. package/dist/commands/projects.js.map +1 -0
  49. package/dist/commands/qna.d.ts +3 -0
  50. package/dist/commands/qna.d.ts.map +1 -0
  51. package/dist/commands/qna.js +211 -0
  52. package/dist/commands/qna.js.map +1 -0
  53. package/dist/commands/specs.d.ts +3 -0
  54. package/dist/commands/specs.d.ts.map +1 -0
  55. package/dist/commands/specs.js +277 -0
  56. package/dist/commands/specs.js.map +1 -0
  57. package/dist/commands/sprints.d.ts +3 -0
  58. package/dist/commands/sprints.d.ts.map +1 -0
  59. package/dist/commands/sprints.js +262 -0
  60. package/dist/commands/sprints.js.map +1 -0
  61. package/dist/commands/sqa.d.ts +3 -0
  62. package/dist/commands/sqa.d.ts.map +1 -0
  63. package/dist/commands/sqa.js +452 -0
  64. package/dist/commands/sqa.js.map +1 -0
  65. package/dist/config.d.ts +28 -0
  66. package/dist/config.d.ts.map +1 -0
  67. package/dist/config.js +115 -0
  68. package/dist/config.js.map +1 -0
  69. package/dist/index.d.ts +3 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +97 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/output.d.ts +13 -0
  74. package/dist/output.d.ts.map +1 -0
  75. package/dist/output.js +174 -0
  76. package/dist/output.js.map +1 -0
  77. package/dist/utils.d.ts +2 -0
  78. package/dist/utils.d.ts.map +1 -0
  79. package/dist/utils.js +7 -0
  80. package/dist/utils.js.map +1 -0
  81. package/package.json +33 -0
  82. package/src/client.ts +137 -0
  83. package/src/commands/archives.ts +334 -0
  84. package/src/commands/auth.ts +154 -0
  85. package/src/commands/dashboard.ts +112 -0
  86. package/src/commands/db-schema.ts +74 -0
  87. package/src/commands/dev-status.ts +166 -0
  88. package/src/commands/init.ts +92 -0
  89. package/src/commands/members.ts +92 -0
  90. package/src/commands/notifications.ts +169 -0
  91. package/src/commands/prd.ts +72 -0
  92. package/src/commands/projects.ts +207 -0
  93. package/src/commands/qna.ts +205 -0
  94. package/src/commands/specs.ts +257 -0
  95. package/src/commands/sprints.ts +255 -0
  96. package/src/commands/sqa.ts +422 -0
  97. package/src/config.ts +98 -0
  98. package/src/index.ts +69 -0
  99. package/src/output.ts +186 -0
  100. package/src/utils.ts +3 -0
  101. package/tsconfig.json +18 -0
package/dist/index.js ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander_1 = require("commander");
38
+ const path = __importStar(require("path"));
39
+ const fs = __importStar(require("fs"));
40
+ const auth_1 = require("./commands/auth");
41
+ const init_1 = require("./commands/init");
42
+ const projects_1 = require("./commands/projects");
43
+ const specs_1 = require("./commands/specs");
44
+ const sprints_1 = require("./commands/sprints");
45
+ const qna_1 = require("./commands/qna");
46
+ const sqa_1 = require("./commands/sqa");
47
+ const archives_1 = require("./commands/archives");
48
+ const members_1 = require("./commands/members");
49
+ const dev_status_1 = require("./commands/dev-status");
50
+ const prd_1 = require("./commands/prd");
51
+ const db_schema_1 = require("./commands/db-schema");
52
+ const notifications_1 = require("./commands/notifications");
53
+ const dashboard_1 = require("./commands/dashboard");
54
+ // Read version from package.json
55
+ function getVersion() {
56
+ try {
57
+ const pkgPath = path.join(__dirname, '..', 'package.json');
58
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
59
+ return pkg.version || '1.0.0';
60
+ }
61
+ catch {
62
+ return '1.0.0';
63
+ }
64
+ }
65
+ const program = new commander_1.Command();
66
+ program
67
+ .name('ch')
68
+ .description('Decencia Communication Channel CLI')
69
+ .version(getVersion(), '-v, --version', '버전 표시')
70
+ .option('--json', 'JSON 형식으로 출력')
71
+ .option('--table', '테이블 형식으로 출력 (기본값)')
72
+ .option('--csv', 'CSV 형식으로 출력')
73
+ .option('--project <projectId>', '프로젝트 ID 오버라이드')
74
+ .option('--verbose', '상세 로그 출력')
75
+ .option('--quiet', '결과만 출력 (스크립팅용)')
76
+ .option('--dry-run', '쓰기 작업 시뮬레이션');
77
+ // Register all command modules
78
+ (0, init_1.registerInitCommand)(program);
79
+ (0, auth_1.registerAuthCommand)(program);
80
+ (0, projects_1.registerProjectsCommand)(program);
81
+ (0, specs_1.registerSpecsCommand)(program);
82
+ (0, sprints_1.registerSprintsCommand)(program);
83
+ (0, qna_1.registerQnaCommand)(program);
84
+ (0, sqa_1.registerSqaCommand)(program);
85
+ (0, archives_1.registerArchivesCommand)(program);
86
+ (0, members_1.registerMembersCommand)(program);
87
+ (0, dev_status_1.registerDevStatusCommand)(program);
88
+ (0, prd_1.registerPrdCommand)(program);
89
+ (0, db_schema_1.registerDbSchemaCommand)(program);
90
+ (0, notifications_1.registerNotificationsCommand)(program);
91
+ (0, dashboard_1.registerDashboardCommand)(program);
92
+ // Parse and execute
93
+ program.parseAsync(process.argv).catch((err) => {
94
+ console.error(err);
95
+ process.exit(1);
96
+ });
97
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,2CAA6B;AAC7B,uCAAyB;AAEzB,0CAAsD;AACtD,0CAAsD;AACtD,kDAA8D;AAC9D,4CAAwD;AACxD,gDAA4D;AAC5D,wCAAoD;AACpD,wCAAoD;AACpD,kDAA8D;AAC9D,gDAA4D;AAC5D,sDAAiE;AACjE,wCAAoD;AACpD,oDAA+D;AAE/D,4DAAwE;AACxE,oDAAgE;AAEhE,iCAAiC;AACjC,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,UAAU,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC;KAC/C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC;KAChC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC;KACtC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;KAC9B,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC;KAC/B,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC;KACnC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAEtC,+BAA+B;AAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,qCAAwB,EAAC,OAAO,CAAC,CAAC;AAClC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,mCAAuB,EAAC,OAAO,CAAC,CAAC;AAEjC,IAAA,4CAA4B,EAAC,OAAO,CAAC,CAAC;AACtC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;AAElC,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface OutputOptions {
2
+ json?: boolean;
3
+ table?: boolean;
4
+ csv?: boolean;
5
+ quiet?: boolean;
6
+ }
7
+ export declare function formatOutput(data: any, options?: OutputOptions): void;
8
+ export declare function printTable(headers: string[], rows: string[][]): void;
9
+ export declare function printError(message: string): void;
10
+ export declare function printSuccess(message: string): void;
11
+ export declare function printWarning(message: string): void;
12
+ export declare function printInfo(message: string): void;
13
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,aAAkB,GAAG,IAAI,CA+CzE;AA4FD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAWpE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAUD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C"}
package/dist/output.js ADDED
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatOutput = formatOutput;
7
+ exports.printTable = printTable;
8
+ exports.printError = printError;
9
+ exports.printSuccess = printSuccess;
10
+ exports.printWarning = printWarning;
11
+ exports.printInfo = printInfo;
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const cli_table3_1 = __importDefault(require("cli-table3"));
14
+ const client_1 = require("./client");
15
+ function formatOutput(data, options = {}) {
16
+ if (options.quiet) {
17
+ // In quiet mode, only output raw JSON for piping
18
+ console.log(JSON.stringify(data));
19
+ return;
20
+ }
21
+ if (options.json) {
22
+ console.log(JSON.stringify(data, null, 2));
23
+ return;
24
+ }
25
+ if (options.csv) {
26
+ printCsv(data);
27
+ return;
28
+ }
29
+ // Default: table or pretty print
30
+ if (Array.isArray(data)) {
31
+ if (data.length === 0) {
32
+ console.log(chalk_1.default.yellow('데이터가 없습니다.'));
33
+ return;
34
+ }
35
+ printAutoTable(data);
36
+ }
37
+ else if (data && typeof data === 'object') {
38
+ // Check if it's a paginated response
39
+ if (data.data && Array.isArray(data.data)) {
40
+ if (data.data.length === 0) {
41
+ console.log(chalk_1.default.yellow('데이터가 없습니다.'));
42
+ }
43
+ else {
44
+ printAutoTable(data.data);
45
+ }
46
+ if (data.pagination) {
47
+ const p = data.pagination;
48
+ console.log(chalk_1.default.gray(`\n페이지 ${p.page}/${p.totalPages} (총 ${p.total}건)`));
49
+ }
50
+ }
51
+ else {
52
+ // Single object - print key-value pairs
53
+ printKeyValue(data);
54
+ }
55
+ }
56
+ else {
57
+ console.log(data);
58
+ }
59
+ }
60
+ function printAutoTable(rows) {
61
+ if (rows.length === 0)
62
+ return;
63
+ const keys = Object.keys(rows[0]);
64
+ // Limit columns to avoid overly wide tables
65
+ const displayKeys = keys.slice(0, 8);
66
+ const table = new cli_table3_1.default({
67
+ head: displayKeys.map((k) => chalk_1.default.cyan(k)),
68
+ style: { head: [], border: [] },
69
+ wordWrap: true,
70
+ });
71
+ for (const row of rows) {
72
+ table.push(displayKeys.map((k) => {
73
+ const val = row[k];
74
+ if (val === null || val === undefined)
75
+ return '';
76
+ if (typeof val === 'object')
77
+ return JSON.stringify(val).substring(0, 50);
78
+ const str = String(val);
79
+ return str.length > 60 ? str.substring(0, 57) + '...' : str;
80
+ }));
81
+ }
82
+ console.log(table.toString());
83
+ }
84
+ function printKeyValue(obj) {
85
+ const table = new cli_table3_1.default({
86
+ style: { head: [], border: [] },
87
+ });
88
+ for (const [key, value] of Object.entries(obj)) {
89
+ let display;
90
+ if (value === null || value === undefined) {
91
+ display = chalk_1.default.gray('(없음)');
92
+ }
93
+ else if (Array.isArray(value)) {
94
+ display = value.length > 0
95
+ ? JSON.stringify(value, null, 2)
96
+ : chalk_1.default.gray('(비어있음)');
97
+ }
98
+ else if (typeof value === 'object') {
99
+ display = JSON.stringify(value, null, 2);
100
+ }
101
+ else {
102
+ display = String(value);
103
+ }
104
+ table.push({ [chalk_1.default.cyan(key)]: display });
105
+ }
106
+ console.log(table.toString());
107
+ }
108
+ function printCsv(data) {
109
+ let rows;
110
+ if (Array.isArray(data)) {
111
+ rows = data;
112
+ }
113
+ else if (data && data.data && Array.isArray(data.data)) {
114
+ rows = data.data;
115
+ }
116
+ else {
117
+ // Single object
118
+ rows = [data];
119
+ }
120
+ if (rows.length === 0)
121
+ return;
122
+ const keys = Object.keys(rows[0]);
123
+ // CSV header
124
+ console.log(keys.map(escapeCsvField).join(','));
125
+ // CSV rows
126
+ for (const row of rows) {
127
+ console.log(keys
128
+ .map((k) => {
129
+ const val = row[k];
130
+ if (val === null || val === undefined)
131
+ return '';
132
+ if (typeof val === 'object')
133
+ return escapeCsvField(JSON.stringify(val));
134
+ return escapeCsvField(String(val));
135
+ })
136
+ .join(','));
137
+ }
138
+ }
139
+ function escapeCsvField(field) {
140
+ if (field.includes(',') || field.includes('"') || field.includes('\n')) {
141
+ return `"${field.replace(/"/g, '""')}"`;
142
+ }
143
+ return field;
144
+ }
145
+ function printTable(headers, rows) {
146
+ const table = new cli_table3_1.default({
147
+ head: headers.map((h) => chalk_1.default.cyan(h)),
148
+ style: { head: [], border: [] },
149
+ });
150
+ for (const row of rows) {
151
+ table.push(row);
152
+ }
153
+ console.log(table.toString());
154
+ }
155
+ function printError(message) {
156
+ console.error(chalk_1.default.red(`오류: ${message}`));
157
+ }
158
+ function projectPrefix() {
159
+ const ctx = (0, client_1.getLastProjectContext)();
160
+ if (ctx?.projectName) {
161
+ return chalk_1.default.cyan(`[${ctx.projectName}] `);
162
+ }
163
+ return '';
164
+ }
165
+ function printSuccess(message) {
166
+ console.log(projectPrefix() + chalk_1.default.green(message));
167
+ }
168
+ function printWarning(message) {
169
+ console.log(projectPrefix() + chalk_1.default.yellow(message));
170
+ }
171
+ function printInfo(message) {
172
+ console.log(projectPrefix() + chalk_1.default.blue(message));
173
+ }
174
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function parseCommaSeparated(value: string): string[];
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3D"}
package/dist/utils.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseCommaSeparated = parseCommaSeparated;
4
+ function parseCommaSeparated(value) {
5
+ return value.split(',').map((v) => v.trim()).filter(Boolean);
6
+ }
7
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;AAAA,kDAEC;AAFD,SAAgB,mBAAmB,CAAC,KAAa;IAC/C,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@decencia/ch-cli",
3
+ "version": "1.0.0",
4
+ "description": "Decencia Communication Channel CLI",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "ch": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsc --watch",
12
+ "start": "node dist/index.js",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "decencia",
17
+ "cli",
18
+ "communication-channel"
19
+ ],
20
+ "author": "Decencia Soft",
21
+ "license": "ISC",
22
+ "dependencies": {
23
+ "axios": "^1.15.2",
24
+ "chalk": "^4.1.2",
25
+ "cli-table3": "^0.6.5",
26
+ "commander": "^14.0.3",
27
+ "form-data": "^4.0.5"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^25.6.0",
31
+ "typescript": "^6.0.3"
32
+ }
33
+ }
package/src/client.ts ADDED
@@ -0,0 +1,137 @@
1
+ import axios, { AxiosInstance, AxiosError } from 'axios';
2
+ import { loadConfig, getProjectContext, ProjectContext } from './config';
3
+ import { printError } from './output';
4
+
5
+ export interface ClientOptions {
6
+ apiKey?: string;
7
+ projectId?: string;
8
+ apiUrl?: string;
9
+ verbose?: boolean;
10
+ }
11
+
12
+ let _lastProjectContext: ProjectContext | null = null;
13
+
14
+ export function getLastProjectContext(): ProjectContext | null {
15
+ return _lastProjectContext;
16
+ }
17
+
18
+ export function createClient(options: ClientOptions = {}): AxiosInstance {
19
+ const config = loadConfig();
20
+
21
+ const apiKey = options.apiKey || config?.apiKey;
22
+ const projectCtx = getProjectContext(options.projectId);
23
+ _lastProjectContext = projectCtx;
24
+ const projectId = projectCtx?.projectId;
25
+ const apiUrl = options.apiUrl || config?.apiUrl || 'https://ch-api-618529407342.asia-northeast3.run.app';
26
+
27
+ if (!apiKey) {
28
+ printError('API Key가 설정되지 않았습니다. "ch auth login" 명령어로 로그인하세요.');
29
+ process.exit(1);
30
+ }
31
+
32
+ const instance = axios.create({
33
+ baseURL: apiUrl,
34
+ timeout: 30000,
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ },
38
+ });
39
+
40
+ // Request interceptor: inject auth headers
41
+ instance.interceptors.request.use((req) => {
42
+ req.headers['Authorization'] = `Bearer ${apiKey}`;
43
+ if (projectId) {
44
+ req.headers['X-Project-Id'] = projectId;
45
+ }
46
+ if (options.verbose) {
47
+ const method = (req.method || 'GET').toUpperCase();
48
+ const url = `${req.baseURL}${req.url}`;
49
+ console.error(`[DEBUG] ${method} ${url}`);
50
+ if (req.params && Object.keys(req.params).length > 0) {
51
+ console.error(`[DEBUG] Params: ${JSON.stringify(req.params)}`);
52
+ }
53
+ if (req.data) {
54
+ console.error(`[DEBUG] Body: ${JSON.stringify(req.data)}`);
55
+ }
56
+ }
57
+ return req;
58
+ });
59
+
60
+ // Response error interceptor
61
+ instance.interceptors.response.use(
62
+ (response) => response,
63
+ (error: AxiosError<{ message?: string; error?: string }>) => {
64
+ if (!error.response) {
65
+ printError('서버에 연결할 수 없습니다. API URL과 네트워크 상태를 확인하세요.');
66
+ process.exit(1);
67
+ }
68
+
69
+ const status = error.response.status;
70
+ const data = error.response.data;
71
+ const serverMessage = data?.message || data?.error || '';
72
+
73
+ switch (status) {
74
+ case 400:
75
+ printError(`잘못된 요청입니다: ${serverMessage}`);
76
+ break;
77
+ case 401:
78
+ printError(`인증 실패: API Key가 유효하지 않거나 만료되었습니다. ${serverMessage}`);
79
+ break;
80
+ case 403:
81
+ printError(`권한이 없습니다: ${serverMessage}`);
82
+ break;
83
+ case 404:
84
+ printError(`리소스를 찾을 수 없습니다: ${serverMessage}`);
85
+ break;
86
+ case 409:
87
+ printError(`충돌: ${serverMessage}`);
88
+ break;
89
+ case 410:
90
+ printError(`만료됨: ${serverMessage}`);
91
+ break;
92
+ case 500:
93
+ printError(`서버 내부 오류: ${serverMessage}`);
94
+ break;
95
+ default:
96
+ printError(`오류 (${status}): ${serverMessage}`);
97
+ }
98
+
99
+ return Promise.reject(error);
100
+ }
101
+ );
102
+
103
+ return instance;
104
+ }
105
+
106
+ /**
107
+ * Create a client that doesn't require projectId (for invitation endpoints)
108
+ */
109
+ export function createUnauthClient(options: ClientOptions = {}): AxiosInstance {
110
+ const config = loadConfig();
111
+ const apiUrl = options.apiUrl || config?.apiUrl || 'https://ch-api-618529407342.asia-northeast3.run.app';
112
+
113
+ const instance = axios.create({
114
+ baseURL: apiUrl,
115
+ timeout: 30000,
116
+ headers: {
117
+ 'Content-Type': 'application/json',
118
+ },
119
+ });
120
+
121
+ instance.interceptors.response.use(
122
+ (response) => response,
123
+ (error: AxiosError<{ message?: string; error?: string }>) => {
124
+ if (!error.response) {
125
+ printError('서버에 연결할 수 없습니다.');
126
+ process.exit(1);
127
+ }
128
+ const status = error.response.status;
129
+ const data = error.response.data;
130
+ const serverMessage = data?.message || data?.error || '';
131
+ printError(`오류 (${status}): ${serverMessage}`);
132
+ return Promise.reject(error);
133
+ }
134
+ );
135
+
136
+ return instance;
137
+ }