Skip to content

Commit 7401378

Browse files
committed
Fix schema
1 parent ff4d5dd commit 7401378

File tree

4 files changed

+62
-11
lines changed

4 files changed

+62
-11
lines changed

examples/vite/openapi.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,55 @@
5454
}
5555
},
5656
"/users/{user_id}/posts": {
57+
"delete": {
58+
"summary": "Get user posts by ID",
59+
"operationId": "getUserPostsById",
60+
"parameters": [
61+
{
62+
"name": "user_id",
63+
"in": "path",
64+
"required": true,
65+
"schema": {
66+
"type": "integer",
67+
"default": 1
68+
},
69+
"description": "User ID"
70+
},
71+
{
72+
"name": "post_id",
73+
"in": "query",
74+
"required": false,
75+
"schema": {
76+
"type": "integer"
77+
},
78+
"description": "Post ID"
79+
},
80+
{
81+
"name": "required",
82+
"in": "query",
83+
"required": true,
84+
"schema": {
85+
"type": "integer"
86+
},
87+
"description": "Post ID"
88+
}
89+
],
90+
"responses": {
91+
"200": {
92+
"description": "User details",
93+
"content": {
94+
"application/json": {
95+
"schema": {
96+
"type": "array",
97+
"items": {
98+
"$ref": "#/components/schemas/Post"
99+
}
100+
}
101+
}
102+
}
103+
}
104+
}
105+
},
57106
"get": {
58107
"summary": "Get user posts by ID",
59108
"operationId": "getUserPostsById",

examples/vite/src/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function App() {
1616
api
1717
.get('/users/{userId}/posts', {
1818
params: { userId: 1 },
19+
// query: { postId: 1 },
1920
})
2021
.then((res) => {
2122
console.log(res)

packages/generator/src/generate-interface.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { toPascal } from '@devup-api/utils'
33
import type { OpenAPIV3_1 } from 'openapi-types'
44
import { convertCase } from './convert-case'
55
import {
6-
areAllPropertiesOptional,
76
extractParameters,
87
extractRequestBody,
98
formatTypeValue,
@@ -299,14 +298,9 @@ export function generateInterface(
299298
const interfaceEntries = entries
300299
.map(([key, endpointValue]) => {
301300
const formattedValue = formatTypeValue(endpointValue, 2)
302-
// Check if all properties in endpointValue are optional
303-
const allOptional =
304-
typeof endpointValue === 'object' &&
305-
endpointValue !== null &&
306-
!Array.isArray(endpointValue) &&
307-
areAllPropertiesOptional(endpointValue as Record<string, unknown>)
308-
const optionalMarker = allOptional ? '?' : ''
309-
return ` ${wrapInterfaceKeyGuard(key)}${optionalMarker}: ${formattedValue}`
301+
// Top-level keys in ApiStruct should never be optional
302+
// Only params, query, body etc. can be optional if all their properties are optional
303+
return ` ${wrapInterfaceKeyGuard(key)}: ${formattedValue}`
310304
})
311305
.join(';\n')
312306

packages/generator/src/generate-schema.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,16 @@ export function formatType(
281281
return `${nextIndentStr}${key}: ${formattedValue}`
282282
}
283283

284+
// Check if value is an object (like params, query) with all optional properties
285+
const valueAllOptional =
286+
typeof value === 'object' &&
287+
value !== null &&
288+
!Array.isArray(value) &&
289+
areAllPropertiesOptional(value as Record<string, unknown>)
290+
const optionalMarker = valueAllOptional ? '?' : ''
291+
284292
const formattedValue = formatTypeValue(value, nextIndent)
285-
// Key already has '?' if it's optional (from getTypeFromSchema), keep it as is
286-
return `${nextIndentStr}${key}: ${formattedValue}`
293+
return `${nextIndentStr}${key}${optionalMarker}: ${formattedValue}`
287294
})
288295
.join(';\n')
289296

0 commit comments

Comments
 (0)