Skip to content

Commit

Permalink
fix: solve issue where responses were not typed correctly
Browse files Browse the repository at this point in the history
ref: #420
fix: #419 

---------

Co-authored-by: Xiphe <github@xiphe.net>
  • Loading branch information
cvereterra and Xiphe committed May 9, 2023
1 parent a69a110 commit 44848a2
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 23 deletions.
37 changes: 37 additions & 0 deletions src/codegen/__fixtures__/issue-419.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"openapi": "3.0.2",
"info": {
"title": "Swagger Petstore - OpenAPI 3.0",
"version": "1.0.5",
"description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)"
},
"servers": [
{
"url": "/api/v3"
}
],
"paths": {
"/healthcheck": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"properties": {
"message": {
"type": "string",
"example": "I'm health"
}
},
"required": ["message"]
}
}
}
}
}
}
}
}
}
50 changes: 27 additions & 23 deletions src/codegen/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -731,30 +731,34 @@ export default class ApiGenerator {
| OpenAPIV3.ReferenceObject,
onlyMode?: OnlyMode
): ts.TypeLiteralNode {
const members: ts.TypeElement[] = Object.keys(props)
.filter((name) => {
const schema = props[name];
if (!onlyMode)
return (
!this.isSchemaReadOnly(schema) && !this.isSchemaWriteOnly(schema)
);
if (onlyMode === "readOnly") return this.isSchemaReadOnly(schema);
else if (onlyMode === "writeOnly")
return this.isSchemaWriteOnly(schema);
})
.map((name) => {
const schema = props[name];
const isRequired = required && required.includes(name);
let type = this.getTypeFromSchema(schema, name);
if (!isRequired && this.opts.unionUndefined) {
type = factory.createUnionTypeNode([type, cg.keywordType.undefined]);
}
return cg.createPropertySignature({
questionToken: !isRequired,
name,
type,
});
// Check if any of the props are readOnly or writeOnly schemas
const propertyNames = Object.keys(props);
const filteredPropertyNames = propertyNames.filter((name) => {
const schema = props[name];
if (!onlyMode)
return (
!this.isSchemaReadOnly(schema) && !this.isSchemaWriteOnly(schema)
);
if (onlyMode === "readOnly") return this.isSchemaReadOnly(schema);
else if (onlyMode === "writeOnly") return this.isSchemaWriteOnly(schema);
});
// By filtering by readOnly/writeOnly props, we may have filtered out all props in schemas
const hasFilteredAllProps = filteredPropertyNames.length === 0;
const names = hasFilteredAllProps ? propertyNames : filteredPropertyNames;

const members: ts.TypeElement[] = names.map((name) => {
const schema = props[name];
const isRequired = required && required.includes(name);
let type = this.getTypeFromSchema(schema, name);
if (!isRequired && this.opts.unionUndefined) {
type = factory.createUnionTypeNode([type, cg.keywordType.undefined]);
}
return cg.createPropertySignature({
questionToken: !isRequired,
name,
type,
});
});
if (additionalProperties) {
const type =
additionalProperties === true
Expand Down
6 changes: 6 additions & 0 deletions src/codegen/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ describe("generateSource", () => {
"export interface ExampleSchema { always_present: string; } export interface ExampleSchemaRead extends ExampleSchema { read_only_prop: string; } export interface ExampleSchemaWrite extends ExampleSchema { write_only_prop: string; }"
);
});

it("shouldn't filter all properties of schema when using readOnly/writeOnly", async () => {
const src = await generate("/__fixtures__/issue-419.json");

expect(src).toContain("message: string");
});
});

describe("useEnumType", () => {
Expand Down

0 comments on commit 44848a2

Please sign in to comment.