I am using the SwaggerToTypeScriptClient to generate a Javascript/TypeScript client SDK that should be framework and platform agnostic. As others mentioned (#512 + #643 and others), I'm struggling with the problem of being able to inject an authorization bearer token in the header, from the consuming perspective.
I know the formal response is "add a header in transformOptions", but I can't see this working with my solution. For example, I am able to generate a BaseClass which neatly acts as a super class for all api clients:
export class ApiClientBase {
protected transformOptions(options: RequestInit): Promise<RequestInit> {
options.headers = { ...options.headers, authorization: ' bearer ' + '???' };
return Promise.resolve(options);
}
protected transformResult(url: string, response: Response, processor: (response: Response) => any) {
return processor(response);
}
}
As you can see in the above code, the '???' is the problematic part leading to the question:
How can I inject this from my client?
Considering I have a (vanilla) client, I cannot resolve to:
Just for the sake of completeness, here is something I'm trying to achieve from a consumer perspective:
test.only('do a call, requiring authentication', async () => {
const token = 'abc123';
const api = new TimeApiClient('http://localhost:5000');
const target = await api.time();
// ^ fails, because I can't 'inject' the token anywhere nor can I access the ApiClientBase
});
To summarize, what I think I'm looing for is either :
TimeApiClient or to the time() operation on it. time() operation, but I'm not quite seeing how I could do this.Is there a way to do this?
Thanks.
Also, please be aware that it's properly outputted in the swagger.json file:
"securityDefinitions": {
"Bearer": {
"name": "Authorization",
"in": "header",
"type": "apiKey",
"description": ""
}
Other tools like Swagger UI and swagger-codegen respect it, so I'm also wondering if this might be a third option?
For example, swagger-codegen allows me to inject a config (also autogenerated) like this:
test.only('do a call, requiring authentication', async () => {
const config: Configuration = {
accessToken: 'ABC123',
basePath: 'http://localhost:5000'
};
const api = new TimeApi(config);
const target = await api.timeGet();
});
I think with the ConfigurationClass setting you can define a class which gets injected and can be used in the base class? Or is this c# only?
Mybe this impl can help you: https://github.com/Picturepark/Picturepark.SDK.TypeScript/tree/master/src/picturepark-sdk-v1-fetch
This... is awesome. Wasn't aware of the ConfigurationClass being available, but indeed by simply setting:
"configurationClass": "MyConfig",
"extensionCode": "src/ApiClientBase.ts",
and adding the MyConfig class to the ApiClientBase.ts this allows it to be injectable in the constructor (and base class). The Picturepark sample helped.
@RSuter thanks a bunch, really!
It would be awesome if you could improve the wiki so that all this is more discoverable...
@RicoSuter Thanks for the hints, I added a section detailing your suggestion!
https://github.com/RicoSuter/NSwag/wiki/TypeScriptClientGenerator#inject-an-authorization-header
The only -- small -- remaining problem is that the provided file gets appended to the end of the generated file, thus I get the following error
Class 'AuthorizedApiBase' used before its declaration.ts(2449)
api.generated.clients.ts(10765, 7): 'AuthorizedApiBase' is declared here.
It seems extension code may not be the correct way to do it?
Is there an alternative?
@RicoSuter Thanks for the hints, I added a section detailing your suggestion!
https://github.com/RicoSuter/NSwag/wiki/TypeScriptClientGenerator#inject-an-authorization-headerThe only -- small -- remaining problem is that the provided file gets appended to the end of the generated file, thus I get the following error
Class 'AuthorizedApiBase' used before its declaration.ts(2449) api.generated.clients.ts(10765, 7): 'AuthorizedApiBase' is declared here.It seems extension code may not be the correct way to do it?
Is there an alternative?
It's a problem with the comments as seen here https://github.com/RicoSuter/NJsonSchema/issues/779
Just remove the comments and you are good to go :)
worked like a charm!
you can also rewrite the comment to remove the word "class", e.g. use "clazz" or "c l a s s"
thanks again!
Most helpful comment
It would be awesome if you could improve the wiki so that all this is more discoverable...