Skip to content

Commit 23fbe5c

Browse files
committed
feat: Add AWS Signiture Ability
- Add AWS Signature Ability - Remove Static Instance Generation - Remove remainder of Legacy HTTP Clients
1 parent bd5c060 commit 23fbe5c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+484
-255
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ $ openapi --help
4949
--exportSchemas <value> Write schemas to disk (default: false)
5050
--postfix <value> Service name postfix (default: "Service")
5151
--request <value> Path to custom request file
52-
--exportClient <value> Generate and write client class to disk (default: false)
5352
--name <value> Custom client class name (default: "AppClient")
5453
-h, --help display help for command
5554
@@ -344,15 +343,15 @@ interface ModelWithNullableString {
344343
}
345344
```
346345

347-
### Generate client instance with `--exportClient` option
346+
### Generate client instance
348347

349348
The OpenAPI generator allows to create client instances to support the multiple backend services use case.
350-
The generated client uses an instance of the server configuration and not the global `OpenAPI` constant.
349+
The generated client uses an instance of the server configuration.
351350

352-
To generate a client instance, use `--exportClient` option. To set a custom name to the client class, use `--name` option.
351+
To set a custom name to the client class, use `--name` option.
353352

354353
```
355-
openapi --input ./spec.json --output ./dist --exportClient true --name DemoAppClient
354+
openapi --input ./spec.json --output ./dist --name DemoAppClient
356355
```
357356

358357
The generated client will be exported from the `index` file and can be used as shown below:

bin/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const params = program
2020
.option('--exportModels <value>', 'Write models to disk', true)
2121
.option('--exportSchemas <value>', 'Write schemas to disk', false)
2222
.option('--postfix <value>', 'Service name postfix', 'Service')
23-
.option('--exportClient <value>', 'Generate and write client class to disk', false)
23+
.option('--awsSign <value>', 'Sign Requests with AWS V4 Signiture', false)
2424
.option('--request <value>', 'Path to custom request file')
2525
.option('--name <value>', 'Custom client class name', 'AppClient')
2626
.parse(process.argv)
@@ -40,8 +40,8 @@ if (OpenAPI) {
4040
exportModels: JSON.parse(params.exportModels) === true,
4141
exportSchemas: JSON.parse(params.exportSchemas) === true,
4242
postfix: params.postfix,
43-
exportClient: JSON.parse(params.exportClient) === true,
4443
clientName: params.name,
44+
awsSign: JSON.parse(params.awsSign) === true,
4545
request: params.request,
4646
})
4747
.then(() => {

package-lock.json

Lines changed: 348 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
"typescript",
2525
"yaml",
2626
"json",
27-
"fetch",
2827
"axios",
2928
"node"
3029
],
@@ -61,6 +60,8 @@
6160
"prepublishOnly": "npm run clean && npm run release"
6261
},
6362
"dependencies": {
63+
"@aws-crypto/sha256-js": "^4.0.0",
64+
"@aws-sdk/signature-v4": "^3.310.0",
6465
"abort-controller": "^3.0.0",
6566
"axios": "^0.27.2",
6667
"camelcase": "6.3.0",

src/HttpClient.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
export enum HttpClient {
2-
FETCH = 'fetch',
3-
XHR = 'xhr',
4-
NODE = 'node',
52
AXIOS = 'axios',
63
}

src/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ export type Options = {
2020
exportModels?: boolean;
2121
exportSchemas?: boolean;
2222
postfix?: string;
23-
exportClient?: boolean;
2423
request?: string;
2524
clientName?: string;
25+
awsSign?: boolean;
2626
write?: boolean;
2727
};
2828

@@ -32,32 +32,32 @@ export type Options = {
3232
* service layer, etc.
3333
* @param input The relative ___location of the OpenAPI spec
3434
* @param output The relative ___location of the output directory
35-
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
35+
* @param httpClient The selected httpClient (axios)
3636
* @param useOptions Use options or arguments functions
3737
* @param useUnionTypes Use union types instead of enums
3838
* @param exportCore: Generate core client classes
3939
* @param exportServices: Generate services
4040
* @param exportModels: Generate models
4141
* @param exportSchemas: Generate schemas
4242
* @param postfix: Service name postfix
43-
* @param exportClient: Generate client class
4443
* @param clientName: Custom client class name
44+
* @param awsSign: Sign Requests with AWS V4 Signiture
4545
* @param request: Path to custom request file
4646
* @param write Write the files to disk (true or false)
4747
*/
4848
export async function generate({
4949
input,
5050
output,
51-
httpClient = HttpClient.FETCH,
51+
httpClient = HttpClient.AXIOS,
5252
useOptions = false,
5353
useUnionTypes = false,
5454
exportCore = true,
5555
exportServices = true,
5656
exportModels = true,
5757
exportSchemas = false,
5858
postfix = 'Service',
59-
exportClient = false,
6059
clientName = 'AppClient',
60+
awsSign = false,
6161
request,
6262
write = true,
6363
}: Options): Promise<void> {
@@ -72,7 +72,7 @@ export async function generate({
7272
switch (openApiVersion) {
7373
case OpenApiVersion.V3: {
7474
const client = parseV3(openApi);
75-
const clientFinal = postProcessClient(client, exportClient);
75+
const clientFinal = postProcessClient(client);
7676
if (!write) break;
7777
await writeClient(
7878
clientFinal,
@@ -86,8 +86,8 @@ export async function generate({
8686
exportModels,
8787
exportSchemas,
8888
postfix,
89-
exportClient,
9089
clientName,
90+
awsSign,
9191
request
9292
);
9393
break;

src/templates/core/OpenAPI.hbs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,4 @@ export type OpenAPIConfig2 = {
1818
token?: string | Resolver<string>;
1919
accountSid?: string | Resolver<string>;
2020
authToken?: string | Resolver<string>;
21-
}
22-
23-
{{#unless @root.exportClient}}
24-
25-
export const OpenAPI: OpenAPIConfig = {
26-
base: '{{{server}}}',
27-
version: '{{{version}}}',
28-
edge: '{{#if server.edgeRegions}}{{server.edgeRegions.[0]}}{{else}}gll{{/if}}',
29-
token: undefined,
30-
accountSid: undefined,
31-
authToken: undefined
32-
};{{/unless}}
21+
}

src/templates/core/axios/getHeaders.hbs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
async function getHeaders(options: ApiRequestOptions, config: OpenAPIConfig2, formData?: FormData): Promise<Record<string, string>> {
1+
async function getHeaders(options: ApiRequestOptions, config: OpenAPIConfig2, url: URL): Promise<Record<string, string>> {
22
const token = await resolve(options, config.token);
33
const accountSid = await resolve(options, config.accountSid);
44
const authToken = await resolve(options, config.authToken);
55

66
const headers = Object.entries({
77
Accept: 'application/json',
8+
host: url.hostname,
89
...options.headers,
910
})
1011
.filter(([_, value]) => isDefined(value))

src/templates/core/axios/request.hbs

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ import type { ApiResult } from './ApiResult';
1010
import { CancelablePromise } from './CancelablePromise';
1111
import type { OnCancel } from './CancelablePromise';
1212
import type { OpenAPIConfig2 } from './OpenAPI';
13-
{{#if @root.exportClient}}
1413
import { BaseHttpRequest } from './BaseHttpRequest';
15-
{{else}}
16-
import { OpenAPI } from './OpenAPI';
14+
15+
{{#if @root.awsSign}}
16+
import { SignatureV4 } from '@aws-sdk/signature-v4';
17+
import { Sha256 } from '@aws-crypto/sha256-js';
18+
19+
{{>functions/signAWS}}
1720
{{/if}}
21+
22+
1823
{{>functions/isDefined}}
1924

2025

@@ -66,7 +71,6 @@ import { OpenAPI } from './OpenAPI';
6671
{{>functions/catchErrors}}
6772

6873

69-
{{#if @root.exportClient}}
7074
export class AxiosHttpRequest extends BaseHttpRequest {
7175
constructor(openApiConfig: OpenAPIConfig2) {
7276
super(openApiConfig);
@@ -84,15 +88,20 @@ export class AxiosHttpRequest extends BaseHttpRequest {
8488
const url = getUrl(options, this.openApiConfig);
8589
const formData = getFormData(options);
8690
const body = getRequestBody(options);
87-
const headers = await getHeaders(options, this.openApiConfig, formData);
91+
const headers = await getHeaders(options, this.openApiConfig, url);
92+
93+
{{#if @root.awsSign}}
94+
const signed = await signAWS({ url, options, headers, body: body ?? formData });
95+
console.log("It worked!", signed);
96+
{{/if}}
8897

8998
if (!onCancel.isCancelled) {
9099
const response = await sendRequest(options, url, formData, body, headers, onCancel, this.openApiConfig);
91100
const responseBody = getResponseBody(response);
92101
const responseHeader = getResponseHeader(response, options.responseHeader);
93102

94103
const result: ApiResult = {
95-
url,
104+
url: url.toString(),
96105
ok: isSuccess(response.status),
97106
status: response.status,
98107
statusText: response.statusText,
@@ -109,41 +118,3 @@ export class AxiosHttpRequest extends BaseHttpRequest {
109118
});
110119
}
111120
}
112-
{{else}}
113-
/**
114-
* Request using axios client
115-
* @param options The request options from the the service
116-
* @returns CancelablePromise<T>
117-
* @throws ApiError
118-
*/
119-
export function request<T>(options: ApiRequestOptions): CancelablePromise<T> {
120-
return new CancelablePromise(async (resolve, reject, onCancel) => {
121-
try {
122-
const url = getUrl(options, OpenAPI);
123-
const formData = getFormData(options);
124-
const body = getRequestBody(options);
125-
const headers = await getHeaders(options, OpenAPI, formData);
126-
127-
if (!onCancel.isCancelled) {
128-
const response = await sendRequest(options, url, formData, body, headers, onCancel, OpenAPI);
129-
const responseBody = getResponseBody(response);
130-
const responseHeader = getResponseHeader(response, options.responseHeader);
131-
132-
const result: ApiResult = {
133-
url,
134-
ok: isSuccess(response.status),
135-
status: response.status,
136-
statusText: response.statusText,
137-
body: responseHeader || responseBody,
138-
};
139-
140-
catchErrors(options, result);
141-
142-
resolve(result.body);
143-
}
144-
} catch (error) {
145-
reject(error);
146-
}
147-
});
148-
}
149-
{{/if}}

src/templates/core/axios/sendRequest.hbs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
const sendRequest = async <T>(
22
options: ApiRequestOptions,
3-
url: string,
3+
url: URL,
44
formData: FormData | undefined,
55
body: any,
66
headers: Record<string, string>,
77
onCancel: OnCancel,
88
openApiConfig: OpenAPIConfig2
99
): Promise<AxiosResponse<T>> => {
1010
const source = axios.CancelToken.source();
11-
const newUrl = openApiConfig.edge ? url.replace("{edge}", openApiConfig.edge) : url;
1211

1312
const requestConfig: AxiosRequestConfig = {
14-
url: newUrl,
13+
url: url.toString(),
1514
headers,
1615
data: body ?? formData,
1716
method: options.method,

0 commit comments

Comments
 (0)