@dotflash/openapi-semantic-generator 0.1.0 → 0.1.2

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 CHANGED
@@ -1,4 +1,4 @@
1
- # OpenAPI-Agent-Sync (oas-agent-sync)
1
+ # OpenAPI Semantic Generator (@dotflash/openapi-semantic-generator)
2
2
 
3
3
  [English](#english) | [한국어](#한국어)
4
4
 
@@ -41,13 +41,13 @@ It provides an index and guide that allows LLMs to understand large-scale API co
41
41
  ### Installation
42
42
 
43
43
  ```bash
44
- npm install -g oas-agent-sync
44
+ npm install -g @dotflash/openapi-semantic-generator
45
45
  ```
46
46
 
47
47
  ### Usage
48
48
 
49
49
  ```bash
50
- npx oas-agent-sync <spec-url-or-path> -o <generated-code-dir> [options]
50
+ npx openapi-semantic-generator <spec-url-or-path> -o <generated-code-dir> [options]
51
51
  ```
52
52
 
53
53
  #### Required Arguments
@@ -56,8 +56,30 @@ npx oas-agent-sync <spec-url-or-path> -o <generated-code-dir> [options]
56
56
 
57
57
  #### Options
58
58
 
59
- - `-o, --output <dir>`: Directory where the code is already generated (e.g., `./src/api`)
60
- - `--api-dir <path>`: Relative path to APIs within the output directory (e.g., `services`)
59
+ - `-o, --output <dir>`: **Required.** Directory where the generated code is located. This tool will scan this directory to find API files.
60
+ - Example: `./src/api`, `./generated/client`
61
+ - **Important**: The generated TypeScript files must be inside this directory or its subdirectories.
62
+
63
+ - `--api-dir <path>`: Optional. Relative path from the output directory where API files are located.
64
+ - Example: `services`, `api`, `client/apis`
65
+ - This path is **relative to the `-o` directory**, not the current working directory.
66
+ - If not specified, the tool searches in `api/`, `apis/`, and the output directory itself (in that order).
67
+
68
+ #### Usage Examples
69
+
70
+ ```bash
71
+ # Basic usage: API files are in ./src/api/
72
+ npx openapi-semantic-generator spec.yaml -o ./src/api
73
+
74
+ # API files are in ./generated/services/
75
+ npx openapi-semantic-generator spec.yaml -o ./generated --api-dir services
76
+
77
+ # Using a remote spec URL
78
+ npx openapi-semantic-generator https://api.example.com/openapi.json -o ./src/api
79
+
80
+ # API files are directly in the output directory
81
+ npx openapi-semantic-generator spec.yaml -o ./dist/client
82
+ ```
61
83
 
62
84
  ### Generated Documents
63
85
 
@@ -91,13 +113,13 @@ OpenAPI Generator로 생성된 코드들을 분석하여 LLM 에이전트가 활
91
113
  ### 설치 방법
92
114
 
93
115
  ```bash
94
- npm install -g oas-agent-sync
116
+ npm install -g @dotflash/openapi-semantic-generator
95
117
  ```
96
118
 
97
119
  ### 사용 방법
98
120
 
99
121
  ```bash
100
- npx oas-agent-sync <spec-url-or-path> -o <generated-code-dir> [options]
122
+ npx openapi-semantic-generator <spec-url-or-path> -o <generated-code-dir> [options]
101
123
  ```
102
124
 
103
125
  #### 필수 인자
@@ -106,8 +128,30 @@ npx oas-agent-sync <spec-url-or-path> -o <generated-code-dir> [options]
106
128
 
107
129
  #### 옵션
108
130
 
109
- - `-o, --output <dir>`: 이미 생성된 코드가 위치한 디렉토리 (예: `./src/api`)
110
- - `--api-dir <path>`: 출력 디렉토리 내 API 파일이 위치한 상대 경로 (예: `services`)
131
+ - `-o, --output <dir>`: **필수.** 생성된 코드가 위치한 디렉토리입니다. 도구는 해당 디렉토리를 스캔하여 API 파일을 찾습니다.
132
+ - 예시: `./src/api`, `./generated/client`
133
+ - **중요**: 생성된 TypeScript 파일이 반드시 이 디렉토리 또는 하위 디렉토리에 있어야 합니다.
134
+
135
+ - `--api-dir <path>`: 선택사항. 출력 디렉토리 기준으로 API 파일이 위치한 상대 경로입니다.
136
+ - 예시: `services`, `api`, `client/apis`
137
+ - 이 경로는 **`-o` 디렉토리 기준의 상대 경로**이며, 현재 작업 디렉토리 기준이 아닙니다.
138
+ - 지정하지 않으면 `api/`, `apis/`, 출력 디렉토리 자체를 순서대로 검색합니다.
139
+
140
+ #### 사용 예시
141
+
142
+ ```bash
143
+ # 기본 사용: API 파일이 ./src/api/에 있는 경우
144
+ npx openapi-semantic-generator spec.yaml -o ./src/api
145
+
146
+ # API 파일이 ./generated/services/에 있는 경우
147
+ npx openapi-semantic-generator spec.yaml -o ./generated --api-dir services
148
+
149
+ # 원격 스펙 URL 사용
150
+ npx openapi-semantic-generator https://api.example.com/openapi.json -o ./src/api
151
+
152
+ # API 파일이 출력 디렉토리 바로 아래에 있는 경우
153
+ npx openapi-semantic-generator spec.yaml -o ./dist/client
154
+ ```
111
155
 
112
156
  ### 생성되는 문서
113
157
 
@@ -95,10 +95,20 @@ async function scanGeneratedFiles(outputDir, metadata, options = {}) {
95
95
  }
96
96
  if (metadata.operations) {
97
97
  for (const op of metadata.operations) {
98
- if (apis.length > 0) {
99
- op.className = apis[0].className;
100
- op.sourceFile = apis[0].sourceFile;
98
+ if (apis.length === 0) continue;
99
+ let matchedApi = apis[0];
100
+ if (op.tags && op.tags.length > 0) {
101
+ const primaryTag = op.tags[0].toLowerCase();
102
+ const found = apis.find((api) => {
103
+ const fileName = api.className.toLowerCase();
104
+ return fileName.includes(primaryTag);
105
+ });
106
+ if (found) {
107
+ matchedApi = found;
108
+ }
101
109
  }
110
+ op.className = matchedApi.className;
111
+ op.sourceFile = matchedApi.sourceFile;
102
112
  }
103
113
  }
104
114
  return {
@@ -143,10 +153,20 @@ async function renderDocs(metadata, outputDir) {
143
153
  });
144
154
  const groupedOperations = Object.entries(operationsByTag).map(([tag, ops]) => ({
145
155
  tag,
146
- ops: ops.map((op, index) => ({
147
- ...op,
148
- last: index === ops.length - 1
149
- }))
156
+ ops: ops.map((op, index) => {
157
+ let relativePath = op.sourceFile;
158
+ if (path2.isAbsolute(op.sourceFile)) {
159
+ relativePath = path2.relative(outputDir, op.sourceFile);
160
+ }
161
+ if (!relativePath.startsWith("./") && !relativePath.startsWith("../")) {
162
+ relativePath = "./" + relativePath;
163
+ }
164
+ return {
165
+ ...op,
166
+ sourceFile: relativePath,
167
+ last: index === ops.length - 1
168
+ };
169
+ })
150
170
  }));
151
171
  const enrichedMetadata = {
152
172
  ...metadata,
package/dist/cli.cjs CHANGED
@@ -133,10 +133,20 @@ async function scanGeneratedFiles(outputDir, metadata, options = {}) {
133
133
  }
134
134
  if (metadata.operations) {
135
135
  for (const op of metadata.operations) {
136
- if (apis.length > 0) {
137
- op.className = apis[0].className;
138
- op.sourceFile = apis[0].sourceFile;
136
+ if (apis.length === 0) continue;
137
+ let matchedApi = apis[0];
138
+ if (op.tags && op.tags.length > 0) {
139
+ const primaryTag = op.tags[0].toLowerCase();
140
+ const found = apis.find((api) => {
141
+ const fileName = api.className.toLowerCase();
142
+ return fileName.includes(primaryTag);
143
+ });
144
+ if (found) {
145
+ matchedApi = found;
146
+ }
139
147
  }
148
+ op.className = matchedApi.className;
149
+ op.sourceFile = matchedApi.sourceFile;
140
150
  }
141
151
  }
142
152
  return {
@@ -181,10 +191,20 @@ async function renderDocs(metadata, outputDir) {
181
191
  });
182
192
  const groupedOperations = Object.entries(operationsByTag).map(([tag, ops]) => ({
183
193
  tag,
184
- ops: ops.map((op, index) => ({
185
- ...op,
186
- last: index === ops.length - 1
187
- }))
194
+ ops: ops.map((op, index) => {
195
+ let relativePath = op.sourceFile;
196
+ if (import_path2.default.isAbsolute(op.sourceFile)) {
197
+ relativePath = import_path2.default.relative(outputDir, op.sourceFile);
198
+ }
199
+ if (!relativePath.startsWith("./") && !relativePath.startsWith("../")) {
200
+ relativePath = "./" + relativePath;
201
+ }
202
+ return {
203
+ ...op,
204
+ sourceFile: relativePath,
205
+ last: index === ops.length - 1
206
+ };
207
+ })
188
208
  }));
189
209
  const enrichedMetadata = {
190
210
  ...metadata,
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateDocs
4
- } from "./chunk-JGV5ULAN.js";
4
+ } from "./chunk-PLFFT6WD.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
package/dist/index.cjs CHANGED
@@ -142,10 +142,20 @@ async function scanGeneratedFiles(outputDir, metadata, options = {}) {
142
142
  }
143
143
  if (metadata.operations) {
144
144
  for (const op of metadata.operations) {
145
- if (apis.length > 0) {
146
- op.className = apis[0].className;
147
- op.sourceFile = apis[0].sourceFile;
145
+ if (apis.length === 0) continue;
146
+ let matchedApi = apis[0];
147
+ if (op.tags && op.tags.length > 0) {
148
+ const primaryTag = op.tags[0].toLowerCase();
149
+ const found = apis.find((api) => {
150
+ const fileName = api.className.toLowerCase();
151
+ return fileName.includes(primaryTag);
152
+ });
153
+ if (found) {
154
+ matchedApi = found;
155
+ }
148
156
  }
157
+ op.className = matchedApi.className;
158
+ op.sourceFile = matchedApi.sourceFile;
149
159
  }
150
160
  }
151
161
  return {
@@ -190,10 +200,20 @@ async function renderDocs(metadata, outputDir) {
190
200
  });
191
201
  const groupedOperations = Object.entries(operationsByTag).map(([tag, ops]) => ({
192
202
  tag,
193
- ops: ops.map((op, index) => ({
194
- ...op,
195
- last: index === ops.length - 1
196
- }))
203
+ ops: ops.map((op, index) => {
204
+ let relativePath = op.sourceFile;
205
+ if (import_path2.default.isAbsolute(op.sourceFile)) {
206
+ relativePath = import_path2.default.relative(outputDir, op.sourceFile);
207
+ }
208
+ if (!relativePath.startsWith("./") && !relativePath.startsWith("../")) {
209
+ relativePath = "./" + relativePath;
210
+ }
211
+ return {
212
+ ...op,
213
+ sourceFile: relativePath,
214
+ last: index === ops.length - 1
215
+ };
216
+ })
197
217
  }));
198
218
  const enrichedMetadata = {
199
219
  ...metadata,
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  generateDocs,
4
4
  renderDocs,
5
5
  scanGeneratedFiles
6
- } from "./chunk-JGV5ULAN.js";
6
+ } from "./chunk-PLFFT6WD.js";
7
7
  export {
8
8
  extractMetadata,
9
9
  generateDocs,
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@dotflash/openapi-semantic-generator",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Semantic mapping automation tool for LLM agents and OpenAPI generated code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
8
8
  "types": "dist/index.d.ts",
9
9
  "bin": {
10
- "oas-agent-sync": "dist/cli.js"
10
+ "openapi-semantic-generator": "dist/cli.js"
11
11
  },
12
12
  "files": [
13
13
  "dist",
@@ -19,7 +19,8 @@
19
19
  "dev": "tsup src/index.ts src/cli.ts --format cjs,esm --watch --shims",
20
20
  "test": "vitest run",
21
21
  "test:watch": "vitest",
22
- "gen:example": "openapi-generator-cli generate -i test/fixtures/petstore.yaml -g typescript-axios -o test/generated/petstore && node dist/cli.js test/fixtures/petstore.yaml -o test/generated/petstore --api-dir api"
22
+ "gen:example": "openapi-generator-cli generate -i https://petstore3.swagger.io/api/v3/openapi.json -g typescript-axios -o test/generated/petstore && node dist/cli.js https://petstore3.swagger.io/api/v3/openapi.json -o test/generated/petstore",
23
+ "gen:example:separate": "openapi-generator-cli generate -i https://petstore3.swagger.io/api/v3/openapi.json -g typescript-axios -o test/generated/petstore-separate --additional-properties=withSeparateModelsAndApi=true,apiPackage=apis,modelPackage=models && node dist/cli.js https://petstore3.swagger.io/api/v3/openapi.json -o test/generated/petstore-separate --api-dir apis"
23
24
  },
24
25
  "keywords": [
25
26
  "openapi",