Skip to content
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

[AB-290]-Extracting-type-information from OAS #834

Merged
merged 19 commits into from
Jan 9, 2025

Conversation

AyushShri
Copy link
Collaborator

@AyushShri AyushShri commented Nov 28, 2024

The changes aims to extract type information along with collection generation from OAS

Sample Type Information Structure

"extractedTypes": { "get/pets": { "request": { "headers": "[]", "pathParam": "[]", "queryParam": "[\n {\n \"keyName\": \"limit1\",\n \"properties\": {\n \"type\": \"integer\",\n \"default\": \"<integer>\",\n \"required\": false,\n \"deprecated\": false\n }\n }\n]" }, "response": { "default": { "body": "{\n \"type\": \"object\",\n \"properties\": {\n \"code\": {\n \"type\": \"integer\",\n \"deprecated\": false\n },\n \"message\": {\n \"type\": \"string\",\n \"deprecated\": false\n }\n },\n \"required\": [\n \"code\",\n \"message\"\n ]\n}", "headers": "[]" } } } }

@jatin3893 jatin3893 added the specification-collection-sync API Builder Initiative label Dec 4, 2024
@AyushShri AyushShri changed the title AB-290-WIP-extracting-type-information [AB-290]-Extracting-type-information from OAS Dec 24, 2024
@AyushShri AyushShri requested a review from barshan23 December 24, 2024 06:04
libV2/index.js Outdated Show resolved Hide resolved
lib/schemapack.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/index.js Outdated
@@ -91,16 +92,19 @@ module.exports = {
// generate the request form the node
let request = {},
collectionVariables = [],
requestObject = {};
requestObject = {},
extractedTypesObject = {};
Copy link
Collaborator

Choose a reason for hiding this comment

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

P2: Can we name the variable typesObject instead of extracted types object ?

if (requiredProperties.has(key) || parentRequired.has(key)) {
schemaDetails.required.push(key);
}
if (prop.$ref) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where are we dereferencing this ? I can see we're calling processSchema again in this case, but this function doesn't seems to handle ref anywhere else. Am I missing something here ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

my bad, this is not required as the $ref would be already resolved by resolvedSchema.

libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
};
}
propertyDetails = { keyName, properties };
if (keyName && param.schema && param.schema.type) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Combine this if check with the above one.

libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
@AyushShri AyushShri requested a review from barshan23 January 7, 2025 08:17
minLength: prop.minLength !== undefined ? prop.minLength : undefined,
maxLength: prop.maxLength !== undefined ? prop.maxLength : undefined,
minimum: prop.minimum !== undefined ? prop.minimum : undefined,
maximum: prop.maximum !== undefined ? prop.maximum : undefined,
pattern: prop.pattern || undefined,
example: prop.example || undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should also check for undefined since example can also be false or 0 or some other falsy value

libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Show resolved Hide resolved
libV2/schemaUtils.js Outdated Show resolved Hide resolved
libV2/schemaUtils.js Show resolved Hide resolved
resolvedResponseBodyResult = resolveBodyData(
context, responseContent[bodyType], bodyType, true, code, requestBodyExamples);
allBodyData = resolvedResponseBodyResult.generatedBody;
resolvedResponseBodyTypes = resolvedResponseBodyResult ?
Copy link
Collaborator

Choose a reason for hiding this comment

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

This check is not needed

requestIdentifier,
requestBlock,
typesObject = {};
if (requestBody && requestBody.resolvedSchemaTypeObject) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not needed

{ pathVariables, collectionVariables } = filterCollectionAndPathVariables(url, pathParams),
requestBody = resolveRequestBodyForPostmanRequest(context, operationItem[method]),
bodyTypes = requestBody && requestBody.resolvedSchemaTypeObject,
Copy link
Collaborator

Choose a reason for hiding this comment

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

bodyTypes -> requestBodyTypes

} = resolveResponseForPostmanRequest(context, operationItem[method], request);

requestIdentifier = method + path;
requestBlock = { request: unifiedRequestTypes, response: unifiedResponseTypes };
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not needed, we can add this directly rather than using another variable

{ alwaysInheritAuthentication } = context.computedOptions,
requestIdentifier,
requestBlock,
typesObject = {};
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can be called requestTypesObject

@@ -2396,7 +2645,22 @@ module.exports = {
auth: alwaysInheritAuthentication ? undefined : authHelper
};

const { responses, acceptHeader } = resolveResponseForPostmanRequest(context, operationItem[method], request);
const unifiedRequestTypes = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

requestTypes

* Processes and resolves types from Nested JSON schema structure.
*
* @param {Object} resolvedSchema - The resolved JSON schema to process.
* @param {Set<string>} [parentRequired=new Set()] - A set of parent-required property keys to inherit.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be removed

processSchema = (resolvedSchema) => {
if (resolvedSchema.type === 'object' && resolvedSchema.properties) {
const schemaDetails = {
type: resolvedSchema.type || 'unknown',
Copy link
Collaborator

Choose a reason for hiding this comment

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

The unknown needs to be removed

}
else if (resolvedSchema.type === 'array' && resolvedSchema.items) {
const arrayDetails = {
type: resolvedSchema.type || 'unknown',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove the unknown from here

schemaDetails.required.push(key);
}
if (prop.properties) {
let res = processSchema(prop);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use descriptive variable names

return arrayDetails;
}
return {
type: resolvedSchema.type || 'unknown'
Copy link
Collaborator

Choose a reason for hiding this comment

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

unknown needs to be removed

@@ -1630,13 +1727,23 @@ let QUERYPARAM = 'query',
mode: 'formdata',
formdata: formDataParams
},
resolvedBody;
resolvedBody,
result,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use more descriptive name

resolvedBody = resolveBodyData(context, requestBodyContent.schema)[0];
result = resolveBodyData(context, requestBodyContent.schema);
resolvedBody =
result && Array.isArray(result.generatedBody) && result.generatedBody.length > 0 ?
Copy link
Collaborator

Choose a reason for hiding this comment

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

These condition checks needs to be simplified, refer the above comment

libV2/schemaUtils.js Outdated Show resolved Hide resolved
minLength: schema.minLength !== undefined ? schema.minLength : undefined,
maxLength: schema.maxLength !== undefined ? schema.maxLength : undefined,
minimum: schema.minimum !== undefined ? schema.minimum : undefined,
maximum: schema.maximum !== undefined ? schema.maximum : undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

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

These checks are unnecessary and can be removed


if (headerData && headerData.name && headerData.schema && headerData.schema.type) {
const { name, schema } = headerData;
keyName = name;
Copy link
Collaborator

Choose a reason for hiding this comment

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

keyName variable is not needed

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's remove this please ^

@AyushShri AyushShri requested a review from barshan23 January 7, 2025 16:20
resolvedBody =

resolvedBodyResult && Array.isArray(resolvedBodyResult.generatedBody) &&
resolvedBodyResult.generatedBody[0] ?
Copy link
Collaborator

Choose a reason for hiding this comment

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

This check needs to be simplified 😞

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was simplified based on your comment

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant we don't need the ternary operator here 🤦

undefined;

resolvedSchemaTypeObject = resolvedBodyResult &&
resolvedBodyResult.resolvedSchemaType ? resolvedBodyResult.resolvedSchemaType : undefined;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above

resolvedBody = resolveBodyData(context, requestBodyContent.schema)[0];
resolvedBodyResult = resolveBodyData(context, requestBodyContent.schema);
resolvedBody =
resolvedBodyResult && Array.isArray(resolvedBodyResult.generatedBody) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above comment, please take care of these in all the places where you have added such checks

Comment on lines 1876 to 1887
resolvedBodyResult = resolveBodyData(context, requestContent[bodyType], bodyType);
resolvedBody =
resolvedBodyResult && Array.isArray(resolvedBodyResult.generatedBody) &&
resolvedBodyResult.generatedBody[0] ?
resolvedBodyResult.generatedBody[0] :
undefined;

resolvedSchemaTypeObject =
resolvedBodyResult && resolvedBodyResult.resolvedSchemaType ?
resolvedBodyResult.resolvedSchemaType :
undefined;

Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above

},

resolvePathParamsForPostmanRequest = (context, operationItem, method) => {
const params = resolvePathItemParams(context, operationItem[method].parameters, operationItem.parameters),
pmParams = [];
let pathParamTypes = [];
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can be combined with the above const declaration

resolvedExamplesObject = resolvedExamples[0] && resolvedExamples[0].resolvedResponseBodyTypes;
responseBodyHeaderObj =
{
body: JSON.stringify(resolvedExamplesObject, null, 2),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Q: Do we really need to stringify here ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, we are not doing it again

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant what is the use of this stringify ? keeping it as JS object also works right ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, but i wanted to export the object in such a way that it can be used by collection0definition as it is. so stringified it. and changing it right now might be risky as all the tests would start to break.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's remove all these stringify calls since they aren't necessary when we're picking up the E2E test ticket.

Copy link
Collaborator

Choose a reason for hiding this comment

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

// Disabling max Length for better visibility of the expectedExtractedTypes

/* eslint-disable one-var */
// Disabling as we want the checks to run in order of their declaration
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't explain / mean anything when I'm reading this 😢

};


describe('convertV2WithTypes should generate collection confirming to collection schema', function() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

typo confirming -> conforming

);
});

it('should validate the schema' + testSpec1, function() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does validate the schema mean here ? The function being tested does not validate the schema right ? 🤔


const element = Object.values(conversionResult.extractedTypes)[0];
const { response } = element;
// Get the schema from the response
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment is unnecessary

@barshan23
Copy link
Collaborator

barshan23 commented Jan 8, 2025

@AyushShri Types are not being generated for responses when the response code is defined as default in OAS. Can you please look into this ?

Screen.Recording.2025-01-08.at.11.23.18.AM.mov

@AyushShri AyushShri merged commit 20aa037 into develop Jan 9, 2025
7 checks passed
@barshan23 barshan23 deleted the AB-289-feature/type-extraction branch January 9, 2025 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
specification-collection-sync API Builder Initiative
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants