Skip to content

Commit 08f080e

Browse files
committed
Improvements and optimization
1 parent 711c3af commit 08f080e

7 files changed

Lines changed: 59 additions & 24 deletions

File tree

eslint.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export default [
9494
'warn',
9595
{ allowConstantExport: true },
9696
],
97-
'@typescript-eslint/no-explicit-any': 'warn',
97+
// Allow 'any' for dynamic API parsing, error handling, and template helpers
98+
'@typescript-eslint/no-explicit-any': 'off',
9899
'@typescript-eslint/no-unused-vars': [
99100
'warn',
100101
{ argsIgnorePattern: '^_' },

src/client/components/steps/StepApiConfig.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function StepApiConfig({
4747
if (onParseRequest) {
4848
onParseRequest(handleParse, canParse, parsing);
4949
}
50+
// eslint-disable-next-line react-hooks/exhaustive-deps
5051
}, [canParse, parsing, formData, inputMethod]);
5152

5253
const handleParse = async () => {
@@ -73,7 +74,7 @@ function StepApiConfig({
7374
if (!parsed.info || !parsed.item) {
7475
throw new Error("Invalid Postman collection format");
7576
}
76-
} catch (e) {
77+
} catch {
7778
setParseError("Invalid Postman collection JSON format");
7879
setParsing(false);
7980
return;

src/client/components/steps/StepSelectEndpoints.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,24 @@ function StepSelectEndpoints({
3030
selectedEndpoints,
3131
setSelectedEndpoints,
3232
}: StepSelectEndpointsProps) {
33-
const endpoints = apiConfig?.endpoints || [];
3433
const [searchTerm, setSearchTerm] = useState("");
3534
const [page, setPage] = useState(0);
3635
const [rowsPerPage, setRowsPerPage] = useState(25);
3736

37+
const endpoints = apiConfig?.endpoints || [];
38+
3839
// Filter endpoints based on search
3940
const filteredEndpoints = useMemo(() => {
40-
if (!searchTerm) return endpoints;
41+
const endpointList = apiConfig?.endpoints || [];
42+
if (!searchTerm) return endpointList;
4143
const searchLower = searchTerm.toLowerCase();
42-
return endpoints.filter(
44+
return endpointList.filter(
4345
(endpoint: any) =>
4446
endpoint.path?.toLowerCase().includes(searchLower) ||
4547
endpoint.method?.toLowerCase().includes(searchLower) ||
4648
endpoint.description?.toLowerCase().includes(searchLower),
4749
);
48-
}, [endpoints, searchTerm]);
50+
}, [apiConfig?.endpoints, searchTerm]);
4951

5052
// Paginate filtered endpoints
5153
const paginatedEndpoints = useMemo(() => {

src/client/pages/CreateServer.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,6 @@ function CreateServer() {
170170
setActiveStep((prev) => prev - 1);
171171
};
172172

173-
const handleReset = () => {
174-
setActiveStep(0);
175-
setApiConfig(null);
176-
setSelectedEndpoints([]);
177-
setServerConfig({ transport: "stdio" });
178-
setGeneratedServerId(null);
179-
setError(null);
180-
};
181-
182173
const getStepContent = (step: number) => {
183174
switch (step) {
184175
case 0:

src/client/pages/McpServers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ function McpServers() {
118118
// Then deploy (install + build)
119119
return apiService.deployServer(serverId);
120120
},
121-
onSuccess: (response) => {
121+
onSuccess: () => {
122122
queryClient.invalidateQueries({ queryKey: ["mcp-servers"] });
123123
enqueueSnackbar("STDIO server regenerated and rebuilt successfully", {
124124
variant: "success",

src/generator/ApiParser.ts

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ export class ApiParser {
4545
if (typeof response.data === "string") {
4646
try {
4747
spec = JSON.parse(response.data);
48-
} catch (jsonError) {
48+
} catch {
4949
try {
5050
spec = YAML.parse(response.data);
51-
} catch (yamlError) {
51+
} catch {
5252
throw new Error(
5353
"Invalid OpenAPI specification from URL: must be valid JSON or YAML format",
5454
);
@@ -62,10 +62,10 @@ export class ApiParser {
6262
// Try to parse as JSON first, then fall back to YAML
6363
try {
6464
spec = JSON.parse(specUrlOrJson);
65-
} catch (jsonError) {
65+
} catch {
6666
try {
6767
spec = YAML.parse(specUrlOrJson);
68-
} catch (yamlError) {
68+
} catch {
6969
throw new Error(
7070
"Invalid OpenAPI specification: must be valid JSON or YAML format",
7171
);
@@ -154,10 +154,14 @@ export class ApiParser {
154154
endpoints.push(currentEndpoint);
155155
}
156156

157+
const method = methodMatch[1].toUpperCase();
158+
const path = methodMatch[2].trim();
159+
157160
currentEndpoint = {
158-
method: methodMatch[1].toUpperCase(),
159-
path: methodMatch[2].trim(),
161+
method,
162+
path,
160163
description: methodMatch[3].trim(),
164+
operationId: this.generateOperationId(method, path),
161165
parameters: [],
162166
};
163167
continue;
@@ -602,11 +606,13 @@ export class ApiParser {
602606
: item.request.url.raw;
603607

604608
const path = this.extractPath(url);
609+
const method = item.request.method;
605610

606611
endpoints.push({
607612
path,
608-
method: item.request.method,
613+
method,
609614
description: item.name || "",
615+
operationId: this.generateOperationId(method, path),
610616
parameters: this.extractPostmanParameters(item.request),
611617
});
612618
}
@@ -617,6 +623,41 @@ export class ApiParser {
617623
}
618624
}
619625

626+
/**
627+
* Generate operationId from method and path
628+
* e.g., GET /submissions -> getSubmissions
629+
* e.g., POST /submissions/{id}/documents -> postSubmissionsIdDocuments
630+
*/
631+
private generateOperationId(method: string, path: string): string {
632+
// Convert method to lowercase
633+
const methodLower = method.toLowerCase();
634+
635+
// Clean and convert path to camelCase
636+
// Remove leading slash and split by /
637+
const pathParts = path
638+
.replace(/^\//, "") // Remove leading slash
639+
.split("/")
640+
.filter((part) => part.length > 0) // Remove empty parts
641+
.map((part) => {
642+
// Replace path parameters {id} with just "id"
643+
if (part.startsWith("{") && part.endsWith("}")) {
644+
return part.slice(1, -1);
645+
}
646+
// Replace hyphens and underscores with spaces for proper casing
647+
return part.replace(/[-_]/g, " ");
648+
})
649+
.map((part) => {
650+
// Convert to title case for all parts
651+
return part
652+
.split(" ")
653+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
654+
.join("");
655+
})
656+
.join("");
657+
658+
return methodLower + (pathParts || "Root");
659+
}
660+
620661
/**
621662
* Extract path from URL
622663
*/

src/server/routes/deployments.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
appendLog,
1212
readLogs,
1313
rotateLogIfNeeded,
14-
deleteServerLogs,
1514
} from "../utils/logger.js";
1615

1716
const router = express.Router();

0 commit comments

Comments
 (0)