Skip to content

Commit 766ad64

Browse files
committed
chore: generate typed baseUrl option
1 parent ccc7ae4 commit 766ad64

File tree

347 files changed

+3062
-424
lines changed

Some content is hidden

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

347 files changed

+3062
-424
lines changed

packages/openapi-ts/src/compiler/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const compiler = {
5858
safeAccessExpression: transform.createSafeAccessExpression,
5959
stringLiteral: types.createStringLiteral,
6060
stringToTsNodes: utils.stringToTsNodes,
61+
templateLiteralType: types.createTemplateLiteralType,
6162
transformArrayMap: transform.createArrayMapTransform,
6263
transformArrayMutation: transform.createArrayTransformMutation,
6364
transformDateMutation: transform.createDateTransformMutation,

packages/openapi-ts/src/compiler/types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,3 +1012,31 @@ export const createAsExpression = ({
10121012
expression: ts.Expression;
10131013
type: ts.TypeNode;
10141014
}) => ts.factory.createAsExpression(expression, type);
1015+
1016+
export const createTemplateLiteralType = ({
1017+
value,
1018+
}: {
1019+
value: ReadonlyArray<string | ts.TypeNode>;
1020+
}) => {
1021+
const spans: Array<ts.TemplateLiteralTypeSpan> = [];
1022+
let spanText = '';
1023+
1024+
for (const item of value.slice(0).reverse()) {
1025+
if (typeof item === 'string') {
1026+
spanText = `${item}${spanText}`;
1027+
} else {
1028+
const literal = spans.length
1029+
? ts.factory.createTemplateMiddle(spanText)
1030+
: ts.factory.createTemplateTail(spanText);
1031+
const span = ts.factory.createTemplateLiteralTypeSpan(item, literal);
1032+
spans.push(span);
1033+
spanText = '';
1034+
}
1035+
}
1036+
1037+
const templateLiteralType = ts.factory.createTemplateLiteralType(
1038+
ts.factory.createTemplateHead(spanText),
1039+
spans.reverse(),
1040+
);
1041+
return templateLiteralType;
1042+
};

packages/openapi-ts/src/ir/context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ interface Events {
5656
name: string;
5757
schema: IR.SchemaObject;
5858
}) => void;
59+
server: (args: { server: IR.ServerObject }) => void;
5960
}
6061

6162
type Listeners = {

packages/openapi-ts/src/ir/parser.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import type { IR } from './types';
77
export const parseIR = async ({ context }: { context: IR.Context }) => {
88
await context.broadcast('before');
99

10+
for (const server of context.ir.servers ?? []) {
11+
await context.broadcast('server', { server });
12+
}
13+
1014
if (context.ir.components) {
1115
for (const name in context.ir.components.schemas) {
1216
const schema = context.ir.components.schemas[name]!;
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import type { IR } from '../../../../ir/types';
4+
import type { OpenApi } from '../../../types';
5+
import { parseServers } from '../server';
6+
7+
describe('parseServers', () => {
8+
it('host + basePath + schemes', () => {
9+
const context: Partial<IR.Context<Partial<OpenApi.V2_0_X>>> = {
10+
// @ts-expect-error
11+
config: {
12+
input: {
13+
path: '',
14+
},
15+
},
16+
ir: {},
17+
spec: {
18+
basePath: '/v1',
19+
host: 'foo.com',
20+
schemes: ['http', 'https'],
21+
},
22+
};
23+
parseServers({ context: context as IR.Context });
24+
expect(context.ir!.servers).toEqual([
25+
{
26+
url: 'http://foo.com/v1',
27+
},
28+
{
29+
url: 'https://foo.com/v1',
30+
},
31+
]);
32+
});
33+
34+
it('schemes + host', () => {
35+
const context: Partial<IR.Context<Partial<OpenApi.V2_0_X>>> = {
36+
// @ts-expect-error
37+
config: {
38+
input: {
39+
path: '',
40+
},
41+
},
42+
ir: {},
43+
spec: {
44+
host: 'foo.com',
45+
schemes: ['ws'],
46+
},
47+
};
48+
parseServers({ context: context as IR.Context });
49+
expect(context.ir!.servers).toEqual([
50+
{
51+
url: 'ws://foo.com',
52+
},
53+
]);
54+
});
55+
56+
it('host + basePath', () => {
57+
const context: Partial<IR.Context<Partial<OpenApi.V2_0_X>>> = {
58+
// @ts-expect-error
59+
config: {
60+
input: {
61+
path: '',
62+
},
63+
},
64+
ir: {},
65+
spec: {
66+
basePath: '/v1',
67+
host: 'foo.com',
68+
},
69+
};
70+
parseServers({ context: context as IR.Context });
71+
expect(context.ir!.servers).toEqual([
72+
{
73+
url: 'foo.com/v1',
74+
},
75+
]);
76+
});
77+
78+
it('host', () => {
79+
const context: Partial<IR.Context<Partial<OpenApi.V2_0_X>>> = {
80+
// @ts-expect-error
81+
config: {
82+
input: {
83+
path: '',
84+
},
85+
},
86+
ir: {},
87+
spec: {
88+
host: 'foo.com',
89+
},
90+
};
91+
parseServers({ context: context as IR.Context });
92+
expect(context.ir!.servers).toEqual([
93+
{
94+
url: 'foo.com',
95+
},
96+
]);
97+
});
98+
99+
it('basePath', () => {
100+
const context: Partial<IR.Context<Partial<OpenApi.V2_0_X>>> = {
101+
// @ts-expect-error
102+
config: {
103+
input: {
104+
path: '',
105+
},
106+
},
107+
ir: {},
108+
spec: {
109+
basePath: '/v1',
110+
},
111+
};
112+
parseServers({ context: context as IR.Context });
113+
expect(context.ir!.servers).toEqual([
114+
{
115+
url: '/v1',
116+
},
117+
]);
118+
});
119+
});

packages/openapi-ts/src/openApi/2.0.x/parser/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
import { parseOperation } from './operation';
1212
import { parametersArrayToObject } from './parameter';
1313
import { parseSchema } from './schema';
14+
import { parseServers } from './server';
1415

1516
type PathKeys<T extends keyof PathsObject = keyof PathsObject> =
1617
keyof T extends infer K ? (K extends `/${string}` ? K : never) : never;
@@ -55,6 +56,8 @@ export const parseV2_0_X = (context: IR.Context<OpenApiV2_0_X>) => {
5556
}
5657
}
5758

59+
parseServers({ context });
60+
5861
for (const path in context.spec.paths) {
5962
if (path.startsWith('x-')) {
6063
continue;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { IR } from '../../../ir/types';
2+
import { parseUrl } from '../../../utils/url';
3+
4+
export const parseServers = ({ context }: { context: IR.Context }) => {
5+
let schemes: ReadonlyArray<string> = context.spec.schemes ?? [];
6+
let host = context.spec.host ?? '';
7+
const path = context.spec.basePath ?? '';
8+
9+
if (typeof context.config.input.path === 'string') {
10+
const url = parseUrl(context.config.input.path);
11+
12+
if (!schemes.length) {
13+
if (url.protocol) {
14+
schemes = [url.protocol] as typeof schemes;
15+
}
16+
}
17+
18+
if (!host) {
19+
host = `${url.host}${url.port ? `:${url.port}` : ''}`;
20+
}
21+
}
22+
23+
if (!schemes.length) {
24+
schemes = [''];
25+
}
26+
27+
const servers = schemes
28+
.map((scheme) => `${scheme ? `${scheme}://` : ''}${host}${path}`)
29+
.filter(Boolean);
30+
31+
if (servers.length) {
32+
context.ir.servers = servers.map((url) => ({
33+
url,
34+
}));
35+
}
36+
};

packages/openapi-ts/src/openApi/3.0.x/parser/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export const parseV3_0_X = (context: IR.Context<OpenApiV3_0_X>) => {
9999
}
100100
}
101101

102+
if (context.spec.servers) {
103+
context.ir.servers = context.spec.servers;
104+
}
105+
102106
for (const path in context.spec.paths) {
103107
const pathItem = context.spec.paths[path as keyof PathsObject]!;
104108

packages/openapi-ts/src/openApi/3.0.x/parser/operation.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ export const parseOperation = ({
236236
context.ir.paths[path] = {};
237237
}
238238

239+
if (operation.servers) {
240+
context.ir.servers = [...(context.ir.servers ?? []), ...operation.servers];
241+
}
242+
239243
operation.id = operationToId({
240244
context,
241245
id: operation.operationId,

packages/openapi-ts/src/openApi/3.1.x/parser/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export const parseV3_1_X = (context: IR.Context<OpenApiV3_1_X>) => {
9999
}
100100
}
101101

102+
if (context.spec.servers) {
103+
context.ir.servers = context.spec.servers;
104+
}
105+
102106
for (const path in context.spec.paths) {
103107
const pathItem = context.spec.paths[path as keyof PathsObject]!;
104108

0 commit comments

Comments
 (0)