Skip to content

Fix V2 parameter types #489

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 8, 2021
Merged

Conversation

yamacent
Copy link
Contributor

close #470

@yamacent yamacent force-pushed the fix-v2-parameter-types branch from ea0a6f4 to 2598f10 Compare February 26, 2021 12:36
@drwpow
Copy link
Contributor

drwpow commented Feb 27, 2021

Thanks so much! I’ll review it soon

@yamacent
Copy link
Contributor Author

@drwpow Thanks for you reply! I'll modify tests as well if the direction of this PR is okay.

}

function transformItemsObj(obj: ItemsObject): string {
switch (obj.type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code actually already exists in utils.ts#L29. So by re-adding different logic, we could introduce bugs.

@drwpow
Copy link
Contributor

drwpow commented Mar 2, 2021

Thanks so much for your PR! I think the fix is much easier than expected. We’re using the same code for OpenAPI 3.0 and Swagger 2.0, and the unknown is happening because it’s trying to parse everything as 3.0 (it’s looking for [parameter].schema.type, when it should be looking for just [parameter].type). All we need to change is one line on parameters.ts#L43.

- paramObj.schema ? transformSchemaObj(paramObj.schema) : "unknown"
+ if (version === 2) {
+  paramObj.type ? transformSchemaObj(paramObj) : "unknown"
+ } else if (version === 3) {
+   paramObj.schema ? transformSchemaObj(paramObj.schema) : "unknown"
+ } 

So that’s step 1. Step 2 would be to pass that version from transform/index.ts into transform/paths.ts and finally into transform/parameters.ts. That should fix it!

Also, I find it best to start by actually making a new test in parameters.test.ts first, and then working until it passes.

@yamacent
Copy link
Contributor Author

yamacent commented Mar 3, 2021

@drwpow
Thank you for your review and kind explanation!
I added tests to parameters.test.ts and fixed the code to pass the test as you say.
Please review again.
Also, could you please tell me how to fix tests in tests/v2 directory?

@drwpow
Copy link
Contributor

drwpow commented Mar 4, 2021

Also, could you please tell me how to fix tests in tests/v2 directory?

Ah so you know what? This problem is a bit trickier than expected. I seemed to miss this critical part of the Open API 2.0 specs that states that we only use the top-level object if in is NOT body. Otherwise, we do use schema if in is body.

Will comment a fix on your PR and I think we can wrap this up!

mappedParams[reference.in][reference.name || paramName] = {
...reference,
schema: { $ref: paramObj.$ref },
...(version === 2 ? schema : version === 3 ? { schema } : {}),
Copy link
Contributor

@drwpow drwpow Mar 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So because this is a bit difficult to follow, let’s take up a little more space:

if (version === 2) {
  mappedParams[reference.in][reference.name || paramName] = {
    ..reference,
    $ref: paramObj.$ref,
  } as any;
} else if (version === 3) {
  mappedParams[reference.in][reference.name || paramName] = {
    ..reference,
    schema: { $ref: paramObj.$ref },
  } as any;
}

Your version takes up fewer lines, and is good in that regard. But you have a nested ternary + a spread operator, and it’s very easy for someone to make a mistake (if not you, the next person to touch this).

This version is more verbose, but it’s a bit clearer.

Copy link
Contributor Author

@yamacent yamacent Mar 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you. Fixed in 8c02bd7

Perhaps we need to consider the case where in is body here as well?

};\n`;
let type = ``;
if (version === 2) {
type = paramObj.type ? transformSchemaObj(paramObj) : "unknown";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So according to the OpenAPI 2.0 spec, this will cause a regression, which is why the V2 tests are failing (to your credit, I think the specs are very confusing here, and I suspect it’s why they changed it for 3.0 🙂 ).

Instead, this needs to be:

Suggested change
type = paramObj.type ? transformSchemaObj(paramObj) : "unknown";
if (paramObj.in === 'body' && paramObj.schema) {
type = transformSchemaObj(paramObj.schema);
} else if (paramObj.type) {
type = transformSchemaObj(paramObj);
} else {
type = 'unknown';
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I missed the spec.. fixed in fe3b69b

output += ` "${paramName}"${required}: ${
paramObj.schema ? transformSchemaObj(paramObj.schema) : "unknown"
};\n`;
let type = ``;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we use another name, other than type? Only because type is a special word in TypeScript (it doesn’t seem to be causing any problems here, but just for clarity)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! I renamed it to paramType. bb668ed

if (version === 2) {
type = paramObj.type ? transformSchemaObj(paramObj) : "unknown";
} else if (version === 3) {
type = paramObj.schema ? transformSchemaObj(paramObj.schema) : "unknown";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻 I believe this is still correct.

items: {
type: "string",
describe.only("transformParametersArray()", () => {
describe("v2", () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tests! 💯

]).trim()
).toBe(
`query: {
{ in: "path", name: "three_d_secure", required: true, type: "string" },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: with our new knowledge, let’s try adding a body param here, like: { in: "body", schema: { type: "string" } }. Then we can test if it generated correctly.

@yamacent
Copy link
Contributor Author

yamacent commented Mar 4, 2021

@drwpow By the way, do we need to keep the changes I did in src/types/index.ts?

export interface ParameterObject {
name?: string; // required
in?: "query" | "header" | "path" | /* V3 */ "cookie" | /* V2 */ "formData" | /* V2 */ "body"; // required
description?: string;
required?: boolean;
deprecated?: boolean;
schema?: ReferenceObject | SchemaObject; // required
type?: "string" | "number" | "integer" | "boolean" | "array" | "file"; // V2 ONLY
items?: ItemsObject; // V2 ONLY
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be ReferenceObject | SchemaObject I believe.

@@ -60,13 +60,22 @@ export interface OperationObject {
responses?: Record<string, ReferenceObject | ResponseObject>; // required
}

export interface ItemsObject {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can remove this; this seems to be a duplication of SchemaObject but with fewer fields (see SchemaObject["items"] as a reference

@drwpow
Copy link
Contributor

drwpow commented Mar 7, 2021

This is looking great! It looks like the only thing keeping the tests from passing are to take tests/v2/generated/*.ts and copy them over to tests/v2/expected/*.ts. Basically these are “snapshot” tests that test very, very large schemas.

These snapshot tests are bad at testing individual features because there are so many lines. But they are good at making sure that complete schemas are generating correctly. I believe all the changes I see point to your PR working as intended; it looks like we are now at an improvement with no other regressions!

I’ll go ahead and approve this, and as soon as you copy the files to tests/v2/expected/*.ts the tests should be working. Then we can merge & release this!

@codecov
Copy link

codecov bot commented Mar 8, 2021

Codecov Report

Merging #489 (ce97089) into main (3a20869) will increase coverage by 0.21%.
The diff coverage is 89.47%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #489      +/-   ##
==========================================
+ Coverage   84.61%   84.82%   +0.21%     
==========================================
  Files           9        9              
  Lines         312      323      +11     
  Branches       98      105       +7     
==========================================
+ Hits          264      274      +10     
- Misses         45       46       +1     
  Partials        3        3              
Impacted Files Coverage Δ
src/transform/index.ts 56.60% <50.00%> (ø)
src/transform/parameters.ts 97.43% <92.85%> (-2.57%) ⬇️
src/transform/operation.ts 96.42% <100.00%> (ø)
src/transform/paths.ts 91.66% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3a20869...ce97089. Read the comment docs.

@yamacent
Copy link
Contributor Author

yamacent commented Mar 8, 2021

@drwpow
I fixed types where you pointed out ( a5b9c79 ) and updated tests/v2/expected/*.ts as you said ( 2e9f004 ).
Please confirm.

@drwpow
Copy link
Contributor

drwpow commented Mar 8, 2021

This looks great, thank you!

@drwpow drwpow merged commit 927e526 into openapi-ts:main Mar 8, 2021
@drwpow
Copy link
Contributor

drwpow commented Mar 8, 2021

@all-contributors please add @yamacent for code, bug, test

@allcontributors
Copy link
Contributor

@drwpow

I've put up a pull request to add @yamacent! 🎉

@yamacent yamacent deleted the fix-v2-parameter-types branch March 8, 2021 06:10
@yamacent
Copy link
Contributor Author

yamacent commented Mar 8, 2021

@drwpow Once again, thank you for your kind review!

@drwpow
Copy link
Contributor

drwpow commented Mar 9, 2021

This was just released in 3.1.0! 🚀 Thank you again for your contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

openapi 2: parameters with known type parsed to unknown
2 participants