swagshot 0.1.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 (68) hide show
  1. package/README.md +182 -0
  2. package/dist/cli/commands/config.d.ts +2 -0
  3. package/dist/cli/commands/config.d.ts.map +1 -0
  4. package/dist/cli/commands/config.js +34 -0
  5. package/dist/cli/commands/config.js.map +1 -0
  6. package/dist/cli/commands/generate.d.ts +9 -0
  7. package/dist/cli/commands/generate.d.ts.map +1 -0
  8. package/dist/cli/commands/generate.js +74 -0
  9. package/dist/cli/commands/generate.js.map +1 -0
  10. package/dist/cli/commands/init.d.ts +4 -0
  11. package/dist/cli/commands/init.d.ts.map +1 -0
  12. package/dist/cli/commands/init.js +104 -0
  13. package/dist/cli/commands/init.js.map +1 -0
  14. package/dist/cli/commands/list.d.ts +6 -0
  15. package/dist/cli/commands/list.d.ts.map +1 -0
  16. package/dist/cli/commands/list.js +26 -0
  17. package/dist/cli/commands/list.js.map +1 -0
  18. package/dist/cli/index.d.ts +3 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +40 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +71 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib/codeGenerator.d.ts +6 -0
  27. package/dist/lib/codeGenerator.d.ts.map +1 -0
  28. package/dist/lib/codeGenerator.js +331 -0
  29. package/dist/lib/codeGenerator.js.map +1 -0
  30. package/dist/lib/configManager.d.ts +8 -0
  31. package/dist/lib/configManager.d.ts.map +1 -0
  32. package/dist/lib/configManager.js +59 -0
  33. package/dist/lib/configManager.js.map +1 -0
  34. package/dist/lib/detectStructure.d.ts +3 -0
  35. package/dist/lib/detectStructure.d.ts.map +1 -0
  36. package/dist/lib/detectStructure.js +65 -0
  37. package/dist/lib/detectStructure.js.map +1 -0
  38. package/dist/lib/fetchSwagger.d.ts +5 -0
  39. package/dist/lib/fetchSwagger.d.ts.map +1 -0
  40. package/dist/lib/fetchSwagger.js +57 -0
  41. package/dist/lib/fetchSwagger.js.map +1 -0
  42. package/dist/lib/types.d.ts +101 -0
  43. package/dist/lib/types.d.ts.map +1 -0
  44. package/dist/lib/types.js +3 -0
  45. package/dist/lib/types.js.map +1 -0
  46. package/dist/tools/configUpdate.d.ts +2 -0
  47. package/dist/tools/configUpdate.d.ts.map +1 -0
  48. package/dist/tools/configUpdate.js +25 -0
  49. package/dist/tools/configUpdate.js.map +1 -0
  50. package/dist/tools/setup.d.ts +2 -0
  51. package/dist/tools/setup.d.ts.map +1 -0
  52. package/dist/tools/setup.js +63 -0
  53. package/dist/tools/setup.js.map +1 -0
  54. package/dist/tools/sync.d.ts +2 -0
  55. package/dist/tools/sync.d.ts.map +1 -0
  56. package/dist/tools/sync.js +87 -0
  57. package/dist/tools/sync.js.map +1 -0
  58. package/package.json +39 -0
  59. package/src/cli/commands/config.ts +33 -0
  60. package/src/cli/commands/generate.ts +90 -0
  61. package/src/cli/commands/init.ts +76 -0
  62. package/src/cli/commands/list.ts +31 -0
  63. package/src/cli/index.ts +44 -0
  64. package/src/lib/codeGenerator.ts +376 -0
  65. package/src/lib/configManager.ts +54 -0
  66. package/src/lib/detectStructure.ts +66 -0
  67. package/src/lib/fetchSwagger.ts +52 -0
  68. package/src/lib/types.ts +102 -0
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # swagshot
2
+
3
+ Swagger/OpenAPI 스펙으로 TypeScript API 함수와 타입 정의를 자동 생성하는 CLI 툴.
4
+
5
+ 프로젝트 구조를 자동 감지해서 기존 코드 스타일에 맞는 코드를 생성합니다.
6
+
7
+ ## 특징
8
+
9
+ - **프로젝트 구조 자동 감지** — API 폴더, 타입 폴더, axios 인스턴스, react-query 등
10
+ - **Swagger 2.0 / OpenAPI 3.0** 모두 지원 (Spring Boot, NestJS 등)
11
+ - **axios / fetch** 스타일 코드 생성
12
+ - **커스텀 axios 인스턴스** 자동 연결
13
+ - deprecated 엔드포인트 자동 제외
14
+
15
+ ## 설치 없이 바로 사용
16
+
17
+ ```bash
18
+ npx swagshot <command>
19
+ ```
20
+
21
+ ## 사용법
22
+
23
+ ### 1. 프로젝트 초기 설정 (처음 한 번만)
24
+
25
+ 프로젝트 루트에서 실행:
26
+
27
+ ```bash
28
+ cd /your/project
29
+ npx swagshot init
30
+ ```
31
+
32
+ 프로젝트 구조를 자동으로 감지하고 `.swagshot.json` 설정 파일을 생성합니다.
33
+
34
+ ```
35
+ 👋 swagshot 초기 설정을 시작합니다.
36
+ 📂 프로젝트 루트: /your/project
37
+
38
+ 자동 감지 결과를 확인해주세요. Enter를 누르면 기본값 사용:
39
+
40
+ Swagger JSON URL (기본값: ):
41
+ API 함수 폴더 (기본값: src/api):
42
+ 타입 정의 폴더 (기본값: src/types):
43
+ ...
44
+ ```
45
+
46
+ ### 2. 컨트롤러 목록 확인
47
+
48
+ ```bash
49
+ npx swagshot list --url "https://api.example.com/v2/api-docs"
50
+ ```
51
+
52
+ ```
53
+ 📋 컨트롤러 태그 목록 (12개):
54
+
55
+ 1. auth-controller
56
+ 2. payment-controller
57
+ 3. order-controller
58
+ ...
59
+ ```
60
+
61
+ ### 3. 코드 생성
62
+
63
+ ```bash
64
+ # 특정 컨트롤러만
65
+ npx swagshot generate --url "https://api.example.com/v2/api-docs" --tag payment-controller
66
+
67
+ # 전체 생성
68
+ npx swagshot generate --url "https://api.example.com/v2/api-docs" --all
69
+
70
+ # deprecated 포함
71
+ npx swagshot generate --url "https://api.example.com/v2/api-docs" --tag payment-controller --include-deprecated
72
+ ```
73
+
74
+ ### 4. 설정 변경
75
+
76
+ ```bash
77
+ npx swagshot config set apiDir src/services
78
+ npx swagshot config set httpClient fetch
79
+ npx swagshot config set axiosInstance src/lib/fetcher.ts
80
+ ```
81
+
82
+ ## 생성 결과 예시
83
+
84
+ `payment-controller` 기준으로 두 파일이 생성됩니다.
85
+
86
+ **`src/types/payment.ts`**
87
+ ```typescript
88
+ // Auto-generated by swagshot
89
+ // Tag: payment-controller
90
+ // Do not edit manually
91
+
92
+ export interface PaymentHistoryResponse {
93
+ id: number;
94
+ price: number;
95
+ status: string;
96
+ createdAt: string;
97
+ }
98
+
99
+ export interface GetHistoryUsingGETParams {
100
+ startDateTime: string;
101
+ endDateTime: string;
102
+ payment_product_types?: string[];
103
+ }
104
+ ```
105
+
106
+ **`src/api/payment.ts`**
107
+ ```typescript
108
+ // Auto-generated by swagshot
109
+ // Tag: payment-controller
110
+ // Do not edit manually
111
+
112
+ import fetcher from '../lib/fetcher';
113
+ import type { PaymentHistoryResponse, GetHistoryUsingGETParams } from '../types/payment';
114
+
115
+ /** 결제 히스토리 조회 */
116
+ export const getHistory = (params: GetHistoryUsingGETParams) =>
117
+ fetcher.get<PaymentHistoryResponse[]>(`/v2/payments/history`, { params });
118
+
119
+ /** 결제 히스토리 상세 조회 */
120
+ export const getPaymentHistory = (paymentHistoryId: number) =>
121
+ fetcher.get<PaymentHistoryResponse>(`/v2/payments/history/${paymentHistoryId}`);
122
+ ```
123
+
124
+ ## 설정 파일 (.swagshot.json)
125
+
126
+ ```json
127
+ {
128
+ "version": "1",
129
+ "project": {
130
+ "root": "/your/project",
131
+ "apiDir": "src/api",
132
+ "typesDir": "src/types",
133
+ "hooksDir": null,
134
+ "outputDir": "src/api"
135
+ },
136
+ "style": {
137
+ "httpClient": "axios",
138
+ "axiosInstance": "src/lib/fetcher.ts",
139
+ "queryLibrary": "react-query",
140
+ "namingConvention": "camelCase"
141
+ },
142
+ "swagger": {
143
+ "url": "https://api.example.com/v2/api-docs"
144
+ }
145
+ }
146
+ ```
147
+
148
+ > `.swagshot.json`은 `.gitignore`에 추가를 권장합니다.
149
+
150
+ ## Swagger JSON URL 찾는 법
151
+
152
+ Swagger UI 페이지 URL이 아닌, JSON 스펙 URL이 필요합니다.
153
+
154
+ | 프레임워크 | JSON URL 패턴 |
155
+ |-----------|--------------|
156
+ | Spring Boot (springfox) | `/v2/api-docs` |
157
+ | Spring Boot (springdoc) | `/v3/api-docs` |
158
+ | NestJS | `/api-json` |
159
+
160
+ ## 전체 커맨드
161
+
162
+ ```bash
163
+ npx swagshot init # 프로젝트 초기 설정
164
+ npx swagshot list --url <url> # 컨트롤러 목록 조회
165
+ npx swagshot generate --url <url> --tag <tag> # 특정 컨트롤러 생성
166
+ npx swagshot generate --url <url> --all # 전체 생성
167
+ npx swagshot config set <key> <value> # 설정 변경
168
+ ```
169
+
170
+ ## 개발 환경 설정
171
+
172
+ ```bash
173
+ git clone https://github.com/Jyophie/swagshot.git
174
+ cd swagshot
175
+ npm install
176
+ npm run build
177
+ node dist/cli/index.js --help
178
+ ```
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,2 @@
1
+ export declare function configCommand(action: string, key: string, value: string): Promise<void>;
2
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAEA,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBA8B7E"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configCommand = configCommand;
4
+ const configManager_1 = require("../../lib/configManager");
5
+ async function configCommand(action, key, value) {
6
+ if (action !== "set") {
7
+ console.error(`❌ 알 수 없는 액션: ${action}. 사용 가능: set`);
8
+ process.exit(1);
9
+ }
10
+ const root = process.cwd();
11
+ const config = await (0, configManager_1.readConfig)(root);
12
+ if (!config) {
13
+ console.error("❌ 설정 파일이 없습니다. 먼저 실행하세요: swagshot init");
14
+ process.exit(1);
15
+ }
16
+ const parsedValue = value === "null" ? null : value;
17
+ if (key in config.project) {
18
+ config.project[key] = parsedValue;
19
+ }
20
+ else if (key in config.style) {
21
+ config.style[key] = parsedValue;
22
+ }
23
+ else if (key === "swaggerUrl" || key === "url") {
24
+ config.swagger = { ...config.swagger, url: parsedValue };
25
+ }
26
+ else {
27
+ console.error(`❌ 알 수 없는 설정 키: ${key}`);
28
+ console.log("사용 가능한 키: apiDir, typesDir, hooksDir, outputDir, httpClient, axiosInstance, queryLibrary, swaggerUrl");
29
+ process.exit(1);
30
+ }
31
+ await (0, configManager_1.writeConfig)(root, config);
32
+ console.log(`✅ ${key} = ${value}`);
33
+ }
34
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":";;AAEA,sCA8BC;AAhCD,2DAAkE;AAE3D,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,GAAW,EAAE,KAAa;IAC5E,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,gBAAgB,MAAM,cAAc,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAU,EAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAEpD,IAAI,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,MAAM,CAAC,OAAmC,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IACjE,CAAC;SAAM,IAAI,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,CAAC,KAAiC,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IAC/D,CAAC;SAAM,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACjD,MAAM,CAAC,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;IAC3D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,sGAAsG,CAAC,CAAC;QACpH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAA,2BAAW,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,9 @@
1
+ interface GenerateOptions {
2
+ url: string;
3
+ tag?: string;
4
+ all?: boolean;
5
+ includeDeprecated?: boolean;
6
+ }
7
+ export declare function generateCommand(options: GenerateOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,iBA4E7D"}
@@ -0,0 +1,74 @@
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.generateCommand = generateCommand;
7
+ const path_1 = __importDefault(require("path"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const configManager_1 = require("../../lib/configManager");
10
+ const fetchSwagger_1 = require("../../lib/fetchSwagger");
11
+ const codeGenerator_1 = require("../../lib/codeGenerator");
12
+ async function generateCommand(options) {
13
+ const root = process.cwd();
14
+ const config = await (0, configManager_1.readConfig)(root);
15
+ if (!config) {
16
+ console.error("❌ 설정 파일이 없습니다. 먼저 실행하세요: swagshot init");
17
+ process.exit(1);
18
+ }
19
+ console.log(`\n📡 Swagger 스펙 가져오는 중... ${options.url}`);
20
+ let spec;
21
+ try {
22
+ spec = await (0, fetchSwagger_1.fetchSwaggerSpec)(options.url);
23
+ }
24
+ catch (e) {
25
+ console.error(`❌ Swagger 스펙을 가져오지 못했습니다.\n${e instanceof Error ? e.message : String(e)}`);
26
+ process.exit(1);
27
+ }
28
+ const allTags = (0, fetchSwagger_1.getControllerTags)(spec);
29
+ // 태그 미지정 시 목록 출력 후 종료
30
+ if (!options.tag && !options.all) {
31
+ console.log("\n📋 사용 가능한 컨트롤러 태그:");
32
+ allTags.forEach((t, i) => console.log(` ${i + 1}. ${t}`));
33
+ console.log("\n사용법:");
34
+ console.log(` swagshot generate --url "${options.url}" --tag <태그명>`);
35
+ console.log(` swagshot generate --url "${options.url}" --all`);
36
+ return;
37
+ }
38
+ const tagsToProcess = options.all ? allTags : [options.tag];
39
+ const writtenFiles = [];
40
+ for (const tag of tagsToProcess) {
41
+ if (!allTags.includes(tag)) {
42
+ console.error(`❌ 태그를 찾을 수 없습니다: "${tag}"`);
43
+ console.log("사용 가능한 태그:", allTags.join(", "));
44
+ process.exit(1);
45
+ }
46
+ const filteredSpec = (0, fetchSwagger_1.filterByTag)(spec, tag, options.includeDeprecated ?? false);
47
+ const endpointCount = Object.values(filteredSpec.paths).reduce((acc, item) => acc + Object.keys(item).length, 0);
48
+ if (endpointCount === 0)
49
+ continue;
50
+ const baseName = tag.replace(/-controller$/, "");
51
+ // types 파일 생성
52
+ const typesContent = (0, codeGenerator_1.generateTypes)(filteredSpec, tag);
53
+ const typesDir = path_1.default.join(root, config.project.typesDir);
54
+ await promises_1.default.mkdir(typesDir, { recursive: true });
55
+ const typesFile = path_1.default.join(typesDir, `${baseName}.ts`);
56
+ await promises_1.default.writeFile(typesFile, typesContent, "utf-8");
57
+ writtenFiles.push(typesFile);
58
+ // api 파일 생성
59
+ const apiContent = (0, codeGenerator_1.generateApiFile)(filteredSpec, tag, config);
60
+ const apiDir = path_1.default.join(root, config.project.outputDir);
61
+ await promises_1.default.mkdir(apiDir, { recursive: true });
62
+ const apiFile = path_1.default.join(apiDir, `${baseName}.ts`);
63
+ await promises_1.default.writeFile(apiFile, apiContent, "utf-8");
64
+ writtenFiles.push(apiFile);
65
+ console.log(`\n✅ ${tag} (${endpointCount}개 엔드포인트)`);
66
+ }
67
+ if (writtenFiles.length === 0) {
68
+ console.log("⚠️ 생성된 파일이 없습니다.");
69
+ return;
70
+ }
71
+ console.log(`\n📁 생성된 파일 (${writtenFiles.length}개):`);
72
+ writtenFiles.forEach(f => console.log(` - ${path_1.default.relative(root, f)}`));
73
+ }
74
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function initCommand(options: {
2
+ root?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,iBAoE3D"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.initCommand = initCommand;
40
+ const path_1 = __importDefault(require("path"));
41
+ const readline = __importStar(require("readline/promises"));
42
+ const process_1 = require("process");
43
+ const configManager_1 = require("../../lib/configManager");
44
+ const detectStructure_1 = require("../../lib/detectStructure");
45
+ async function initCommand(options) {
46
+ const root = path_1.default.resolve(options.root ?? process.cwd());
47
+ const existing = await (0, configManager_1.readConfig)(root);
48
+ if (existing) {
49
+ console.log("\n✅ 이미 설정 파일이 있습니다:");
50
+ console.log(JSON.stringify(existing, null, 2));
51
+ console.log("\n변경하려면: swagshot config set <key> <value>");
52
+ return;
53
+ }
54
+ console.log("\n👋 swagshot 초기 설정을 시작합니다.");
55
+ console.log(`📂 프로젝트 루트: ${root}\n`);
56
+ const detected = await (0, detectStructure_1.detectProjectStructure)(root);
57
+ const rl = readline.createInterface({ input: process_1.stdin, output: process_1.stdout });
58
+ async function ask(question, defaultValue) {
59
+ const answer = await rl.question(`${question} (기본값: ${defaultValue}): `);
60
+ return answer.trim() || defaultValue;
61
+ }
62
+ console.log("자동 감지 결과를 확인해주세요. Enter를 누르면 기본값 사용:\n");
63
+ const swaggerUrl = await ask("Swagger JSON URL", "");
64
+ const apiDir = await ask("API 함수 폴더", detected.apiDir ?? "src/api");
65
+ const typesDir = await ask("타입 정의 폴더", detected.typesDir ?? "src/types");
66
+ const hooksDir = await ask("훅 폴더 (없으면 빈칸)", detected.hooksDir ?? "");
67
+ const httpClient = await ask("HTTP 클라이언트 (axios/fetch)", detected.httpClient ?? "axios");
68
+ const axiosInstance = httpClient === "axios"
69
+ ? await ask("axios 인스턴스 파일 경로 (없으면 빈칸)", detected.axiosInstance ?? "")
70
+ : "";
71
+ const queryLibrary = await ask("Query 라이브러리 (react-query/swr/없으면 빈칸)", detected.queryLibrary ?? "");
72
+ rl.close();
73
+ const config = {
74
+ version: "1",
75
+ project: {
76
+ root,
77
+ apiDir,
78
+ typesDir,
79
+ hooksDir: hooksDir || null,
80
+ outputDir: apiDir,
81
+ },
82
+ style: {
83
+ httpClient: httpClient,
84
+ axiosInstance: axiosInstance || null,
85
+ queryLibrary: (queryLibrary || null),
86
+ namingConvention: "camelCase",
87
+ },
88
+ swagger: {
89
+ url: swaggerUrl || null,
90
+ },
91
+ };
92
+ await (0, configManager_1.writeConfig)(root, config);
93
+ console.log(`\n✅ 설정 완료! ${path_1.default.join(root, configManager_1.CONFIG_FILE)} 저장됨`);
94
+ console.log("\n이제 코드를 생성할 수 있습니다:");
95
+ if (swaggerUrl) {
96
+ console.log(` swagshot list --url "${swaggerUrl}"`);
97
+ console.log(` swagshot generate --url "${swaggerUrl}" --tag <컨트롤러명>`);
98
+ }
99
+ else {
100
+ console.log(` swagshot list --url <swagger-json-url>`);
101
+ console.log(` swagshot generate --url <swagger-json-url> --tag <컨트롤러명>`);
102
+ }
103
+ }
104
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface ListOptions {
2
+ url: string;
3
+ }
4
+ export declare function listCommand(options: ListOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBAwBrD"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listCommand = listCommand;
4
+ const fetchSwagger_1 = require("../../lib/fetchSwagger");
5
+ async function listCommand(options) {
6
+ console.log(`\n📡 Swagger 스펙 가져오는 중... ${options.url}`);
7
+ let spec;
8
+ try {
9
+ spec = await (0, fetchSwagger_1.fetchSwaggerSpec)(options.url);
10
+ }
11
+ catch (e) {
12
+ console.error(`❌ Swagger 스펙을 가져오지 못했습니다.\n${e instanceof Error ? e.message : String(e)}`);
13
+ process.exit(1);
14
+ }
15
+ const tags = (0, fetchSwagger_1.getControllerTags)(spec);
16
+ if (tags.length === 0) {
17
+ console.log("❌ 태그가 없습니다.");
18
+ return;
19
+ }
20
+ console.log(`\n📋 컨트롤러 태그 목록 (${tags.length}개):\n`);
21
+ tags.forEach((t, i) => console.log(` ${i + 1}. ${t}`));
22
+ console.log("\n사용법:");
23
+ console.log(` swagshot generate --url "${options.url}" --tag <태그명>`);
24
+ console.log(` swagshot generate --url "${options.url}" --all`);
25
+ }
26
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":";;AAMA,kCAwBC;AA9BD,yDAA6E;AAMtE,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,OAAO,CAAC,GAAG,CAAC,6BAA6B,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAExD,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,IAAA,+BAAgB,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,gCAAiB,EAAC,IAAI,CAAC,CAAC;IAErC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAExD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,8BAA8B,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,8BAA8B,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_1 = require("./commands/init");
6
+ const generate_1 = require("./commands/generate");
7
+ const list_1 = require("./commands/list");
8
+ const config_1 = require("./commands/config");
9
+ const program = new commander_1.Command();
10
+ program
11
+ .name("swagshot")
12
+ .description("Swagger-powered API & type generator")
13
+ .version("0.1.0");
14
+ program
15
+ .command("init")
16
+ .description("프로젝트 초기 설정 (.swagshot.json 생성)")
17
+ .option("--root <path>", "프로젝트 루트 경로 (기본값: 현재 디렉토리)")
18
+ .action(init_1.initCommand);
19
+ program
20
+ .command("generate")
21
+ .description("Swagger 스펙으로 API 함수와 TypeScript 타입 생성")
22
+ .requiredOption("--url <url>", "Swagger JSON URL 또는 파일 경로")
23
+ .option("--tag <tag>", "생성할 컨트롤러 태그 (없으면 목록 표시)")
24
+ .option("--all", "모든 컨트롤러 생성")
25
+ .option("--include-deprecated", "deprecated 엔드포인트 포함")
26
+ .action(generate_1.generateCommand);
27
+ program
28
+ .command("list")
29
+ .description("Swagger 스펙의 컨트롤러 태그 목록 조회")
30
+ .requiredOption("--url <url>", "Swagger JSON URL 또는 파일 경로")
31
+ .action(list_1.listCommand);
32
+ program
33
+ .command("config")
34
+ .description("프로젝트 설정 변경")
35
+ .argument("<action>", "set")
36
+ .argument("<key>", "설정 키 (예: apiDir, typesDir, httpClient)")
37
+ .argument("<value>", "설정 값")
38
+ .action(config_1.configCommand);
39
+ program.parse();
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,kDAAsD;AACtD,0CAA8C;AAC9C,8CAAkD;AAElD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,sCAAsC,CAAC;KACnD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,eAAe,EAAE,2BAA2B,CAAC;KACpD,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,uCAAuC,CAAC;KACpD,cAAc,CAAC,aAAa,EAAE,2BAA2B,CAAC;KAC1D,MAAM,CAAC,aAAa,EAAE,yBAAyB,CAAC;KAChD,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC;KAC7B,MAAM,CAAC,sBAAsB,EAAE,qBAAqB,CAAC;KACrD,MAAM,CAAC,0BAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2BAA2B,CAAC;KACxC,cAAc,CAAC,aAAa,EAAE,2BAA2B,CAAC;KAC1D,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,YAAY,CAAC;KACzB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;KAC3B,QAAQ,CAAC,OAAO,EAAE,wCAAwC,CAAC;KAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC3B,MAAM,CAAC,sBAAa,CAAC,CAAC;AAEzB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const zod_1 = require("zod");
7
+ const setup_js_1 = require("./tools/setup.js");
8
+ const sync_js_1 = require("./tools/sync.js");
9
+ const configUpdate_js_1 = require("./tools/configUpdate.js");
10
+ // Workaround: cast server to any to avoid TS2589 deep type instantiation errors
11
+ // caused by the MCP SDK 1.28.x zod-compat union types (zod v3 | v4).
12
+ // The runtime behavior is fully correct.
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ const srv = new mcp_js_1.McpServer({ name: "swagshot", version: "0.1.0" });
15
+ // ── Tool: swagger_setup ───────────────────────────────────────────────────
16
+ srv.registerTool("swagger_setup", {
17
+ description: "프로젝트 구조를 분석하고 swagshot 설정 파일(.swagshot.json)을 생성합니다. 처음 한 번만 실행하면 이후 자동으로 참고합니다.",
18
+ inputSchema: {
19
+ projectRoot: zod_1.z
20
+ .string()
21
+ .optional()
22
+ .describe("레포 루트 경로 (없으면 현재 디렉토리 사용)"),
23
+ },
24
+ }, async ({ projectRoot }) => {
25
+ const result = await (0, setup_js_1.handleSetup)(projectRoot);
26
+ return { content: [{ type: "text", text: result }] };
27
+ });
28
+ // ── Tool: swagger_sync ────────────────────────────────────────────────────
29
+ srv.registerTool("swagger_sync", {
30
+ description: "Swagger URL 또는 파일 경로를 받아 프로젝트 패턴에 맞게 API 함수와 TypeScript 타입을 생성합니다.",
31
+ inputSchema: {
32
+ swaggerUrl: zod_1.z
33
+ .string()
34
+ .describe("Swagger JSON URL 또는 로컬 파일 경로 (예: https://api.example.com/swagger.json)"),
35
+ tag: zod_1.z
36
+ .string()
37
+ .optional()
38
+ .describe("생성할 컨트롤러 태그 (없으면 사용 가능한 태그 목록 반환). 전체 생성 시 'all'"),
39
+ includeDeprecated: zod_1.z
40
+ .boolean()
41
+ .optional()
42
+ .describe("deprecated된 엔드포인트도 포함할지 여부 (기본값: false)"),
43
+ },
44
+ }, async ({ swaggerUrl, tag, includeDeprecated }) => {
45
+ const result = await (0, sync_js_1.handleSync)(swaggerUrl, tag, includeDeprecated);
46
+ return { content: [{ type: "text", text: result }] };
47
+ });
48
+ // ── Tool: swagger_config_update ───────────────────────────────────────────
49
+ srv.registerTool("swagger_config_update", {
50
+ description: "swagshot 프로젝트 설정을 업데이트합니다. (예: apiDir, typesDir, httpClient 등)",
51
+ inputSchema: {
52
+ updates: zod_1.z
53
+ .record(zod_1.z.string().nullable())
54
+ .describe('변경할 설정 키-값 쌍 (예: { "apiDir": "src/services", "httpClient": "fetch" })'),
55
+ },
56
+ }, async ({ updates }) => {
57
+ const result = await (0, configUpdate_js_1.handleConfigUpdate)(updates);
58
+ return { content: [{ type: "text", text: result }] };
59
+ });
60
+ // ── Start server ──────────────────────────────────────────────────────────
61
+ const server = srv;
62
+ async function main() {
63
+ const transport = new stdio_js_1.StdioServerTransport();
64
+ await server.connect(transport);
65
+ console.error("swagshot MCP server running on stdio");
66
+ }
67
+ main().catch((err) => {
68
+ console.error("Fatal error:", err);
69
+ process.exit(1);
70
+ });
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,oEAAoE;AACpE,wEAAiF;AACjF,6BAAwB;AACxB,+CAA+C;AAC/C,6CAA6C;AAC7C,6DAA6D;AAE7D,gFAAgF;AAChF,qEAAqE;AACrE,yCAAyC;AACzC,8DAA8D;AAC9D,MAAM,GAAG,GAAG,IAAI,kBAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,CAAQ,CAAC;AAEzE,6EAA6E;AAC7E,GAAG,CAAC,YAAY,CACd,eAAe,EACf;IACE,WAAW,EACT,kFAAkF;IACpF,WAAW,EAAE;QACX,WAAW,EAAE,OAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2BAA2B,CAAC;KACzC;CACF,EACD,KAAK,EAAE,EAAE,WAAW,EAA4B,EAAE,EAAE;IAClD,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAW,EAAC,WAAW,CAAC,CAAC;IAC9C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAChE,CAAC,CACF,CAAC;AAEF,6EAA6E;AAC7E,GAAG,CAAC,YAAY,CACd,cAAc,EACd;IACE,WAAW,EACT,oEAAoE;IACtE,WAAW,EAAE;QACX,UAAU,EAAE,OAAC;aACV,MAAM,EAAE;aACR,QAAQ,CACP,wEAAwE,CACzE;QACH,GAAG,EAAE,OAAC;aACH,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,kDAAkD,CACnD;QACH,iBAAiB,EAAE,OAAC;aACjB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,yCAAyC,CAAC;KACvD;CACF,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,iBAAiB,EAAqE,EAAE,EAAE;IAClH,MAAM,MAAM,GAAG,MAAM,IAAA,oBAAU,EAAC,UAAU,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC;IACpE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAChE,CAAC,CACF,CAAC;AAEF,6EAA6E;AAC7E,GAAG,CAAC,YAAY,CACd,uBAAuB,EACvB;IACE,WAAW,EAAE,gEAAgE;IAC7E,WAAW,EAAE;QACX,OAAO,EAAE,OAAC;aACP,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;aAC7B,QAAQ,CACP,uEAAuE,CACxE;KACJ;CACF,EACD,KAAK,EAAE,EAAE,OAAO,EAA8C,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,IAAA,oCAAkB,EAAC,OAAO,CAAC,CAAC;IACjD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAChE,CAAC,CACF,CAAC;AAEF,6EAA6E;AAC7E,MAAM,MAAM,GAAG,GAAgB,CAAC;AAEhC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { SwaggerSpec, SchemaObject } from "./types.js";
2
+ import { SwagShotConfig } from "./types.js";
3
+ export declare function schemaToTS(schema: SchemaObject, schemas?: Record<string, SchemaObject>, indent?: number): string;
4
+ export declare function generateTypes(spec: SwaggerSpec, tag: string): string;
5
+ export declare function generateApiFile(spec: SwaggerSpec, tag: string, config: SwagShotConfig): string;
6
+ //# sourceMappingURL=codeGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeGenerator.d.ts","sourceRoot":"","sources":["../../src/lib/codeGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAwB,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C,wBAAgB,UAAU,CACxB,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAM,EAC1C,MAAM,SAAI,GACT,MAAM,CAsDR;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAiEpE;AAID,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,GACrB,MAAM,CAmHR"}