Skip to content

Commit 50c44cc

Browse files
committed
- Support for JSON Schema type "as an array of primary types"
1 parent 931ee9c commit 50c44cc

File tree

11 files changed

+13772
-1646
lines changed

11 files changed

+13772
-1646
lines changed

src/client/interfaces/Type.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export interface Type {
33
base: string;
44
template: string | null;
55
imports: string[];
6+
isNullable: boolean;
67
}

src/openApi/v2/parser/getType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function getType(value?: string, template?: string): Type {
1717
base: 'any',
1818
template: null,
1919
imports: [],
20+
isNullable: false,
2021
};
2122

2223
const valueClean = stripNamespace(value || '');

src/openApi/v3/interfaces/OpenApiSchema.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface OpenApiSchema extends OpenApiReference, WithEnumExtension {
2525
minProperties?: number;
2626
required?: string[];
2727
enum?: (string | number)[];
28-
type?: string;
28+
type?: string | string[];
2929
allOf?: OpenApiSchema[];
3030
oneOf?: OpenApiSchema[];
3131
anyOf?: OpenApiSchema[];

src/openApi/v3/parser/getModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
180180
model.type = definitionType.type;
181181
model.base = definitionType.base;
182182
model.template = definitionType.template;
183+
model.isNullable = definitionType.isNullable;
183184
model.imports.push(...definitionType.imports);
184185
model.default = getModelDefault(definition, model);
185186
return model;

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ describe('getType', () => {
77
expect(type.base).toEqual('number');
88
expect(type.template).toEqual(null);
99
expect(type.imports).toEqual([]);
10+
expect(type.isNullable).toEqual(false);
1011
});
1112

1213
it('should convert string', () => {
@@ -15,6 +16,7 @@ describe('getType', () => {
1516
expect(type.base).toEqual('string');
1617
expect(type.template).toEqual(null);
1718
expect(type.imports).toEqual([]);
19+
expect(type.isNullable).toEqual(false);
1820
});
1921

2022
it('should convert string array', () => {
@@ -23,6 +25,7 @@ describe('getType', () => {
2325
expect(type.base).toEqual('string');
2426
expect(type.template).toEqual(null);
2527
expect(type.imports).toEqual([]);
28+
expect(type.isNullable).toEqual(false);
2629
});
2730

2831
it('should convert template with primary', () => {
@@ -31,6 +34,7 @@ describe('getType', () => {
3134
expect(type.base).toEqual('Link');
3235
expect(type.template).toEqual('string');
3336
expect(type.imports).toEqual(['Link']);
37+
expect(type.isNullable).toEqual(false);
3438
});
3539

3640
it('should convert template with model', () => {
@@ -39,6 +43,7 @@ describe('getType', () => {
3943
expect(type.base).toEqual('Link');
4044
expect(type.template).toEqual('Model');
4145
expect(type.imports).toEqual(['Link', 'Model']);
46+
expect(type.isNullable).toEqual(false);
4247
});
4348

4449
it('should have double imports', () => {
@@ -47,6 +52,7 @@ describe('getType', () => {
4752
expect(type.base).toEqual('Link');
4853
expect(type.template).toEqual('Link');
4954
expect(type.imports).toEqual(['Link', 'Link']);
55+
expect(type.isNullable).toEqual(false);
5056
});
5157

5258
it('should convert generic', () => {
@@ -55,6 +61,7 @@ describe('getType', () => {
5561
expect(type.base).toEqual('T');
5662
expect(type.template).toEqual(null);
5763
expect(type.imports).toEqual([]);
64+
expect(type.isNullable).toEqual(false);
5865
});
5966

6067
it('should support dot', () => {
@@ -63,6 +70,7 @@ describe('getType', () => {
6370
expect(type.base).toEqual('model_000');
6471
expect(type.template).toEqual(null);
6572
expect(type.imports).toEqual(['model_000']);
73+
expect(type.isNullable).toEqual(false);
6674
});
6775

6876
it('should support dashes', () => {
@@ -71,6 +79,7 @@ describe('getType', () => {
7179
expect(type.base).toEqual('some_special_schema');
7280
expect(type.template).toEqual(null);
7381
expect(type.imports).toEqual(['some_special_schema']);
82+
expect(type.isNullable).toEqual(false);
7483
});
7584

7685
it('should support dollar sign', () => {
@@ -79,5 +88,24 @@ describe('getType', () => {
7988
expect(type.base).toEqual('$some_special_schema');
8089
expect(type.template).toEqual(null);
8190
expect(type.imports).toEqual(['$some_special_schema']);
91+
expect(type.isNullable).toEqual(false);
92+
});
93+
94+
it('should support multiple base types', () => {
95+
const type = getType(['string', 'int']);
96+
expect(type.type).toEqual('string | number');
97+
expect(type.base).toEqual('string | number');
98+
expect(type.template).toEqual(null);
99+
expect(type.imports).toEqual([]);
100+
expect(type.isNullable).toEqual(false);
101+
});
102+
103+
it('should support multiple nullable types', () => {
104+
const type = getType(['string', 'null']);
105+
expect(type.type).toEqual('string');
106+
expect(type.base).toEqual('string');
107+
expect(type.template).toEqual(null);
108+
expect(type.imports).toEqual([]);
109+
expect(type.isNullable).toEqual(true);
82110
});
83111
});

src/openApi/v3/parser/getType.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,35 @@ import { stripNamespace } from './stripNamespace';
55
function encode(value: string): string {
66
return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_');
77
}
8-
98
/**
109
* Parse any string value into a type object.
11-
* @param value String value like "integer" or "Link[Model]".
10+
* @param values String or String[] value like "integer", "Link[Model]" or ["string", "null"]
1211
* @param template Optional template class from parent (needed to process generics)
1312
*/
14-
export function getType(value?: string, template?: string): Type {
13+
export function getType(values?: string | string[], template?: string): Type {
1514
const result: Type = {
1615
type: 'any',
1716
base: 'any',
1817
template: null,
1918
imports: [],
19+
isNullable: false,
2020
};
2121

22-
const valueClean = stripNamespace(value || '');
22+
// Special case for JSON Schema spec (december 2020, page 17),
23+
// that allows type to be an array of primitive types...
24+
if (Array.isArray(values)) {
25+
const type = values
26+
.filter(value => value !== 'null')
27+
.filter(value => hasMappedType(value))
28+
.map(value => getMappedType(value))
29+
.join(' | ');
30+
result.type = type;
31+
result.base = type;
32+
result.isNullable = values.includes('null');
33+
return result;
34+
}
35+
36+
const valueClean = stripNamespace(values || '');
2337

2438
if (/\[.*\]$/g.test(valueClean)) {
2539
const matches = valueClean.match(/(.*?)\[(.*)\]$/);

test/__snapshots__/index.spec.js.snap

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,7 +2094,7 @@ export class ParametersService {
20942094
parameterPath: string,
20952095
): Promise<void> {
20962096
const result = await __request({
2097-
method: 'GET',
2097+
method: 'POST',
20982098
path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath}\`,
20992099
headers: {
21002100
'parameterHeader': parameterHeader,
@@ -2132,7 +2132,7 @@ export class ParametersService {
21322132
_default?: string,
21332133
): Promise<void> {
21342134
const result = await __request({
2135-
method: 'GET',
2135+
method: 'POST',
21362136
path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath1}/\${parameterPath2}/\${parameterPath3}\`,
21372137
headers: {
21382138
'parameter.header': parameterHeader,
@@ -3572,7 +3572,7 @@ exports[`v3 should generate: ./test/generated/v3/models/SimpleStringWithPattern.
35723572
/**
35733573
* This is a simple string
35743574
*/
3575-
export type SimpleStringWithPattern = string | null;"
3575+
export type SimpleStringWithPattern = string;"
35763576
`;
35773577

35783578
exports[`v3 should generate: ./test/generated/v3/schemas/$ArrayWithArray.ts 1`] = `
@@ -4392,7 +4392,6 @@ exports[`v3 should generate: ./test/generated/v3/schemas/$SimpleStringWithPatter
43924392
/* eslint-disable */
43934393
export const $SimpleStringWithPattern = {
43944394
type: 'string',
4395-
isNullable: true,
43964395
maxLength: 64,
43974396
pattern: '^[a-zA-Z0-9_]*$',
43984397
};"
@@ -4791,7 +4790,7 @@ export class ParametersService {
47914790
requestBody: ModelWithString | null,
47924791
): Promise<void> {
47934792
const result = await __request({
4794-
method: 'GET',
4793+
method: 'POST',
47954794
path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath}\`,
47964795
cookies: {
47974796
'parameterCookie': parameterCookie,
@@ -4835,7 +4834,7 @@ export class ParametersService {
48354834
_default?: string,
48364835
): Promise<void> {
48374836
const result = await __request({
4838-
method: 'GET',
4837+
method: 'POST',
48394838
path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath1}/\${parameterPath2}/\${parameterPath3}\`,
48404839
cookies: {
48414840
'PARAMETER-COOKIE': parameterCookie,

test/e2e/v3.fetch.spec.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,22 @@ describe('v3.fetch', () => {
5757
});
5858
expect(result).toBeDefined();
5959
});
60+
61+
it('formData', async () => {
62+
const result = await browser.evaluate(async () => {
63+
const { ParametersService } = window.api;
64+
return await ParametersService.callWithParameters(
65+
'valueHeader',
66+
'valueQuery',
67+
'valueForm',
68+
'valueCookie',
69+
'valuePath',
70+
{
71+
prop: 'valueBody'
72+
}
73+
);
74+
});
75+
expect(result).toBeDefined();
76+
});
77+
6078
});

test/e2e/v3.node.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,19 @@ describe('v3.node', () => {
4848
expect(result).toBeDefined();
4949
});
5050

51+
it('formData', async () => {
52+
const { ParametersService } = require('./generated/v3/node/index.js');
53+
const result = await ParametersService.callWithParameters(
54+
'valueHeader',
55+
'valueQuery',
56+
'valueForm',
57+
'valueCookie',
58+
'valuePath',
59+
{
60+
prop: 'valueBody'
61+
}
62+
);
63+
console.log(result)
64+
expect(result).toBeDefined();
65+
});
5166
});

test/spec/v2.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
}
5656
},
5757
"/api/v{api-version}/parameters/{parameterPath}": {
58-
"get": {
58+
"post": {
5959
"tags": [
6060
"Parameters"
6161
],
@@ -106,7 +106,7 @@
106106
}
107107
},
108108
"/api/v{api-version}/parameters/{parameter.path.1}/{parameter-path-2}/{PARAMETER-PATH-3}": {
109-
"get": {
109+
"post": {
110110
"tags": [
111111
"Parameters"
112112
],

0 commit comments

Comments
 (0)