Skip to content

Commit 7ac8a91

Browse files
author
Jaakko Heusala
committed
Fixes #952
1 parent 2d281c3 commit 7ac8a91

File tree

4 files changed

+128
-3
lines changed

4 files changed

+128
-3
lines changed

templates/default/procedure-call.ejs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ const describeReturnType = () => {
7979
}
8080
}
8181
82+
const isValidIdentifier = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
83+
8284
%>
8385
/**
8486
<%~ routeDocs.description %>
@@ -88,7 +90,7 @@ const describeReturnType = () => {
8890
<%~ routeDocs.lines %>
8991

9092
*/
91-
<%~ route.routeName.usage %><%~ route.namespace ? ': ' : ' = ' %>(<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> =>
93+
<% if (isValidIdentifier(route.routeName.usage)) { %><%~ route.routeName.usage %><%~ route.namespace ? ': ' : ' = ' %><% } else { %>"<%~ route.routeName.usage %>"<%~ route.namespace ? ': ' : ' = ' %><% } %>(<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> =>
9294
<%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>, <%~ errorType %>>({
9395
path: `<%~ path %>`,
9496
method: '<%~ _.upperCase(method) %>',

templates/modular/procedure-call.ejs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ const describeReturnType = () => {
7979
}
8080
}
8181
82+
const isValidIdentifier = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
83+
8284
%>
8385
/**
8486
<%~ routeDocs.description %>
@@ -88,7 +90,7 @@ const describeReturnType = () => {
8890
<%~ routeDocs.lines %>
8991

9092
*/
91-
<%~ route.routeName.usage %> = (<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> =>
93+
<% if (isValidIdentifier(route.routeName.usage)) { %><%~ route.routeName.usage %><%~ route.namespace ? ': ' : ' = ' %><% } else { %>"<%~ route.routeName.usage %>"<%~ route.namespace ? ': ' : ' = ' %><% } %>(<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> =>
9294
<%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>, <%~ errorType %>>({
9395
path: `<%~ path %>`,
9496
method: '<%~ _.upperCase(method) %>',
@@ -98,4 +100,4 @@ const describeReturnType = () => {
98100
<%~ bodyContentKindTmpl ? `type: ${bodyContentKindTmpl},` : '' %>
99101
<%~ responseFormatTmpl ? `format: ${responseFormatTmpl},` : '' %>
100102
...<%~ _.get(requestConfigParam, "name") %>,
101-
})
103+
})<%~ route.namespace ? ',' : '' %>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as fs from "node:fs/promises";
2+
import * as os from "node:os";
3+
import * as path from "node:path";
4+
5+
import { afterAll, beforeAll, describe, expect, test } from "vitest";
6+
7+
import { generateApi } from "../../../src/index.js";
8+
9+
describe("operationId starting with number", async () => {
10+
let tmpdir: string;
11+
12+
beforeAll(async () => {
13+
tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), "swagger-typescript-api"));
14+
});
15+
16+
afterAll(async () => {
17+
await fs.rm(tmpdir, { recursive: true });
18+
});
19+
20+
test("should handle operationIds that start with numbers", async () => {
21+
await generateApi({
22+
fileName: "schema",
23+
input: path.resolve(import.meta.dirname, "schema.json"),
24+
output: tmpdir,
25+
silent: true,
26+
generateClient: true,
27+
generateRouteTypes: true,
28+
});
29+
30+
const content = await fs.readFile(path.join(tmpdir, "schema.ts"), {
31+
encoding: "utf8",
32+
});
33+
34+
// Should contain quoted property names for invalid identifiers
35+
expect(content).toContain('"123GetUser"');
36+
expect(content).toContain('"456CreatePost"');
37+
// Should not contain unquoted invalid identifiers
38+
expect(content).not.toContain('123GetUser:');
39+
expect(content).not.toContain('456CreatePost:');
40+
// Should be valid TypeScript (no syntax errors)
41+
expect(content).toMatchSnapshot();
42+
});
43+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"openapi": "3.0.0",
3+
"info": {
4+
"title": "Test API with operationId starting with number",
5+
"version": "1.0.0"
6+
},
7+
"paths": {
8+
"/users": {
9+
"get": {
10+
"operationId": "123getUser",
11+
"summary": "Get user",
12+
"responses": {
13+
"200": {
14+
"description": "Success",
15+
"content": {
16+
"application/json": {
17+
"schema": {
18+
"type": "object",
19+
"properties": {
20+
"id": {
21+
"type": "integer"
22+
},
23+
"name": {
24+
"type": "string"
25+
}
26+
}
27+
}
28+
}
29+
}
30+
}
31+
}
32+
}
33+
},
34+
"/posts": {
35+
"post": {
36+
"operationId": "456createPost",
37+
"summary": "Create post",
38+
"requestBody": {
39+
"content": {
40+
"application/json": {
41+
"schema": {
42+
"type": "object",
43+
"properties": {
44+
"title": {
45+
"type": "string"
46+
},
47+
"content": {
48+
"type": "string"
49+
}
50+
}
51+
}
52+
}
53+
}
54+
},
55+
"responses": {
56+
"201": {
57+
"description": "Created",
58+
"content": {
59+
"application/json": {
60+
"schema": {
61+
"type": "object",
62+
"properties": {
63+
"id": {
64+
"type": "integer"
65+
},
66+
"title": {
67+
"type": "string"
68+
}
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)