Skip to content
This repository was archived by the owner on May 28, 2024. It is now read-only.

Commit 301ffda

Browse files
Merge pull request #2 from krokettenkoal/feature/openapi-v3-servers
Add support for Path Item and Operation servers (v3)
2 parents 8611094 + 269b7db commit 301ffda

File tree

10 files changed

+364
-293
lines changed

10 files changed

+364
-293
lines changed

src/client/interfaces/Operation.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ export interface Operation extends OperationParameters {
1313
errors: OperationError[];
1414
results: OperationResponse[];
1515
responseHeader: string | null;
16+
server?: string;
1617
}

src/client/interfaces/Service.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export interface Service {
44
name: string;
55
operations: Operation[];
66
imports: string[];
7+
server?: string;
78
}

src/openApi/v3/parser/getOperation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { getOperationRequestBody } from './getOperationRequestBody';
1010
import { getOperationResponseHeader } from './getOperationResponseHeader';
1111
import { getOperationResponses } from './getOperationResponses';
1212
import { getOperationResults } from './getOperationResults';
13+
import { getOperationServer } from './getServer';
1314
import { getRef } from './getRef';
1415
import { getServiceName } from './getServiceName';
1516
import { sortByRequired } from './sortByRequired';
@@ -24,6 +25,7 @@ export const getOperation = (
2425
): Operation => {
2526
const serviceName = getServiceName(tag);
2627
const operationName = getOperationName(url, method, op.operationId);
28+
const server = getOperationServer(op);
2729

2830
// Create a new operation object for this method.
2931
const operation: Operation = {
@@ -34,6 +36,7 @@ export const getOperation = (
3436
deprecated: op.deprecated === true,
3537
method: method.toUpperCase(),
3638
path: url,
39+
server: server,
3740
parameters: [...pathParams.parameters],
3841
parametersPath: [...pathParams.parametersPath],
3942
parametersQuery: [...pathParams.parametersQuery],

src/openApi/v3/parser/getServer.spec.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getServer } from './getServer';
1+
import { getOperationServer, getPathItemServer, getServer } from "./getServer";
22

33
describe('getServer', () => {
44
it('should produce correct result', () => {
@@ -44,4 +44,51 @@ describe('getServer', () => {
4444
})
4545
).toEqual('https://localhost:8080/api');
4646
});
47+
48+
it('should produce correct result with Path Item servers', () => {
49+
expect(
50+
getPathItemServer({
51+
servers: [
52+
{
53+
url: 'https://sub.localhost:8080/api',
54+
},
55+
],
56+
})
57+
).toEqual('https://sub.localhost:8080/api');
58+
});
59+
60+
it('should produce undefined with no Path Item servers', () => {
61+
expect(
62+
getPathItemServer({})
63+
).toEqual(undefined);
64+
});
65+
66+
it('should produce correct result with Operation servers', () => {
67+
expect(
68+
getOperationServer({
69+
servers: [
70+
{
71+
url: 'https://sub.localhost:8080/api',
72+
},
73+
],
74+
responses: {
75+
default: {
76+
description: 'dummy',
77+
}
78+
},
79+
})
80+
).toEqual('https://sub.localhost:8080/api');
81+
});
82+
83+
it('should produce undefined with no Operation servers', () => {
84+
expect(
85+
getOperationServer({
86+
responses: {
87+
default: {
88+
description: 'dummy',
89+
}
90+
},
91+
})
92+
).toEqual(undefined);
93+
});
4794
});

src/openApi/v3/parser/getServer.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
import type { OpenApi } from '../interfaces/OpenApi';
2+
import type { OpenApiServer } from '../interfaces/OpenApiServer';
3+
import type { OpenApiPath } from '../interfaces/OpenApiPath';
4+
import type { OpenApiOperation } from '../interfaces/OpenApiOperation';
25

3-
export const getServer = (openApi: OpenApi): string => {
4-
const server = openApi.servers?.[0];
5-
const variables = server?.variables || {};
6-
let url = server?.url || '';
6+
export const getServerUrl = (server?: OpenApiServer): string | undefined => {
7+
if (!server) return undefined;
8+
9+
const variables = server.variables || {};
10+
let url = server.url || '';
711
for (const variable in variables) {
812
if (variables.hasOwnProperty(variable)) {
913
url = url.replace(`{${variable}}`, variables[variable].default);
1014
}
1115
}
1216
return url.replace(/\/$/g, '');
1317
};
18+
19+
export const getServer = (openApi: OpenApi): string => getServerUrl(openApi.servers?.[0]) ?? '';
20+
export const getPathItemServer = (pathItem: OpenApiPath): string | undefined => getServerUrl(pathItem.servers?.[0]);
21+
export const getOperationServer = (operation: OpenApiOperation): string | undefined =>
22+
getServerUrl(operation.servers?.[0]);

src/openApi/v3/parser/getServices.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { unique } from '../../../utils/unique';
33
import type { OpenApi } from '../interfaces/OpenApi';
44
import { getOperation } from './getOperation';
55
import { getOperationParameters } from './getOperationParameters';
6+
import { getPathItemServer } from './getServer';
67

78
/**
89
* Get the OpenAPI services
@@ -43,6 +44,7 @@ export const getServices = (openApi: OpenApi): Service[] => {
4344
// Push the operation in the service
4445
service.operations.push(operation);
4546
service.imports.push(...operation.imports);
47+
service.server ??= getPathItemServer(path);
4648
services.set(operation.service, service);
4749
});
4850
break;

src/templates/core/ApiRequestOptions.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export type ApiRequestOptions = {
44
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
55
readonly url: string;
6+
readonly server?: string;
67
readonly path?: Record<string, any>;
78
readonly cookies?: Record<string, any>;
89
readonly headers?: Record<string, any>;

src/templates/core/functions/getUrl.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
1010
return substring;
1111
});
1212

13-
const url = `${config.BASE}${path}`;
13+
const url = `${options.server || config.BASE}${path}`;
1414
if (options.query) {
1515
return `${url}${getQueryString(options.query)}`;
1616
}

src/templates/exportService.hbs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ export class {{{name}}}{{{@root.postfix}}} {
8989
{{/if}}
9090
method: '{{{method}}}',
9191
url: '{{{path}}}',
92+
{{#if server}}
93+
server: '{{{server}}}',
94+
{{else if ../server}}
95+
server: '{{{../server}}}',
96+
{{/if}}
9297
{{#if parametersPath}}
9398
path: {
9499
{{#each parametersPath}}

0 commit comments

Comments
 (0)