@mintlify/validation 0.1.177 → 0.1.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/openapi/IncrementalEvaluator.d.ts +58 -0
- package/dist/openapi/IncrementalEvaluator.js +363 -0
- package/dist/openapi/OpenApiToEndpointConverter.d.ts +26 -8
- package/dist/openapi/OpenApiToEndpointConverter.js +126 -42
- package/dist/openapi/ParametersConverter.d.ts +15 -2
- package/dist/openapi/ParametersConverter.js +61 -1
- package/dist/openapi/SchemaConverter.d.ts +14 -0
- package/dist/openapi/SchemaConverter.js +2 -15
- package/dist/openapi/stripComponents.d.ts +3 -0
- package/dist/openapi/stripComponents.js +31 -0
- package/dist/openapi/types/endpoint.d.ts +32 -24
- package/dist/openapi/types/endpoint.js +1 -0
- package/dist/openapi/utils.d.ts +8 -0
- package/dist/openapi/utils.js +30 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { BaseConverter } from './BaseConverter.js';
|
|
2
|
-
import {
|
|
2
|
+
import { generateFirstIncrementalSchema } from './IncrementalEvaluator.js';
|
|
3
|
+
import { IncrementalParametersConverter, ParametersConverter } from './ParametersConverter.js';
|
|
3
4
|
import { SchemaConverter } from './SchemaConverter.js';
|
|
4
5
|
import { SecurityConverter } from './SecurityConverter.js';
|
|
5
6
|
import { ServersConverter } from './ServersConverter.js';
|
|
6
7
|
import { InvalidSchemaError } from './errors.js';
|
|
7
8
|
import { generateExampleFromSchema } from './generateExampleFromSchema.js';
|
|
8
|
-
|
|
9
|
+
import { dereference } from './utils.js';
|
|
10
|
+
export class BaseOpenApiToEndpointConverter extends BaseConverter {
|
|
9
11
|
constructor(document, path, method, safeParse = false) {
|
|
10
12
|
super(safeParse);
|
|
11
13
|
this.document = document;
|
|
12
14
|
this.path = path;
|
|
13
15
|
this.method = method;
|
|
14
16
|
this.safeParse = safeParse;
|
|
15
|
-
}
|
|
16
|
-
convert() {
|
|
17
|
-
var _a, _b, _c, _d, _e;
|
|
18
17
|
const paths = this.document.paths;
|
|
19
18
|
if (paths === undefined) {
|
|
20
19
|
throw new InvalidSchemaError(['#'], 'paths not defined');
|
|
@@ -23,25 +22,27 @@ export class OpenApiToEndpointConverter extends BaseConverter {
|
|
|
23
22
|
if (pathObject === undefined) {
|
|
24
23
|
throw new InvalidSchemaError(['#', 'paths'], `path not defined: ${this.path}`);
|
|
25
24
|
}
|
|
25
|
+
this.pathObject = pathObject;
|
|
26
26
|
const operationObject = pathObject[this.method];
|
|
27
27
|
if (operationObject === undefined) {
|
|
28
28
|
throw new InvalidSchemaError(['#', 'paths', this.path], `operation does not exist: ${this.method}`);
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
this.operationObject = operationObject;
|
|
31
|
+
}
|
|
32
|
+
convert() {
|
|
33
|
+
var _a, _b, _c, _d, _e;
|
|
34
|
+
const securityRequirements = (_a = this.operationObject.security) !== null && _a !== void 0 ? _a : this.document.security;
|
|
31
35
|
const securitySchemes = (_b = this.document.components) === null || _b === void 0 ? void 0 : _b.securitySchemes;
|
|
32
36
|
const security = SecurityConverter.convert(securityRequirements, securitySchemes, this.safeParse);
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const parameters = ParametersConverter.convert(this.method, pathParameters, operationParameters, ['#', 'paths', this.path], this.safeParse);
|
|
36
|
-
const servers = ServersConverter.convert((_d = (_c = operationObject.servers) !== null && _c !== void 0 ? _c : pathObject.servers) !== null && _d !== void 0 ? _d : this.document.servers);
|
|
37
|
+
const parameters = this.convertParameters();
|
|
38
|
+
const servers = ServersConverter.convert((_d = (_c = this.operationObject.servers) !== null && _c !== void 0 ? _c : this.pathObject.servers) !== null && _d !== void 0 ? _d : this.document.servers);
|
|
37
39
|
// title is a bit too specific to take from the path object
|
|
38
|
-
const title = operationObject.summary;
|
|
39
|
-
const description = (_e = operationObject.description) !== null && _e !== void 0 ? _e : pathObject.description;
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const response = this.convertResponses(['#', 'paths', this.path, this.method, 'responses'], operationObject.responses);
|
|
40
|
+
const title = this.operationObject.summary;
|
|
41
|
+
const description = (_e = this.operationObject.description) !== null && _e !== void 0 ? _e : this.pathObject.description;
|
|
42
|
+
const body = this.convertBody();
|
|
43
|
+
const deprecated = !!this.operationObject.deprecated;
|
|
44
|
+
const codeSamples = this.convertCodeSamples(['#', 'paths', this.path, this.method], this.operationObject);
|
|
45
|
+
const response = this.convertResponses();
|
|
45
46
|
return {
|
|
46
47
|
title,
|
|
47
48
|
description,
|
|
@@ -58,24 +59,6 @@ export class OpenApiToEndpointConverter extends BaseConverter {
|
|
|
58
59
|
deprecated,
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
|
-
convertContent(debugPath, content, location, required) {
|
|
62
|
-
if (content === undefined) {
|
|
63
|
-
return {};
|
|
64
|
-
}
|
|
65
|
-
const newEntries = Object.entries(content).map(([contentType, mediaObject]) => {
|
|
66
|
-
const schemaArray = SchemaConverter.convert({
|
|
67
|
-
schema: mediaObject.schema,
|
|
68
|
-
path: [...debugPath, contentType, 'schema'],
|
|
69
|
-
required,
|
|
70
|
-
location,
|
|
71
|
-
contentType,
|
|
72
|
-
safeParse: this.safeParse,
|
|
73
|
-
});
|
|
74
|
-
const examples = this.convertExamples(mediaObject.examples, mediaObject.example, schemaArray);
|
|
75
|
-
return [contentType, { schemaArray, examples }];
|
|
76
|
-
});
|
|
77
|
-
return Object.fromEntries(newEntries);
|
|
78
|
-
}
|
|
79
62
|
convertExamples(examples, example, schemaArray) {
|
|
80
63
|
if (examples && Object.values(examples).some(({ value }) => value !== undefined)) {
|
|
81
64
|
return Object.fromEntries(Object.entries(examples)
|
|
@@ -94,13 +77,6 @@ export class OpenApiToEndpointConverter extends BaseConverter {
|
|
|
94
77
|
}
|
|
95
78
|
return { example: { value: generateExampleFromSchema(schemaArray[0]) } };
|
|
96
79
|
}
|
|
97
|
-
convertResponses(debugPath, responses) {
|
|
98
|
-
const newEntries = Object.entries(responses).map(([statusCode, response]) => [
|
|
99
|
-
statusCode,
|
|
100
|
-
this.convertContent([...debugPath, statusCode, 'content'], response.content, 'response'),
|
|
101
|
-
]);
|
|
102
|
-
return Object.fromEntries(newEntries);
|
|
103
|
-
}
|
|
104
80
|
convertCodeSamples(debugPath, operation) {
|
|
105
81
|
let key;
|
|
106
82
|
let rawCodeSamples;
|
|
@@ -140,7 +116,115 @@ export class OpenApiToEndpointConverter extends BaseConverter {
|
|
|
140
116
|
});
|
|
141
117
|
return codeSamples;
|
|
142
118
|
}
|
|
119
|
+
}
|
|
120
|
+
export class OpenApiToEndpointConverter extends BaseOpenApiToEndpointConverter {
|
|
121
|
+
convertBody() {
|
|
122
|
+
const requestBody = this.operationObject.requestBody;
|
|
123
|
+
return this.convertContent(['#', 'paths', this.path, this.method, 'requestBody', 'content'], requestBody === null || requestBody === void 0 ? void 0 : requestBody.content, 'request', requestBody === null || requestBody === void 0 ? void 0 : requestBody.required);
|
|
124
|
+
}
|
|
125
|
+
convertResponses() {
|
|
126
|
+
const responses = this.operationObject.responses;
|
|
127
|
+
if (!responses)
|
|
128
|
+
return {};
|
|
129
|
+
const newEntries = Object.entries(responses).map(([statusCode, response]) => [
|
|
130
|
+
statusCode,
|
|
131
|
+
this.convertContent(['#', 'paths', this.path, this.method, 'responses', statusCode, 'content'], response.content, 'response'),
|
|
132
|
+
]);
|
|
133
|
+
return Object.fromEntries(newEntries);
|
|
134
|
+
}
|
|
135
|
+
convertContent(debugPath, content, location, required) {
|
|
136
|
+
if (content === undefined) {
|
|
137
|
+
return {};
|
|
138
|
+
}
|
|
139
|
+
const newEntries = Object.entries(content).map(([contentType, mediaObject]) => {
|
|
140
|
+
const schemaArray = SchemaConverter.convert({
|
|
141
|
+
schema: mediaObject.schema,
|
|
142
|
+
path: [...debugPath, contentType, 'schema'],
|
|
143
|
+
required,
|
|
144
|
+
location,
|
|
145
|
+
contentType,
|
|
146
|
+
safeParse: this.safeParse,
|
|
147
|
+
});
|
|
148
|
+
const examples = this.convertExamples(mediaObject.examples, mediaObject.example, schemaArray);
|
|
149
|
+
return [contentType, { schemaArray, examples }];
|
|
150
|
+
});
|
|
151
|
+
return Object.fromEntries(newEntries);
|
|
152
|
+
}
|
|
153
|
+
convertParameters() {
|
|
154
|
+
const pathParameters = this.pathObject.parameters;
|
|
155
|
+
const operationParameters = this.operationObject.parameters;
|
|
156
|
+
return ParametersConverter.convert(this.method, pathParameters, operationParameters, ['#', 'paths', this.path], this.safeParse);
|
|
157
|
+
}
|
|
143
158
|
static convert(spec, path, method, safeParse) {
|
|
144
159
|
return new OpenApiToEndpointConverter(spec, path, method, safeParse).convert();
|
|
145
160
|
}
|
|
146
161
|
}
|
|
162
|
+
export class OpenApiToIncrementalEndpointConverter extends BaseOpenApiToEndpointConverter {
|
|
163
|
+
constructor(rawDocument, document, path, method, safeParse = false) {
|
|
164
|
+
super(document, path, method, safeParse);
|
|
165
|
+
this.rawDocument = rawDocument;
|
|
166
|
+
}
|
|
167
|
+
convertParameters() {
|
|
168
|
+
var _a, _b, _c, _d, _e;
|
|
169
|
+
const pathParameters = (_b = (_a = this.rawDocument.paths) === null || _a === void 0 ? void 0 : _a[this.path]) === null || _b === void 0 ? void 0 : _b.parameters;
|
|
170
|
+
const operationParameters = (_e = (_d = (_c = this.rawDocument.paths) === null || _c === void 0 ? void 0 : _c[this.path]) === null || _d === void 0 ? void 0 : _d[this.method]) === null || _e === void 0 ? void 0 : _e.parameters;
|
|
171
|
+
return IncrementalParametersConverter.convert(this.rawDocument, this.method, pathParameters, operationParameters, ['#', 'paths', this.path], this.safeParse);
|
|
172
|
+
}
|
|
173
|
+
convertBody() {
|
|
174
|
+
var _a, _b, _c, _d;
|
|
175
|
+
let rawRequestBody = (_c = (_b = (_a = this.rawDocument.paths) === null || _a === void 0 ? void 0 : _a[this.path]) === null || _b === void 0 ? void 0 : _b[this.method]) === null || _c === void 0 ? void 0 : _c.requestBody;
|
|
176
|
+
if (rawRequestBody && '$ref' in rawRequestBody) {
|
|
177
|
+
rawRequestBody = dereference('requestBodies', rawRequestBody.$ref, (_d = this.rawDocument.components) === null || _d === void 0 ? void 0 : _d.requestBodies);
|
|
178
|
+
}
|
|
179
|
+
if (!rawRequestBody || '$ref' in rawRequestBody)
|
|
180
|
+
return {};
|
|
181
|
+
const requestBody = this.operationObject.requestBody;
|
|
182
|
+
return this.convertContent(['#', 'paths', this.path, this.method, 'requestBody', 'content'], rawRequestBody.content, requestBody === null || requestBody === void 0 ? void 0 : requestBody.content, 'request', requestBody === null || requestBody === void 0 ? void 0 : requestBody.required);
|
|
183
|
+
}
|
|
184
|
+
convertResponses() {
|
|
185
|
+
var _a, _b, _c;
|
|
186
|
+
const rawResponses = (_c = (_b = (_a = this.rawDocument.paths) === null || _a === void 0 ? void 0 : _a[this.path]) === null || _b === void 0 ? void 0 : _b[this.method]) === null || _c === void 0 ? void 0 : _c.responses;
|
|
187
|
+
if (!rawResponses)
|
|
188
|
+
return {};
|
|
189
|
+
const newEntries = Object.entries(rawResponses).map(([statusCode, rawResponse]) => {
|
|
190
|
+
var _a, _b;
|
|
191
|
+
if ('$ref' in rawResponse) {
|
|
192
|
+
const dereferencedRes = dereference('responses', rawResponse.$ref, (_a = this.rawDocument.components) === null || _a === void 0 ? void 0 : _a.responses);
|
|
193
|
+
if (!dereferencedRes || '$ref' in dereferencedRes)
|
|
194
|
+
throw Error();
|
|
195
|
+
rawResponse = dereferencedRes;
|
|
196
|
+
}
|
|
197
|
+
const response = (_b = this.operationObject.responses) === null || _b === void 0 ? void 0 : _b[statusCode];
|
|
198
|
+
return [
|
|
199
|
+
statusCode,
|
|
200
|
+
this.convertContent(['#', 'paths', this.path, this.method, 'responses', statusCode, 'content'], rawResponse.content, response === null || response === void 0 ? void 0 : response.content, 'response'),
|
|
201
|
+
];
|
|
202
|
+
});
|
|
203
|
+
return Object.fromEntries(newEntries);
|
|
204
|
+
}
|
|
205
|
+
convertContent(debugPath, rawContent, dereferencedContent, location, required) {
|
|
206
|
+
if (!rawContent || !dereferencedContent) {
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
const newEntries = Object.entries(rawContent).map(([contentType, mediaObject]) => {
|
|
210
|
+
var _a;
|
|
211
|
+
const incrementalSchemaArray = generateFirstIncrementalSchema(mediaObject.schema, (_a = this.rawDocument.components) === null || _a === void 0 ? void 0 : _a.schemas, required, location, contentType);
|
|
212
|
+
// still need to generate schemaArray so we can generate examples
|
|
213
|
+
const dereferencedMediaObject = dereferencedContent[contentType];
|
|
214
|
+
const schemaArray = SchemaConverter.convert({
|
|
215
|
+
schema: dereferencedMediaObject === null || dereferencedMediaObject === void 0 ? void 0 : dereferencedMediaObject.schema,
|
|
216
|
+
path: [...debugPath, contentType, 'schema'],
|
|
217
|
+
required,
|
|
218
|
+
location,
|
|
219
|
+
contentType,
|
|
220
|
+
safeParse: this.safeParse,
|
|
221
|
+
});
|
|
222
|
+
const examples = this.convertExamples(dereferencedMediaObject === null || dereferencedMediaObject === void 0 ? void 0 : dereferencedMediaObject.examples, dereferencedMediaObject === null || dereferencedMediaObject === void 0 ? void 0 : dereferencedMediaObject.example, schemaArray);
|
|
223
|
+
return [contentType, { schemaArray: incrementalSchemaArray, examples }];
|
|
224
|
+
});
|
|
225
|
+
return Object.fromEntries(newEntries);
|
|
226
|
+
}
|
|
227
|
+
static convert(rawDocument, resolvedDocument, path, method, safeParse) {
|
|
228
|
+
return new OpenApiToIncrementalEndpointConverter(rawDocument, resolvedDocument, path, method, safeParse).convert();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OpenAPIV3_1 } from 'openapi-types';
|
|
2
2
|
import { BaseConverter } from './BaseConverter.js';
|
|
3
|
-
import { ParameterSections } from './types/endpoint.js';
|
|
3
|
+
import { DataSchemaArray, IncrementalDataSchemaArray, ParameterSections } from './types/endpoint.js';
|
|
4
4
|
export declare class ParametersConverter extends BaseConverter {
|
|
5
5
|
readonly method: string;
|
|
6
6
|
readonly pathParameters: OpenAPIV3_1.ParameterObject[] | undefined;
|
|
@@ -11,5 +11,18 @@ export declare class ParametersConverter extends BaseConverter {
|
|
|
11
11
|
private constructor();
|
|
12
12
|
private convert;
|
|
13
13
|
private addParameter;
|
|
14
|
-
static convert(method: string, pathParameters: OpenAPIV3_1.ParameterObject[] | undefined, operationParameters: OpenAPIV3_1.ParameterObject[] | undefined, path: string[], safeParse?: boolean): ParameterSections
|
|
14
|
+
static convert(method: string, pathParameters: OpenAPIV3_1.ParameterObject[] | undefined, operationParameters: OpenAPIV3_1.ParameterObject[] | undefined, path: string[], safeParse?: boolean): ParameterSections<DataSchemaArray>;
|
|
15
|
+
}
|
|
16
|
+
export declare class IncrementalParametersConverter extends BaseConverter {
|
|
17
|
+
readonly rawDocument: OpenAPIV3_1.Document;
|
|
18
|
+
readonly method: string;
|
|
19
|
+
readonly pathParameters: (OpenAPIV3_1.ParameterObject | OpenAPIV3_1.ReferenceObject)[] | undefined;
|
|
20
|
+
readonly operationParameters: (OpenAPIV3_1.ParameterObject | OpenAPIV3_1.ReferenceObject)[] | undefined;
|
|
21
|
+
readonly path: string[];
|
|
22
|
+
readonly safeParse: boolean;
|
|
23
|
+
private parameterSections;
|
|
24
|
+
private constructor();
|
|
25
|
+
private convert;
|
|
26
|
+
private addParameter;
|
|
27
|
+
static convert(rawDocument: OpenAPIV3_1.Document, method: string, pathParameters: (OpenAPIV3_1.ParameterObject | OpenAPIV3_1.ReferenceObject)[] | undefined, operationParameters: (OpenAPIV3_1.ParameterObject | OpenAPIV3_1.ReferenceObject)[] | undefined, path: string[], safeParse?: boolean): ParameterSections<IncrementalDataSchemaArray>;
|
|
15
28
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BaseConverter } from './BaseConverter.js';
|
|
2
|
+
import { generateFirstIncrementalSchema } from './IncrementalEvaluator.js';
|
|
2
3
|
import { SchemaConverter } from './SchemaConverter.js';
|
|
3
4
|
import { InvalidSchemaError } from './errors.js';
|
|
4
|
-
import { copyKeyIfDefined } from './utils.js';
|
|
5
|
+
import { copyKeyIfDefined, dereference } from './utils.js';
|
|
5
6
|
export class ParametersConverter extends BaseConverter {
|
|
6
7
|
constructor(method, pathParameters, operationParameters, path, safeParse = false) {
|
|
7
8
|
super(safeParse);
|
|
@@ -48,3 +49,62 @@ export class ParametersConverter extends BaseConverter {
|
|
|
48
49
|
return new ParametersConverter(method, pathParameters, operationParameters, path, safeParse).convert();
|
|
49
50
|
}
|
|
50
51
|
}
|
|
52
|
+
export class IncrementalParametersConverter extends BaseConverter {
|
|
53
|
+
constructor(rawDocument, method, pathParameters, operationParameters, path, safeParse = false) {
|
|
54
|
+
super(safeParse);
|
|
55
|
+
this.rawDocument = rawDocument;
|
|
56
|
+
this.method = method;
|
|
57
|
+
this.pathParameters = pathParameters;
|
|
58
|
+
this.operationParameters = operationParameters;
|
|
59
|
+
this.path = path;
|
|
60
|
+
this.safeParse = safeParse;
|
|
61
|
+
this.parameterSections = {
|
|
62
|
+
path: {},
|
|
63
|
+
query: {},
|
|
64
|
+
header: {},
|
|
65
|
+
cookie: {},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
convert() {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
(_a = this.pathParameters) === null || _a === void 0 ? void 0 : _a.forEach((parameterObject, i) => {
|
|
71
|
+
this.addParameter([...this.path, 'parameters', i.toString()], parameterObject);
|
|
72
|
+
});
|
|
73
|
+
(_b = this.operationParameters) === null || _b === void 0 ? void 0 : _b.forEach((parameterObject, i) => {
|
|
74
|
+
this.addParameter([...this.path, this.method, 'parameters', i.toString()], parameterObject);
|
|
75
|
+
});
|
|
76
|
+
return this.parameterSections;
|
|
77
|
+
}
|
|
78
|
+
addParameter(path, parameter) {
|
|
79
|
+
var _a, _b, _c;
|
|
80
|
+
if ('$ref' in parameter) {
|
|
81
|
+
const dereferencedParam = dereference('parameters', parameter.$ref, (_a = this.rawDocument.components) === null || _a === void 0 ? void 0 : _a.parameters);
|
|
82
|
+
if (!dereferencedParam || '$ref' in dereferencedParam) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
parameter = dereferencedParam;
|
|
86
|
+
}
|
|
87
|
+
if (!['path', 'header', 'query', 'cookie'].includes(parameter.in)) {
|
|
88
|
+
this.handleNewError(InvalidSchemaError, path, `invalid parameter location: '${parameter.in}'`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const location = parameter.in;
|
|
92
|
+
// parameter.schema may be undefined (if the schema is instead defined in parameter.content), but this is likely super rare
|
|
93
|
+
let schema = parameter.schema;
|
|
94
|
+
if (schema && '$ref' in schema) {
|
|
95
|
+
schema = dereference('schemas', schema.$ref, (_b = this.rawDocument.components) === null || _b === void 0 ? void 0 : _b.schemas);
|
|
96
|
+
}
|
|
97
|
+
if (!schema) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// maintain immutability
|
|
101
|
+
const schemaCopy = Object.assign({}, schema);
|
|
102
|
+
copyKeyIfDefined('description', parameter, schemaCopy);
|
|
103
|
+
copyKeyIfDefined('deprecated', parameter, schemaCopy);
|
|
104
|
+
const incrementalSchema = generateFirstIncrementalSchema(schemaCopy, (_c = this.rawDocument.components) === null || _c === void 0 ? void 0 : _c.schemas, location === 'path' ? true : parameter.required);
|
|
105
|
+
this.parameterSections[location][parameter.name] = { schema: incrementalSchema };
|
|
106
|
+
}
|
|
107
|
+
static convert(rawDocument, method, pathParameters, operationParameters, path, safeParse) {
|
|
108
|
+
return new IncrementalParametersConverter(rawDocument, method, pathParameters, operationParameters, path, safeParse).convert();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -62,3 +62,17 @@ export declare class SchemaConverter extends BaseConverter {
|
|
|
62
62
|
safeParse?: boolean;
|
|
63
63
|
}): DataSchemaArray;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Given an OpenAPI 3.1 schema, this function will attempt to determine the schema type
|
|
67
|
+
* based on the properties present in the schema. This is useful for assigning types to
|
|
68
|
+
* schemas that are missing a type.
|
|
69
|
+
*
|
|
70
|
+
* For example, if a schema has no type but has `schema.properties`, we can infer the
|
|
71
|
+
* intended type is `object`.
|
|
72
|
+
*
|
|
73
|
+
* Used in the Conversion step.
|
|
74
|
+
*
|
|
75
|
+
* @param schema
|
|
76
|
+
* @returns if exactly one type can be inferred, the string corresponding to that type; otherwise `undefined`
|
|
77
|
+
*/
|
|
78
|
+
export declare const inferType: (schema: Omit<OpenAPIV3_1.SchemaObject, "type">) => OpenAPIV3_1.ArraySchemaObjectType | OpenAPIV3_1.NonArraySchemaObjectType | undefined;
|
|
@@ -2,13 +2,7 @@ import lcm from 'lcm';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import { BaseConverter } from './BaseConverter.js';
|
|
4
4
|
import { ConversionError, ImpossibleSchemaError, InvalidSchemaError } from './errors.js';
|
|
5
|
-
import { addKeyIfDefined, copyKeyIfDefined } from './utils.js';
|
|
6
|
-
const structuredDataContentTypes = [
|
|
7
|
-
'multipart/form-data',
|
|
8
|
-
'application/json',
|
|
9
|
-
'application/x-www-form-urlencoded',
|
|
10
|
-
];
|
|
11
|
-
const stringFileFormats = ['binary', 'base64'];
|
|
5
|
+
import { addKeyIfDefined, copyExampleIfDefined, copyKeyIfDefined, stringFileFormats, structuredDataContentTypes, } from './utils.js';
|
|
12
6
|
export class SchemaConverter extends BaseConverter {
|
|
13
7
|
constructor(schema, required, path = ['#'], location, contentType, safeParse = false) {
|
|
14
8
|
super(safeParse);
|
|
@@ -484,13 +478,6 @@ export class SchemaConverter extends BaseConverter {
|
|
|
484
478
|
return new SchemaConverter(schema, required, path, location, contentType, safeParse).convert();
|
|
485
479
|
}
|
|
486
480
|
}
|
|
487
|
-
const copyExampleIfDefined = (source, destination) => {
|
|
488
|
-
var _a;
|
|
489
|
-
const example = ((_a = source.examples) === null || _a === void 0 ? void 0 : _a[0]) !== undefined ? source.examples[0] : source.example;
|
|
490
|
-
if (example !== undefined) {
|
|
491
|
-
destination.example = example;
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
481
|
const takeLast = (schema1, schema2, key) => {
|
|
495
482
|
var _a;
|
|
496
483
|
return (_a = schema2[key]) !== null && _a !== void 0 ? _a : schema1[key];
|
|
@@ -514,7 +501,7 @@ const combine = (schema1, schema2, key, transform) => {
|
|
|
514
501
|
* @param schema
|
|
515
502
|
* @returns if exactly one type can be inferred, the string corresponding to that type; otherwise `undefined`
|
|
516
503
|
*/
|
|
517
|
-
const inferType = (schema) => {
|
|
504
|
+
export const inferType = (schema) => {
|
|
518
505
|
var _a, _b;
|
|
519
506
|
let type = undefined;
|
|
520
507
|
if (schema.format !== undefined ||
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
export declare function findRefsUsed(schema: unknown, components?: Record<string, unknown>): Set<string>;
|
|
3
|
+
export declare function stripComponents(valueContainingRefs: unknown, rawDocument: OpenAPIV3_1.Document): Record<string, OpenAPIV3_1.SchemaObject>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const schemaPrefix = '#/components/schemas/';
|
|
2
|
+
export function findRefsUsed(schema, components = {}) {
|
|
3
|
+
const refsUsed = new Set();
|
|
4
|
+
function traverse(value) {
|
|
5
|
+
if (typeof value === 'object' && value !== null) {
|
|
6
|
+
if ('$ref' in value &&
|
|
7
|
+
typeof value.$ref === 'string' &&
|
|
8
|
+
value.$ref.startsWith(schemaPrefix)) {
|
|
9
|
+
const schemaName = value.$ref.slice(schemaPrefix.length);
|
|
10
|
+
if (!refsUsed.has(schemaName)) {
|
|
11
|
+
refsUsed.add(schemaName);
|
|
12
|
+
traverse(components[schemaName]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
for (const val of Object.values(value)) {
|
|
16
|
+
traverse(val);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
traverse(schema);
|
|
21
|
+
return refsUsed;
|
|
22
|
+
}
|
|
23
|
+
export function stripComponents(valueContainingRefs, rawDocument) {
|
|
24
|
+
var _a;
|
|
25
|
+
const schemas = (_a = rawDocument.components) === null || _a === void 0 ? void 0 : _a.schemas;
|
|
26
|
+
if (schemas === undefined)
|
|
27
|
+
return {};
|
|
28
|
+
const refsUsed = findRefsUsed(valueContainingRefs, schemas);
|
|
29
|
+
const newEntries = Object.entries(schemas).filter(([schemaName]) => refsUsed.has(schemaName));
|
|
30
|
+
return Object.fromEntries(newEntries);
|
|
31
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
export type Endpoint<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
2
3
|
title?: string;
|
|
3
4
|
description?: string;
|
|
4
5
|
path: string;
|
|
5
6
|
method: HttpMethod;
|
|
6
7
|
servers?: Server[];
|
|
7
|
-
request: RequestSchema
|
|
8
|
-
response: ResponseSchema
|
|
8
|
+
request: RequestSchema<D>;
|
|
9
|
+
response: ResponseSchema<D>;
|
|
9
10
|
deprecated: boolean;
|
|
10
11
|
};
|
|
11
12
|
export type Server = {
|
|
@@ -29,10 +30,10 @@ export type ServerVariableStringEnumSchema = {
|
|
|
29
30
|
};
|
|
30
31
|
export declare const httpMethods: readonly ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
31
32
|
export type HttpMethod = (typeof httpMethods)[number];
|
|
32
|
-
export type RequestSchema = {
|
|
33
|
+
export type RequestSchema<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
33
34
|
security: SecurityOption[];
|
|
34
|
-
parameters: ParameterSections
|
|
35
|
-
body: BodySchema
|
|
35
|
+
parameters: ParameterSections<D>;
|
|
36
|
+
body: BodySchema<D>;
|
|
36
37
|
codeSamples?: CodeSample[];
|
|
37
38
|
};
|
|
38
39
|
export type CodeSample = {
|
|
@@ -40,11 +41,11 @@ export type CodeSample = {
|
|
|
40
41
|
lang: string;
|
|
41
42
|
source: string;
|
|
42
43
|
};
|
|
43
|
-
export type BodySchema = {
|
|
44
|
-
[contentType: string]: ContentSchema
|
|
44
|
+
export type BodySchema<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
45
|
+
[contentType: string]: ContentSchema<D>;
|
|
45
46
|
};
|
|
46
|
-
export type ContentSchema = {
|
|
47
|
-
schemaArray:
|
|
47
|
+
export type ContentSchema<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
48
|
+
schemaArray: D;
|
|
48
49
|
examples: {
|
|
49
50
|
[title: string]: ExampleSchema;
|
|
50
51
|
};
|
|
@@ -54,15 +55,15 @@ export type ExampleSchema = {
|
|
|
54
55
|
description?: string;
|
|
55
56
|
value: unknown;
|
|
56
57
|
};
|
|
57
|
-
export type ParameterSchema = {
|
|
58
|
-
schema:
|
|
58
|
+
export type ParameterSchema<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
59
|
+
schema: D;
|
|
59
60
|
};
|
|
60
|
-
export type ParameterGroup = {
|
|
61
|
-
[name: string]: ParameterSchema
|
|
61
|
+
export type ParameterGroup<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
62
|
+
[name: string]: ParameterSchema<D>;
|
|
62
63
|
};
|
|
63
64
|
export type ParameterLocation = 'query' | 'header' | 'cookie' | 'path';
|
|
64
65
|
type NonPathParameterLocation = Exclude<ParameterLocation, 'path'>;
|
|
65
|
-
export type ParameterSections = Record<ParameterLocation, ParameterGroup
|
|
66
|
+
export type ParameterSections<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = Record<ParameterLocation, ParameterGroup<D>>;
|
|
66
67
|
export type SecurityOption = {
|
|
67
68
|
title: string;
|
|
68
69
|
parameters: SecurityParameterSections;
|
|
@@ -85,13 +86,11 @@ export type SecurityParameterGroup = {
|
|
|
85
86
|
[name: string]: SecurityParameterSchema;
|
|
86
87
|
};
|
|
87
88
|
export type SecurityParameterSections = Record<NonPathParameterLocation, SecurityParameterGroup>;
|
|
88
|
-
export type ResponseSchema = {
|
|
89
|
-
[code: string]: BodySchema
|
|
89
|
+
export type ResponseSchema<D extends DataSchemaArray | IncrementalDataSchemaArray = DataSchemaArray | IncrementalDataSchemaArray> = {
|
|
90
|
+
[code: string]: BodySchema<D>;
|
|
90
91
|
};
|
|
91
|
-
export type DataSchemaArray = [DataSchema, ...DataSchema[]];
|
|
92
92
|
export declare const typeList: readonly ["boolean", "string", "number", "integer", "object", "array", "enum<string>", "enum<number>", "enum<integer>", "file", "null", "any"];
|
|
93
93
|
export type SchemaType = (typeof typeList)[number];
|
|
94
|
-
export type DataSchema = BooleanSchema | StringSchema | NumberSchema | ObjectSchema | ArraySchema | StringEnumSchema | NumberEnumSchema | FileSchema | NullSchema | AnySchema;
|
|
95
94
|
export type BaseSchema<T> = {
|
|
96
95
|
type: SchemaType;
|
|
97
96
|
title?: string;
|
|
@@ -121,18 +120,19 @@ export type NumberSchema = {
|
|
|
121
120
|
minimum?: number;
|
|
122
121
|
exclusiveMinimum?: boolean;
|
|
123
122
|
} & BaseSchema<number>;
|
|
124
|
-
|
|
123
|
+
type BaseObjectSchema<R> = {
|
|
125
124
|
type: 'object';
|
|
126
|
-
additionalProperties?: boolean |
|
|
125
|
+
additionalProperties?: boolean | R;
|
|
127
126
|
maxProperties?: number;
|
|
128
127
|
minProperties?: number;
|
|
129
128
|
properties: {
|
|
130
|
-
[key: string]:
|
|
129
|
+
[key: string]: R;
|
|
131
130
|
};
|
|
131
|
+
requiredProperties?: string[];
|
|
132
132
|
} & BaseSchema<Record<string, unknown>>;
|
|
133
|
-
|
|
133
|
+
type BaseArraySchema<R> = {
|
|
134
134
|
type: 'array';
|
|
135
|
-
items:
|
|
135
|
+
items: R;
|
|
136
136
|
maxItems?: number;
|
|
137
137
|
minItems?: number;
|
|
138
138
|
uniqueItems?: boolean;
|
|
@@ -156,4 +156,12 @@ export type NullSchema = {
|
|
|
156
156
|
export type AnySchema = {
|
|
157
157
|
type: 'any';
|
|
158
158
|
} & BaseSchema<unknown>;
|
|
159
|
+
export type ObjectSchema = BaseObjectSchema<DataSchemaArray>;
|
|
160
|
+
export type ArraySchema = BaseArraySchema<DataSchemaArray>;
|
|
161
|
+
export type DataSchema = BooleanSchema | StringSchema | NumberSchema | ObjectSchema | ArraySchema | StringEnumSchema | NumberEnumSchema | FileSchema | NullSchema | AnySchema;
|
|
162
|
+
export type DataSchemaArray = [DataSchema, ...DataSchema[]];
|
|
163
|
+
export type IncrementalObjectSchema = BaseObjectSchema<OpenAPIV3_1.SchemaObject>;
|
|
164
|
+
export type IncrementalArraySchema = BaseArraySchema<OpenAPIV3_1.SchemaObject>;
|
|
165
|
+
export type IncrementalDataSchema = BooleanSchema | StringSchema | NumberSchema | IncrementalObjectSchema | IncrementalArraySchema | StringEnumSchema | NumberEnumSchema | FileSchema | NullSchema | AnySchema;
|
|
166
|
+
export type IncrementalDataSchemaArray = [IncrementalDataSchema, ...IncrementalDataSchema[]];
|
|
159
167
|
export {};
|
package/dist/openapi/utils.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
import { OpenAPIV3_1 } from 'openapi-types';
|
|
2
|
+
import { DataSchema } from './types/endpoint.js';
|
|
3
|
+
export declare const stringFileFormats: string[];
|
|
4
|
+
export declare const structuredDataContentTypes: string[];
|
|
5
|
+
type ComponentsSection = keyof OpenAPIV3_1.ComponentsObject;
|
|
6
|
+
export declare function dereference<S extends ComponentsSection>(section: S, $ref: string, components: Record<string, NonNullable<OpenAPIV3_1.ComponentsObject[S]>[string]> | undefined, maxDepth?: number): NonNullable<OpenAPIV3_1.ComponentsObject[S]>[string] | undefined;
|
|
1
7
|
export declare const addKeyIfDefined: <D, K extends keyof D>(key: K, value: D[K] | undefined, destination: D) => void;
|
|
2
8
|
export declare const copyKeyIfDefined: <D, K extends keyof D>(key: K, source: Pick<D, K>, destination: D) => void;
|
|
9
|
+
export declare const copyExampleIfDefined: (source: Pick<OpenAPIV3_1.SchemaObject, "example" | "examples">, destination: Pick<DataSchema, "example">) => void;
|
|
10
|
+
export {};
|
package/dist/openapi/utils.js
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
export const stringFileFormats = ['binary', 'base64'];
|
|
2
|
+
export const structuredDataContentTypes = [
|
|
3
|
+
'multipart/form-data',
|
|
4
|
+
'application/json',
|
|
5
|
+
'application/x-www-form-urlencoded',
|
|
6
|
+
];
|
|
7
|
+
// the number of times a $ref can point to another $ref before we give up
|
|
8
|
+
const MAX_DEREFERENCE_DEPTH = 5;
|
|
9
|
+
export function dereference(section, $ref, components, maxDepth = MAX_DEREFERENCE_DEPTH) {
|
|
10
|
+
const sectionPrefix = `#/components/${section}/`;
|
|
11
|
+
if (!$ref.startsWith(sectionPrefix))
|
|
12
|
+
return undefined;
|
|
13
|
+
const key = $ref.slice(sectionPrefix.length);
|
|
14
|
+
const value = components === null || components === void 0 ? void 0 : components[key];
|
|
15
|
+
// if a $ref points to another $ref, keep resolving until we hit our max depth
|
|
16
|
+
if (value && '$ref' in value) {
|
|
17
|
+
if (maxDepth > 0 && typeof value.$ref === 'string') {
|
|
18
|
+
return dereference(section, value.$ref, components, maxDepth - 1);
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
1
24
|
export const addKeyIfDefined = (key, value, destination) => {
|
|
2
25
|
if (value !== undefined) {
|
|
3
26
|
destination[key] = value;
|
|
@@ -10,3 +33,10 @@ export const copyKeyIfDefined = (key, source, destination) => {
|
|
|
10
33
|
destination[key] = source[key];
|
|
11
34
|
}
|
|
12
35
|
};
|
|
36
|
+
export const copyExampleIfDefined = (source, destination) => {
|
|
37
|
+
var _a;
|
|
38
|
+
const example = ((_a = source.examples) === null || _a === void 0 ? void 0 : _a[0]) !== undefined ? source.examples[0] : source.example;
|
|
39
|
+
if (example !== undefined) {
|
|
40
|
+
destination.example = example;
|
|
41
|
+
}
|
|
42
|
+
};
|