From 26f97645b98e03e63e9501c30a7d4267747b9171 Mon Sep 17 00:00:00 2001 From: Rusty Conover Date: Mon, 21 Jun 2021 16:51:40 -0400 Subject: [PATCH] Feature: add full response typing for status code, data and headers. This commit adds additional type information to the route's response object that allows types to be created that express the combination of status code, data and headers for each response. This type information can be used to "narrow" a response type based on an HTTP status code. This narrowing is useful since it can prevent type mismatches where a status code is presumed to have one type but in actuality it returns another. Additionally, response headers are now associated with data types and status codes rather than being free form. A caveat right now is that only there are no response codes like 3XX or 5XX, every code must be explicitly listed. --- src/routes.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/routes.js b/src/routes.js index 787dfb4e..2beb1a0f 100644 --- a/src/routes.js +++ b/src/routes.js @@ -2,6 +2,7 @@ const _ = require("lodash"); const { types, parseSchema, + getType, getRefType, getInlineParseContent, checkAndAddNull, @@ -475,6 +476,21 @@ const getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => { (response) => !response.isSuccess && response.type !== TS_KEYWORDS.ANY, ); + const handleResponseHeaders = (src) => { + if (!src) { + return "headers: {},"; + } + const headerTypes = Object.fromEntries( + Object.entries(src).map(([k, v]) => { + return [k, getType(v)]; + }), + ); + const r = `headers: { ${Object.entries(headerTypes) + .map(([k, v]) => `"${k}": ${v}`) + .join(",")} },`; + return r; + }; + return { contentTypes, responses: responseInfos, @@ -486,6 +502,19 @@ const getResponseBodyInfo = (routeInfo, routeParams, parsedSchemas) => { schemas: errorResponses, type: _.uniq(errorResponses.map((response) => response.type)).join(" | ") || TS_KEYWORDS.ANY, }, + full: { + types: + responseInfos + .map( + (response) => `{ + data: ${response.type}, status: ${response.status}, statusCode: ${ + response.status + }, statusText: "${response.description}", ${handleResponseHeaders( + response.headers, + )} config: {} }`, + ) + .join(" | ") || TS_KEYWORDS.ANY, + }, }; }; @@ -685,6 +714,7 @@ const parseRoutes = ({ contentTypes: responseBodyInfo.contentTypes, type: responseBodyInfo.success.type, errorType: responseBodyInfo.error.type, + fullTypes: responseBodyInfo.full.types, }, raw: rawRouteInfo, };