Skip to content

Commit 79945b1

Browse files
committed
Add response
1 parent 2aa19bd commit 79945b1

File tree

3 files changed

+81
-39
lines changed

3 files changed

+81
-39
lines changed

packages/fetch/src/api.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ export class DevupApi {
3434
path: T,
3535
...options: [RequiredOptions<O>] extends [never]
3636
? [options?: DevupApiRequestInit]
37-
: [options: DevupApiRequestInit & O]
37+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
3838
) {
3939
return this.request(path, {
4040
method: 'GET',
4141
...options[0],
42-
} as DevupApiRequestInit & O)
42+
} as DevupApiRequestInit & Omit<O, 'response'>)
4343
}
4444

4545
GET<
@@ -49,12 +49,12 @@ export class DevupApi {
4949
path: T,
5050
...options: [RequiredOptions<O>] extends [never]
5151
? [options?: DevupApiRequestInit]
52-
: [options: DevupApiRequestInit & O]
52+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
5353
) {
5454
return this.request(path, {
5555
method: 'GET',
5656
...options[0],
57-
} as DevupApiRequestInit & O)
57+
} as DevupApiRequestInit & Omit<O, 'response'>)
5858
}
5959

6060
post<
@@ -64,12 +64,12 @@ export class DevupApi {
6464
path: T,
6565
...options: [RequiredOptions<O>] extends [never]
6666
? [options?: DevupApiRequestInit]
67-
: [options: DevupApiRequestInit & O]
67+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
6868
) {
6969
return this.request(path, {
7070
method: 'POST',
7171
...options[0],
72-
} as DevupApiRequestInit & O)
72+
} as DevupApiRequestInit & Omit<O, 'response'>)
7373
}
7474

7575
POST<
@@ -79,12 +79,12 @@ export class DevupApi {
7979
path: T,
8080
...options: [RequiredOptions<O>] extends [never]
8181
? [options?: DevupApiRequestInit]
82-
: [options: DevupApiRequestInit & O]
82+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
8383
) {
8484
return this.request(path, {
8585
method: 'POST',
8686
...options[0],
87-
} as DevupApiRequestInit & O)
87+
} as DevupApiRequestInit & Omit<O, 'response'>)
8888
}
8989

9090
put<
@@ -94,12 +94,12 @@ export class DevupApi {
9494
path: T,
9595
...options: [RequiredOptions<O>] extends [never]
9696
? [options?: DevupApiRequestInit]
97-
: [options: DevupApiRequestInit & O]
97+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
9898
) {
9999
return this.request(path, {
100100
method: 'PUT',
101101
...options[0],
102-
} as DevupApiRequestInit & O)
102+
} as DevupApiRequestInit & Omit<O, 'response'>)
103103
}
104104

105105
PUT<
@@ -109,12 +109,12 @@ export class DevupApi {
109109
path: T,
110110
...options: [RequiredOptions<O>] extends [never]
111111
? [options?: DevupApiRequestInit]
112-
: [options: DevupApiRequestInit & O]
112+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
113113
) {
114114
return this.request(path, {
115115
method: 'PUT',
116116
...options[0],
117-
} as DevupApiRequestInit & O)
117+
} as DevupApiRequestInit & Omit<O, 'response'>)
118118
}
119119

120120
delete<
@@ -124,12 +124,12 @@ export class DevupApi {
124124
path: T,
125125
...options: [RequiredOptions<O>] extends [never]
126126
? [options?: DevupApiRequestInit]
127-
: [options: DevupApiRequestInit & O]
127+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
128128
) {
129129
return this.request(path, {
130130
method: 'DELETE',
131131
...options[0],
132-
} as DevupApiRequestInit & O)
132+
} as DevupApiRequestInit & Omit<O, 'response'>)
133133
}
134134

135135
DELETE<
@@ -139,12 +139,12 @@ export class DevupApi {
139139
path: T,
140140
...options: [RequiredOptions<O>] extends [never]
141141
? [options?: DevupApiRequestInit]
142-
: [options: DevupApiRequestInit & O]
142+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
143143
) {
144144
return this.request(path, {
145145
method: 'DELETE',
146146
...options[0],
147-
} as DevupApiRequestInit & O)
147+
} as DevupApiRequestInit & Omit<O, 'response'>)
148148
}
149149

150150
patch<
@@ -154,12 +154,12 @@ export class DevupApi {
154154
path: T,
155155
...options: [RequiredOptions<O>] extends [never]
156156
? [options?: DevupApiRequestInit]
157-
: [options: DevupApiRequestInit & O]
157+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
158158
) {
159159
return this.request(path, {
160160
method: 'PATCH',
161161
...options[0],
162-
} as DevupApiRequestInit & O)
162+
} as DevupApiRequestInit & Omit<O, 'response'>)
163163
}
164164

165165
PATCH<
@@ -169,24 +169,19 @@ export class DevupApi {
169169
path: T,
170170
...options: [RequiredOptions<O>] extends [never]
171171
? [options?: DevupApiRequestInit]
172-
: [options: DevupApiRequestInit & O]
172+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
173173
) {
174174
return this.request(path, {
175175
method: 'PATCH',
176176
...options[0],
177-
} as DevupApiRequestInit & O)
177+
} as DevupApiRequestInit & Omit<O, 'response'>)
178178
}
179179

180-
request<
181-
T extends DevupApiStructKey,
182-
O extends Additional<T, DevupApiStruct> & {
183-
params?: Record<string, string | number | boolean | null | undefined>
184-
},
185-
>(
180+
request<T extends DevupApiStructKey, O extends Additional<T, DevupApiStruct>>(
186181
path: T,
187182
...options: [RequiredOptions<O>] extends [never]
188183
? [options?: DevupApiRequestInit]
189-
: [options: DevupApiRequestInit & O]
184+
: [options: DevupApiRequestInit & Omit<O, 'response'>]
190185
) {
191186
const { method, url } = getUrlWithMethod(path)
192187
const mergedOptions = {

packages/generator/src/generate-interface.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,13 @@ export function generateInterface(
284284
// Use component reference
285285
responseType = `DevupResponseComponentStruct['${schemaName}']`
286286
} else {
287-
// Extract schema type
287+
// Extract schema type with response options
288+
const responseDefaultNonNullable =
289+
options?.responseDefaultNonNullable ?? true
288290
const { type: schemaType } = getTypeFromSchema(
289291
jsonContent.schema,
290292
schema,
293+
{ defaultNonNullable: responseDefaultNonNullable },
291294
)
292295
responseType = schemaType
293296
}
@@ -312,18 +315,24 @@ export function generateInterface(
312315
// Use component reference for array items
313316
responseType = `Array<DevupResponseComponentStruct['${schemaName}']>`
314317
} else {
315-
// Extract schema type
318+
// Extract schema type with response options
319+
const responseDefaultNonNullable =
320+
options?.responseDefaultNonNullable ?? true
316321
const { type: schemaType } = getTypeFromSchema(
317322
jsonContent.schema,
318323
schema,
324+
{ defaultNonNullable: responseDefaultNonNullable },
319325
)
320326
responseType = schemaType
321327
}
322328
} else {
323-
// Extract schema type
329+
// Extract schema type with response options
330+
const responseDefaultNonNullable =
331+
options?.responseDefaultNonNullable ?? true
324332
const { type: schemaType } = getTypeFromSchema(
325333
jsonContent.schema,
326334
schema,
335+
{ defaultNonNullable: responseDefaultNonNullable },
327336
)
328337
responseType = schemaType
329338
}
@@ -363,9 +372,17 @@ export function generateInterface(
363372
schema.components.schemas,
364373
)) {
365374
if (schemaObj) {
375+
const requestDefaultNonNullable =
376+
options?.requestDefaultNonNullable ?? false
377+
const responseDefaultNonNullable =
378+
options?.responseDefaultNonNullable ?? true
379+
366380
const { type: schemaType } = getTypeFromSchema(
367381
schemaObj as OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject,
368382
schema,
383+
requestSchemaNames.has(schemaName)
384+
? { defaultNonNullable: requestDefaultNonNullable }
385+
: { defaultNonNullable: responseDefaultNonNullable },
369386
)
370387
// Keep original schema name as-is
371388
if (requestSchemaNames.has(schemaName)) {

packages/generator/src/generate-schema.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,16 @@ export function resolveSchemaRef(
6565
export function getTypeFromSchema(
6666
schema: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject,
6767
document: OpenAPIV3_1.Document,
68+
options?: {
69+
defaultNonNullable?: boolean
70+
},
6871
): { type: unknown; default?: unknown } {
72+
const defaultNonNullable = options?.defaultNonNullable ?? false
6973
// Handle $ref
7074
if ('$ref' in schema) {
7175
const resolved = resolveSchemaRef(schema.$ref, document)
7276
if (resolved) {
73-
return getTypeFromSchema(resolved, document)
77+
return getTypeFromSchema(resolved, document, options)
7478
}
7579
return { type: 'unknown', default: undefined }
7680
}
@@ -79,7 +83,9 @@ export function getTypeFromSchema(
7983

8084
// Handle allOf, anyOf, oneOf
8185
if (schemaObj.allOf) {
82-
const types = schemaObj.allOf.map((s) => getTypeFromSchema(s, document))
86+
const types = schemaObj.allOf.map((s) =>
87+
getTypeFromSchema(s, document, options),
88+
)
8389
return {
8490
type:
8591
types.length > 0
@@ -91,7 +97,7 @@ export function getTypeFromSchema(
9197

9298
if (schemaObj.anyOf || schemaObj.oneOf) {
9399
const types = (schemaObj.anyOf || schemaObj.oneOf || []).map((s) =>
94-
getTypeFromSchema(s, document),
100+
getTypeFromSchema(s, document, options),
95101
)
96102
return {
97103
type:
@@ -130,7 +136,7 @@ export function getTypeFromSchema(
130136
if (schemaObj.type === 'array') {
131137
const items = schemaObj.items
132138
if (items) {
133-
const itemType = getTypeFromSchema(items, document)
139+
const itemType = getTypeFromSchema(items, document, options)
134140
return {
135141
type: `Array<${formatTypeValue(itemType.type)}>`,
136142
default: schemaObj.default,
@@ -146,9 +152,26 @@ export function getTypeFromSchema(
146152

147153
if (schemaObj.properties) {
148154
for (const [key, value] of Object.entries(schemaObj.properties)) {
149-
const propType = getTypeFromSchema(value, document)
150-
// Mark as optional if not in required array
151-
if (!required.includes(key)) {
155+
const propType = getTypeFromSchema(value, document, options)
156+
// Check if property has default value
157+
// Need to resolve $ref if present to check for default
158+
let hasDefault = false
159+
if ('$ref' in value) {
160+
const resolved = resolveSchemaRef(value.$ref, document)
161+
if (resolved) {
162+
hasDefault = resolved.default !== undefined
163+
}
164+
} else {
165+
const propSchema = value as OpenAPIV3_1.SchemaObject
166+
hasDefault = propSchema.default !== undefined
167+
}
168+
const isInRequired = required.includes(key)
169+
170+
// If defaultNonNullable is true and has default, treat as required
171+
// Otherwise, mark as optional if not in required array
172+
if (defaultNonNullable && hasDefault && !isInRequired) {
173+
props[key] = propType
174+
} else if (!isInRequired) {
152175
props[`${key}?`] = propType
153176
} else {
154177
props[key] = propType
@@ -164,6 +187,7 @@ export function getTypeFromSchema(
164187
const additionalType = getTypeFromSchema(
165188
schemaObj.additionalProperties,
166189
document,
190+
options,
167191
)
168192
props['[key: string]'] = {
169193
type: additionalType.type,
@@ -373,6 +397,7 @@ export function extractParameters(
373397
const { type: paramType, default: paramDefault } = getTypeFromSchema(
374398
paramSchema,
375399
document,
400+
{ defaultNonNullable: false },
376401
)
377402
const result = {
378403
...resolved,
@@ -394,6 +419,7 @@ export function extractParameters(
394419
const { type: paramType, default: paramDefault } = getTypeFromSchema(
395420
paramSchema,
396421
document,
422+
{ defaultNonNullable: false },
397423
)
398424
const result = {
399425
...param,
@@ -434,7 +460,9 @@ export function extractRequestBody(
434460
resolved.content as OpenAPIV3_1.RequestBodyObject['content']
435461
const jsonContent = content['application/json']
436462
if (jsonContent && 'schema' in jsonContent && jsonContent.schema) {
437-
return getTypeFromSchema(jsonContent.schema, document).type
463+
return getTypeFromSchema(jsonContent.schema, document, {
464+
defaultNonNullable: false,
465+
}).type
438466
}
439467
}
440468
return 'unknown'
@@ -444,7 +472,9 @@ export function extractRequestBody(
444472
if (content) {
445473
const jsonContent = content['application/json']
446474
if (jsonContent && 'schema' in jsonContent && jsonContent.schema) {
447-
return getTypeFromSchema(jsonContent.schema, document).type
475+
return getTypeFromSchema(jsonContent.schema, document, {
476+
defaultNonNullable: false,
477+
}).type
448478
}
449479
}
450480

0 commit comments

Comments
 (0)