-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbool-enum-to-bool.js
100 lines (86 loc) · 2.81 KB
/
bool-enum-to-bool.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* @copyright Copyright 2021 Kevin Locke <kevin@kevinlocke.name>
* @license MIT
* @module "openapi-transformers/bool-enum-to-bool.js"
*/
import OpenApiTransformerBase from 'openapi-transformer-base';
const inStringContextSymbol = Symbol('inStringContext');
/**
* Transformer to replace `enum: [true, false]` with `type: boolean` for
* simplicity and to assist generators.
*/
export default class BoolEnumToBoolTransformer
extends OpenApiTransformerBase {
constructor() {
super();
this[inStringContextSymbol] = false;
}
transformSchemaLike(schema) {
if (schema === null
|| typeof schema !== 'object'
|| Array.isArray(schema)) {
return schema;
}
const { enum: enumValues, ...schemaNoEnum } = schema;
if (!Array.isArray(enumValues) || enumValues.length < 2) {
return schema;
}
const { type } = schema;
if (!this[inStringContextSymbol]
&& type !== 'boolean'
&& !enumValues.every((ev) => typeof ev === 'boolean')) {
// If schema validates non-boolean values in a type-sensitive context,
// limiting to boolean would change validation.
return schema;
}
if (!(enumValues.includes(true) || enumValues.includes('true'))
|| !(enumValues.includes(false) || enumValues.includes('false'))
|| enumValues.some((ev) => ev !== true
&& ev !== false
&& ev !== 'true'
&& ev !== 'false')) {
// Enum must contain both true and false, and only true/false
return schema;
}
schemaNoEnum.type = 'boolean';
return schemaNoEnum;
}
transformSchema(schema) {
return this.transformSchemaLike(super.transformSchema(schema));
}
transformItems(items) {
return this.transformSchemaLike(super.transformItems(items));
}
transformHeader(header) {
const prevContext = this[inStringContextSymbol];
try {
this[inStringContextSymbol] = true;
return this.transformSchemaLike(super.transformHeader(header));
} finally {
this[inStringContextSymbol] = prevContext;
}
}
transformParameter(parameter) {
const prevContext = this[inStringContextSymbol];
try {
this[inStringContextSymbol] = parameter.in !== 'body';
return this.transformSchemaLike(super.transformParameter(parameter));
} finally {
this[inStringContextSymbol] = prevContext;
}
}
transformMediaType(mediaType) {
const prevContext = this[inStringContextSymbol];
const mediaTypeStr = this.transformPath.at(-1);
try {
this[inStringContextSymbol] =
mediaTypeStr === 'application/x-www-form-urlencoded'
|| mediaTypeStr === 'multipart/form-data'
|| mediaTypeStr === 'text/csv'
|| mediaTypeStr === 'text/plain';
return super.transformMediaType(mediaType);
} finally {
this[inStringContextSymbol] = prevContext;
}
}
}