-
Notifications
You must be signed in to change notification settings - Fork 43
fix: sdk exploded syntax - take into account request plugin options #3076
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
Conversation
View your CI Pipeline Execution ↗ for commit f00d17a.
☁️ Nx Cloud last updated this comment at |
Codecov ReportAttention: Patch coverage is
✅ All tests successful. No failed tests found. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
...pescript/core/openapi-codegen-typescript/src/main/resources/typescriptFetch/api/api.mustache
Outdated
Show resolved
Hide resolved
335df01
to
c3f2dee
Compare
c3f2dee
to
3fcbd65
Compare
return serializedParamValue.split('&').reduce((obj: { [key: string]: PrimitiveType }, currentValue) => { | ||
const [key, value] = currentValue.split('='); | ||
// NOTE: The key of an object in deepObject style is surrounded by opening and closing square brackets | ||
obj[paramSerialization.style === 'deepObject' ? key.split(OPENING_SQUARE_BRACKET_URL_CODE)[1].split(CLOSING_SQUARE_BRACKET_URL_CODE)[0] : key] = value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably consider also if the character is not encoded or at least document it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
obj[paramSerialization.style === 'deepObject' ? key.split(OPENING_SQUARE_BRACKET_URL_CODE)[1].split(CLOSING_SQUARE_BRACKET_URL_CODE)[0] : key] = value; | |
obj[paramSerialization.style === 'deepObject' ? key.match(`^${OPENING_SQUARE_BRACKET_URL_CODE})([^${CLOSING_SQUARE_BRACKET_URL_CODE}]+)`)[1]` : key] = value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the OpenAPI documentation, special characters should be encoded since this is required by RFC6570 and RFC3986, but I can document this yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document it just in case
} | ||
return obj; | ||
}, {} as { [key: string]: PrimitiveType }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should log something if the combination exploded/style is not supported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I previously added logs but we had decided these would saturate the flow, but we can rediscuss this if you find it beneficial
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussion, we decided to add these logs in another PR if necessary
return splitObject.reduce((obj: { [key: string]: PrimitiveType }, currentValue, index, array) => { | ||
if (index % 2 === 0) { | ||
obj[currentValue] = array[index + 1]; | ||
} | ||
return obj; | ||
}, {} as { [key: string]: PrimitiveType }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is used several times we could extract the code in a dedicated function
export function objectFromPairwiseArray<T>(inputArray: T[]): Record<string, T> {
return inputArray.reduce((obj: { [key: string]: T}, currentValue, index, array) => {
if (index % 2 === 0) {
obj[currentValue] = array[index + 1];
}
return obj;
}, []);
}
return splitObject.reduce((obj: { [key: string]: PrimitiveType }, currentValue, index, array) => { | |
if (index % 2 === 0) { | |
obj[currentValue] = array[index + 1]; | |
} | |
return obj; | |
}, {} as { [key: string]: PrimitiveType }); | |
return objectFromPairwiseArray(splitObject); |
or something like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is used only twice (deserialization of object query and path parameters), I am not sure if it is worth creating another function in the code but if it makes it easier to read/understand then yes I can make the update
export function deserializeObjectPathParams(serializedParamValue: string, paramSerialization: ParamSerialization) { | ||
const splitObject: string[] = paramSerialization.style === 'matrix' && paramSerialization.explode | ||
? serializedParamValue.substring(1).split(';') | ||
: deserializeArrayPathParams(serializedParamValue, paramSerialization)!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you use the ArrayPathParams method to deserialize an object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if this is a similar logic, it seems confusing when reading the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the delimiter of the serialized object parameter is the same as the delimiter of array parameters:
https://swagger.io/specification/#style-examples
I did this to avoid code duplicates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cpaulve-1A I added a comment to explain, hoping this makes it a bit clearer, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename the method to avoid confusion or duplicate code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could rename it something like splitParameterElements
return obj; | ||
}, {} as { [key: string]: PrimitiveType }); | ||
} | ||
return splitObject.reduce((obj: { [key: string]: PrimitiveType }, currentValue, index, array) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have a comment here to explain the logic between the alternative key/value pairs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the comment below, I added the link to the OpenAPI documentation in the function description but I can add description comments if this is not enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
myParam.matchAll(`${outerDelimiter}?[^${innerDelimiter}]+${innerDelimiter}[^${outerDelimiter}]+${outerDelimiter}?`)
.reduce(obj, serializedProperty => {
const splitProperty = serializedProperty.match('^${outerDelimiter}?([^${innerDelimiter}]+)${innerDelimiter}([^${outerDelimiter}]+)${outerDelimiter}?
});
obj[splitProperty[1]] = splitProperty[2];
But I am not sure it is clearer (it works for all the use case I think if you remove the prefix)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cpaulve-1A let me know if the added comments make it a bit easier to understand the logic
f0bc897
to
baa7fc6
Compare
After reflection, we have decided to implement the deserialization of the parameters in a separate PR since these functions are beneficial but non-essential. This will allow further time for discussions on the implementation. UPDATE: The separate has been created: #3116 |
packages/@ama-sdk/core/src/plugins/json-token/json-token.spec.ts
Outdated
Show resolved
Hide resolved
did not realize the breaking for our current user
a2b6879
to
55ee0e2
Compare
...cript/core/openapi-codegen-typescript/src/main/java/com/amadeus/codegen/ts/LambdaHelper.java
Show resolved
Hide resolved
data.queryParams = { ...data.queryParams, ...queryParams }; | ||
if (data.paramSerializationOptions?.enableParameterSerialization && !isParamValueRecord(queryParams)) { | ||
data.queryParams = { ...data.queryParams, ...serializeRequestPluginQueryParams(queryParams) }; | ||
} else if (isParamValueRecord(queryParams)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we log/throw an error in case both data.paramSerializationOptions?.enableParameterSerialization
and isParamValueRecord(queryParams)
are false?
I assume here the params are silently ignored
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could throw an error yes if you find this helpful, I was not sure when to add error logs or not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
55ee0e2
to
aea43f6
Compare
@@ -100,33 +98,65 @@ export class {{classname}} implements Api { | |||
body = data['{{baseName}}'] as any; | |||
} | |||
{{/bodyParam}} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To facilitate the review of this file, I will explain my logic here (small tip: the file is easier to read in unified mode):
- All of the query / path parameter logic is grouped together since these params are not needed for the headers or body
queryParams
will always be created and initialized as an empty object{}
paramSerializationOptions
will always be created with the value ofthis.client.options.enableParameterSerialization
since this is passed to the request options- If there are path parameters, we will create the
if
statement to allow path parameter serialization- Within this
if
statement, we check if there are query params as well to add their serialization logic if needed
- Within this
- If there are no path parameters, the variables
basePath
andtokenizedUrl
are initialized as they were before- We check if there are query parameters to add the same logic as before (an
if
statement with the serialization logic)
- We check if there are query parameters to add the same logic as before (an
94045af
to
5a3d24b
Compare
packages/@ama-sdk/core/src/plugins/additional-params/additional-params.spec.ts
Outdated
Show resolved
Hide resolved
make serialization optional
5a3d24b
to
f00d17a
Compare
Proposed change
When we previously implemented the exploded syntax for SDK parameter serialization, we removed the possibility of taking into account the query parameters that can be updated in the Request Plugins - which needs to be fixed. Here is a possible fix, which prepares the URL using the request plugins options (which could update the query parameters).
Also, the parameter
queryParamSerialization
has been added toRequestOptionsParameters
, which can be used in order to serialize the query parameter modifications that are potentially made. In another PR, I will add a method allowing to deserialize the parameters, which facilitates the modifications in the Request Plugins.Related issues
- No issue associated -