diff --git a/src/__tests__/__snapshots__/gen-api-models-oas3.test.ts.snap b/src/__tests__/__snapshots__/gen-api-models-oas3.test.ts.snap
index 6a78104b..e04b4dd0 100644
--- a/src/__tests__/__snapshots__/gen-api-models-oas3.test.ts.snap
+++ b/src/__tests__/__snapshots__/gen-api-models-oas3.test.ts.snap
@@ -170,7 +170,7 @@ exports[`gen-api-models should generate the operator definition 1`] = `
*/
// Request type definition
- export type TestAuthBearerT = r.IGetApiRequestType<{readonly bearerToken: string}, \\"Authorization\\", never, r.IResponseType<200, undefined>|r.IResponseType<403, undefined>>;
+ export type TestAuthBearerT = r.IGetApiRequestType<{readonly bearerToken: string,readonly qo?: string,readonly qr: string}, \\"Authorization\\", never, r.IResponseType<200, undefined>|r.IResponseType<403, undefined>>;
// Decodes the success response with a custom success type
export function testAuthBearerDecoder(type: t.Type) { return r.composeResponseDecoders(r.ioResponseDecoder<200, (typeof type)[\\"_A\\"], (typeof type)[\\"_O\\"]>(200, type), r.constantResponseDecoder(403, undefined)); }
@@ -508,3 +508,19 @@ exports[`gen-api-models should support file uploads 1`] = `
// Decodes the success response with the type defined in the specs
export const testFileUploadDefaultDecoder = () => testFileUploadDecoder(t.undefined);"
`;
+
+exports[`gen-api-models should support generate serializers 1`] = `
+"
+ /****************************************************************
+ * testSerializer
+ */
+
+ // Request type definition
+ export type TestSerializerT = r.IPostApiRequestType<{readonly qo?: string,readonly paginationRequest?: string}, \\"Content-Type\\", never, r.IResponseType<200, Message>|r.IResponseType<403, Problem>>;
+
+ // Decodes the success response with a custom success type
+ export function testSerializerDecoder(type: t.Type) { return r.composeResponseDecoders(r.ioResponseDecoder<200, (typeof type)[\\"_A\\"], (typeof type)[\\"_O\\"]>(200, type), r.ioResponseDecoder<403, (typeof Problem)[\\"_A\\"], (typeof Problem)[\\"_O\\"]>(403, Problem)); }
+
+ // Decodes the success response with the type defined in the specs
+ export const testSerializerDefaultDecoder = () => testSerializerDecoder(Message);"
+`;
diff --git a/src/__tests__/__snapshots__/gen-api-models.test.ts.snap b/src/__tests__/__snapshots__/gen-api-models.test.ts.snap
index 3fa0ca2f..815dc1cd 100644
--- a/src/__tests__/__snapshots__/gen-api-models.test.ts.snap
+++ b/src/__tests__/__snapshots__/gen-api-models.test.ts.snap
@@ -508,3 +508,19 @@ exports[`gen-api-models should support file uploads 1`] = `
// Decodes the success response with the type defined in the specs
export const testFileUploadDefaultDecoder = () => testFileUploadDecoder(t.undefined);"
`;
+
+exports[`gen-api-models should support generate serializers 1`] = `
+"
+ /****************************************************************
+ * testSerializer
+ */
+
+ // Request type definition
+ export type TestSerializerT = r.IPostApiRequestType<{readonly qo?: string,readonly paginationRequest?: string}, \\"Content-Type\\", never, r.IResponseType<200, Message>|r.IResponseType<403, Problem>>;
+
+ // Decodes the success response with a custom success type
+ export function testSerializerDecoder(type: t.Type) { return r.composeResponseDecoders(r.ioResponseDecoder<200, (typeof type)[\\"_A\\"], (typeof type)[\\"_O\\"]>(200, type), r.ioResponseDecoder<403, (typeof Problem)[\\"_A\\"], (typeof Problem)[\\"_O\\"]>(403, Problem)); }
+
+ // Decodes the success response with the type defined in the specs
+ export const testSerializerDefaultDecoder = () => testSerializerDecoder(Message);"
+`;
diff --git a/src/__tests__/api.yaml b/src/__tests__/api.yaml
index fec97352..6bcf4553 100644
--- a/src/__tests__/api.yaml
+++ b/src/__tests__/api.yaml
@@ -45,7 +45,31 @@ paths:
responses:
"200":
description: "File uploaded"
+ /test-serializers:
+ post:
+ operationId: "testSerializer"
+ parameters:
+ - name: "qo"
+ in: "query"
+ required: false
+ type: "string"
+ - $ref: "#/parameters/PaginationRequest"
+ responses:
+ "200":
+ description: "File uploaded"
+ schema:
+ $ref: "#/definitions/Message"
+ "403":
+ description: "Error string"
+ schema:
+ $ref: "#/definitions/Problem"
definitions:
+ Problem:
+ properties:
+ title:
+ type: string
+ type:
+ type: string
AllOfTest:
allOf:
- type: object
diff --git a/src/__tests__/api_oas3.yaml b/src/__tests__/api_oas3.yaml
index 9e3c66d2..3040c5a1 100644
--- a/src/__tests__/api_oas3.yaml
+++ b/src/__tests__/api_oas3.yaml
@@ -42,6 +42,29 @@ paths:
responses:
"200":
description: File uploaded
+ /test-serializers:
+ post:
+ operationId: "testSerializer"
+ parameters:
+ - name: "qo"
+ in: "query"
+ required: false
+ schema:
+ type: "string"
+ - $ref: "#/components/parameters/PaginationRequest"
+ responses:
+ "200":
+ description: "File uploaded"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Message"
+ "403":
+ description: "Error string"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Problem"
servers:
- url: https://localhost/api/v1
components:
@@ -79,6 +102,12 @@ components:
write: Grants write access
admin: Grants access to admin operations
schemas:
+ Problem:
+ properties:
+ title:
+ type: string
+ type:
+ type: string
AllOfTest:
allOf:
- type: object
diff --git a/src/__tests__/gen-api-models-oas3.test.ts b/src/__tests__/gen-api-models-oas3.test.ts
index 146aa8b5..8b0fac8f 100644
--- a/src/__tests__/gen-api-models-oas3.test.ts
+++ b/src/__tests__/gen-api-models-oas3.test.ts
@@ -273,7 +273,26 @@ describe("gen-api-models", () => {
"post",
operation.operationId,
operation,
- spec.parameters,
+ spec.components.parameters,
+ spec.components.securitySchemes,
+ [],
+ {},
+ "undefined",
+ "undefined",
+ true
+ );
+
+ expect(code.e1).toMatchSnapshot();
+ });
+
+ it("should support generate serializers", async () => {
+ const operation = spec.paths["/test-serializers"].post;
+
+ const code = await renderOperation(
+ "post",
+ operation.operationId,
+ operation,
+ spec.components.parameters,
spec.components.securitySchemes,
[],
{},
diff --git a/src/__tests__/gen-api-models.test.ts b/src/__tests__/gen-api-models.test.ts
index 059131e2..4d7edeb3 100644
--- a/src/__tests__/gen-api-models.test.ts
+++ b/src/__tests__/gen-api-models.test.ts
@@ -284,4 +284,24 @@ describe("gen-api-models", () => {
expect(code.e1).toMatchSnapshot();
});
+
+ it("should support generate serializers", async () => {
+ const operation = spec.paths["/test-serializers"].post;
+
+ const code = await renderOperation(
+ "post",
+ operation.operationId,
+ operation,
+ spec.parameters,
+ spec.securityDefinitions,
+ [],
+ {},
+ "undefined",
+ "undefined",
+ true
+ );
+
+ expect(code.e1).toMatchSnapshot();
+ });
+
});
diff --git a/src/gen-api-models.ts b/src/gen-api-models.ts
index 1946278c..c888b942 100644
--- a/src/gen-api-models.ts
+++ b/src/gen-api-models.ts
@@ -62,13 +62,25 @@ function typeFromRef(
s: string
): ITuple2<"definition" | "parameter" | "other", string> | undefined {
const parts = s.split("/");
+
+ if (!parts) {
+ return undefined;
+ }
+
+ // If it's an OAS3, remove the "components" part.
+ if (parts[1] === "components") {
+ parts.splice(1,1);
+ }
+
if (parts && parts.length === 3) {
const refType: "definition" | "parameter" | "other" =
parts[1] === "definitions"
? "definition"
- : parts[1] === "parameters"
- ? "parameter"
- : "other";
+ : parts[1] === "schemas"
+ ? "definition"
+ : parts[1] === "parameters"
+ ? "parameter"
+ : "other";
return Tuple2(refType, parts[2]);
}
return undefined;
@@ -120,11 +132,12 @@ export function renderOperation(
OpenAPIV2.InBodyParameterObject | OpenAPIV3.ParameterObject
>;
parameters.forEach(param => {
- if (param.name && (param as any).type) {
+ if (param.name && getParameterType(param)) {
// The parameter description is inline
+ // and the parameter type is not undefined.
const isRequired = param.required === true;
params[`${param.name}${isRequired ? "" : "?"}`] = specTypeToTs(
- (param as any).type
+ getParameterType(param)!
);
return;
}
@@ -148,11 +161,17 @@ export function renderOperation(
console.warn(`Unrecognized ref type [${refInParam}]`);
return;
}
+ // if the reference type is "definition"
+ // e2 contains a schema object
+ // otherwise it is the schema name
const paramType: string | undefined =
refType === "definition"
? parsedRef.e2
- : specParameters
- ? specTypeToTs((specParameters as any)[parsedRef.e2].type)
+ // check that specParameters contain a valid declaration too!
+ : specParameters && getParameterType((specParameters as any)[parsedRef.e2])
+ ? specTypeToTs(
+ getParameterType((specParameters as any)[parsedRef.e2])!
+ )
: undefined;
if (paramType === undefined) {
@@ -217,7 +236,19 @@ export function renderOperation(
const responses = Object.keys(operation.responses as object).map(
responseStatus => {
const response = operation.responses![responseStatus];
- const typeRef = response.schema ? response.schema.$ref : undefined;
+ const media_type = "application/json"
+ const typeRef =
+ // get schema from Swagger...
+ response.schema
+ ? response.schema.$ref
+ // ... or try with OAS3
+ : response.content
+ ? response.content[media_type]
+ && response.content[media_type].schema
+ ? response.content[media_type].schema.$ref
+ : undefined
+ // Not OAS2 or missing media-type in response.content
+ : undefined;
const parsedRef = typeRef ? typeFromRef(typeRef) : undefined;
if (parsedRef !== undefined) {
importedTypes.add(parsedRef.e2);
@@ -273,6 +304,20 @@ export function renderOperation(
return Tuple2(code, importedTypes);
}
+function getParameterType(
+ parameter:
+ any | undefined
+): string | undefined {
+ if (!parameter) {
+ return undefined;
+ }
+ return parameter.type
+ ? parameter.type
+ : parameter.schema
+ ? parameter.schema.type
+ : undefined;
+}
+
function getAuthHeaders(
securityDefinitions:
| OpenAPIV2.SecurityDefinitionsObject