@kubb/oas 3.16.2 → 3.16.3

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.js CHANGED
@@ -1,341 +1,298 @@
1
- import { matchesMimeType } from 'oas/utils';
2
- export { findSchemaDefinition, matchesMimeType } from 'oas/utils';
3
- import { isRef } from 'oas/types';
4
- import { isPlainObject, mergeDeep } from 'remeda';
5
- import { loadConfig, bundle } from '@redocly/openapi-core';
6
- import OASNormalize from 'oas-normalize';
7
- import swagger2openapi from 'swagger2openapi';
8
- import jsonpointer from 'jsonpointer';
9
- import BaseOas from 'oas';
1
+ import { findSchemaDefinition, matchesMimeType, matchesMimeType as matchesMimeType$1 } from "oas/utils";
2
+ import { isRef } from "oas/types";
3
+ import OASNormalize from "oas-normalize";
4
+ import { isPlainObject, mergeDeep } from "remeda";
5
+ import swagger2openapi from "swagger2openapi";
6
+ import jsonpointer from "jsonpointer";
7
+ import BaseOas from "oas";
10
8
 
11
- // src/types.ts
12
- var HttpMethods = {
13
- GET: "get",
14
- POST: "post",
15
- PUT: "put",
16
- PATCH: "patch",
17
- DELETE: "delete",
18
- HEAD: "head",
19
- OPTIONS: "options",
20
- TRACE: "trace"
9
+ //#region src/types.ts
10
+ const HttpMethods = {
11
+ GET: "get",
12
+ POST: "post",
13
+ PUT: "put",
14
+ PATCH: "patch",
15
+ DELETE: "delete",
16
+ HEAD: "head",
17
+ OPTIONS: "options",
18
+ TRACE: "trace"
21
19
  };
20
+
21
+ //#endregion
22
+ //#region src/Oas.ts
22
23
  var Oas = class extends BaseOas {
23
- #options = {
24
- discriminator: "strict"
25
- };
26
- document = void 0;
27
- constructor({ oas, user }) {
28
- if (typeof oas === "string") {
29
- oas = JSON.parse(oas);
30
- }
31
- super(oas, user);
32
- this.document = oas;
33
- }
34
- setOptions(options) {
35
- this.#options = options;
36
- }
37
- get options() {
38
- return this.#options;
39
- }
40
- get($ref) {
41
- const origRef = $ref;
42
- $ref = $ref.trim();
43
- if ($ref === "") {
44
- return false;
45
- }
46
- if ($ref.startsWith("#")) {
47
- $ref = globalThis.decodeURIComponent($ref.substring(1));
48
- } else {
49
- return null;
50
- }
51
- const current = jsonpointer.get(this.api, $ref);
52
- if (!current) {
53
- throw new Error(`Could not find a definition for ${origRef}.`);
54
- }
55
- return current;
56
- }
57
- getKey($ref) {
58
- const key = $ref.split("/").pop();
59
- return key === "" ? void 0 : key;
60
- }
61
- set($ref, value) {
62
- $ref = $ref.trim();
63
- if ($ref === "") {
64
- return false;
65
- }
66
- if ($ref.startsWith("#")) {
67
- $ref = globalThis.decodeURIComponent($ref.substring(1));
68
- jsonpointer.set(this.api, $ref, value);
69
- }
70
- }
71
- getDiscriminator(schema) {
72
- if (!isDiscriminator(schema)) {
73
- return void 0;
74
- }
75
- const { mapping = {}, propertyName } = schema.discriminator;
76
- if (this.#options.discriminator === "inherit") {
77
- Object.entries(mapping).forEach(([mappingKey, mappingValue]) => {
78
- if (mappingValue) {
79
- const childSchema = this.get(mappingValue);
80
- if (!childSchema.properties) {
81
- childSchema.properties = {};
82
- }
83
- const property = childSchema.properties[propertyName];
84
- if (childSchema.properties) {
85
- childSchema.properties[propertyName] = {
86
- ...childSchema.properties ? childSchema.properties[propertyName] : {},
87
- enum: [...property?.enum?.filter((value) => value !== mappingKey) ?? [], mappingKey]
88
- };
89
- childSchema.required = [...childSchema.required ?? [], propertyName];
90
- this.set(mappingValue, childSchema);
91
- }
92
- }
93
- });
94
- }
95
- if (schema.oneOf) {
96
- schema.oneOf.forEach((schema2) => {
97
- if (isReference(schema2)) {
98
- const key = this.getKey(schema2.$ref);
99
- const refSchema = this.get(schema2.$ref);
100
- const propertySchema = refSchema.properties?.[propertyName];
101
- const canAdd = key && !Object.values(mapping).includes(schema2.$ref);
102
- if (canAdd && propertySchema?.enum?.length === 1) {
103
- mapping[propertySchema.enum[0]] = schema2.$ref;
104
- } else if (canAdd) {
105
- mapping[key] = schema2.$ref;
106
- }
107
- }
108
- });
109
- }
110
- if (schema.anyOf) {
111
- schema.anyOf.forEach((schema2) => {
112
- if (isReference(schema2)) {
113
- const key = this.getKey(schema2.$ref);
114
- const refSchema = this.get(schema2.$ref);
115
- const propertySchema = refSchema.properties?.[propertyName];
116
- const canAdd = key && !Object.values(mapping).includes(schema2.$ref);
117
- if (canAdd && propertySchema?.enum?.length === 1) {
118
- mapping[propertySchema.enum[0]] = schema2.$ref;
119
- } else if (canAdd) {
120
- mapping[key] = schema2.$ref;
121
- }
122
- }
123
- });
124
- }
125
- return {
126
- ...schema.discriminator,
127
- mapping
128
- };
129
- }
130
- // TODO add better typing
131
- dereferenceWithRef(schema) {
132
- if (isReference(schema)) {
133
- return {
134
- ...schema,
135
- ...this.get(schema.$ref),
136
- $ref: schema.$ref
137
- };
138
- }
139
- return schema;
140
- }
141
- /**
142
- * Oas does not have a getResponseBody(contentType)
143
- */
144
- #getResponseBodyFactory(responseBody) {
145
- function hasResponseBody(res = responseBody) {
146
- return !!res;
147
- }
148
- return (contentType) => {
149
- if (!hasResponseBody(responseBody)) {
150
- return false;
151
- }
152
- if (isReference(responseBody)) {
153
- return false;
154
- }
155
- if (!responseBody.content) {
156
- return false;
157
- }
158
- if (contentType) {
159
- if (!(contentType in responseBody.content)) {
160
- return false;
161
- }
162
- return responseBody.content[contentType];
163
- }
164
- let availablecontentType;
165
- const contentTypes = Object.keys(responseBody.content);
166
- contentTypes.forEach((mt) => {
167
- if (!availablecontentType && matchesMimeType.json(mt)) {
168
- availablecontentType = mt;
169
- }
170
- });
171
- if (!availablecontentType) {
172
- contentTypes.forEach((mt) => {
173
- if (!availablecontentType) {
174
- availablecontentType = mt;
175
- }
176
- });
177
- }
178
- if (availablecontentType) {
179
- return [availablecontentType, responseBody.content[availablecontentType], ...responseBody.description ? [responseBody.description] : []];
180
- }
181
- return false;
182
- };
183
- }
184
- getResponseSchema(operation, statusCode) {
185
- if (operation.schema.responses) {
186
- Object.keys(operation.schema.responses).forEach((key) => {
187
- const schema2 = operation.schema.responses[key];
188
- const $ref = isReference(schema2) ? schema2.$ref : void 0;
189
- if (schema2 && $ref) {
190
- operation.schema.responses[key] = this.get($ref);
191
- }
192
- });
193
- }
194
- const getResponseBody = this.#getResponseBodyFactory(operation.getResponseByStatusCode(statusCode));
195
- const { contentType } = this.#options;
196
- const responseBody = getResponseBody(contentType);
197
- if (responseBody === false) {
198
- return {};
199
- }
200
- const schema = Array.isArray(responseBody) ? responseBody[1].schema : responseBody.schema;
201
- if (!schema) {
202
- return {};
203
- }
204
- return this.dereferenceWithRef(schema);
205
- }
206
- getRequestSchema(operation) {
207
- const { contentType } = this.#options;
208
- if (operation.schema.requestBody) {
209
- operation.schema.requestBody = this.dereferenceWithRef(operation.schema.requestBody);
210
- }
211
- const requestBody = operation.getRequestBody(contentType);
212
- if (requestBody === false) {
213
- return void 0;
214
- }
215
- const schema = Array.isArray(requestBody) ? requestBody[1].schema : requestBody.schema;
216
- if (!schema) {
217
- return void 0;
218
- }
219
- return this.dereferenceWithRef(schema);
220
- }
221
- getParametersSchema(operation, inKey) {
222
- const { contentType = operation.getContentType() } = this.#options;
223
- const params = operation.getParameters().map((schema) => {
224
- return this.dereferenceWithRef(schema);
225
- }).filter((v) => v.in === inKey);
226
- if (!params.length) {
227
- return null;
228
- }
229
- return params.reduce(
230
- (schema, pathParameters) => {
231
- const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;
232
- const required = [...schema.required || [], pathParameters.required ? pathParameters.name : void 0].filter(Boolean);
233
- return {
234
- ...schema,
235
- description: schema.description,
236
- deprecated: schema.deprecated,
237
- example: schema.example,
238
- required,
239
- properties: {
240
- ...schema.properties,
241
- [pathParameters.name]: {
242
- description: pathParameters.description,
243
- ...property
244
- }
245
- }
246
- };
247
- },
248
- { type: "object", required: [], properties: {} }
249
- );
250
- }
251
- async valdiate() {
252
- const oasNormalize = new OASNormalize(this.api, {
253
- enablePaths: true,
254
- colorizeErrors: true
255
- });
256
- return oasNormalize.validate({
257
- parser: {
258
- validate: {
259
- errors: {
260
- colorize: true
261
- }
262
- }
263
- }
264
- });
265
- }
24
+ #options = { discriminator: "strict" };
25
+ document = void 0;
26
+ constructor({ oas, user }) {
27
+ if (typeof oas === "string") oas = JSON.parse(oas);
28
+ super(oas, user);
29
+ this.document = oas;
30
+ }
31
+ setOptions(options) {
32
+ this.#options = options;
33
+ }
34
+ get options() {
35
+ return this.#options;
36
+ }
37
+ get($ref) {
38
+ const origRef = $ref;
39
+ $ref = $ref.trim();
40
+ if ($ref === "") return false;
41
+ if ($ref.startsWith("#")) $ref = globalThis.decodeURIComponent($ref.substring(1));
42
+ else return null;
43
+ const current = jsonpointer.get(this.api, $ref);
44
+ if (!current) throw new Error(`Could not find a definition for ${origRef}.`);
45
+ return current;
46
+ }
47
+ getKey($ref) {
48
+ const key = $ref.split("/").pop();
49
+ return key === "" ? void 0 : key;
50
+ }
51
+ set($ref, value) {
52
+ $ref = $ref.trim();
53
+ if ($ref === "") return false;
54
+ if ($ref.startsWith("#")) {
55
+ $ref = globalThis.decodeURIComponent($ref.substring(1));
56
+ jsonpointer.set(this.api, $ref, value);
57
+ }
58
+ }
59
+ getDiscriminator(schema) {
60
+ if (!isDiscriminator(schema)) return void 0;
61
+ const { mapping = {}, propertyName } = schema.discriminator;
62
+ if (this.#options.discriminator === "inherit") Object.entries(mapping).forEach(([mappingKey, mappingValue]) => {
63
+ if (mappingValue) {
64
+ const childSchema = this.get(mappingValue);
65
+ if (!childSchema.properties) childSchema.properties = {};
66
+ const property = childSchema.properties[propertyName];
67
+ if (childSchema.properties) {
68
+ childSchema.properties[propertyName] = {
69
+ ...childSchema.properties ? childSchema.properties[propertyName] : {},
70
+ enum: [...property?.enum?.filter((value) => value !== mappingKey) ?? [], mappingKey]
71
+ };
72
+ childSchema.required = [...childSchema.required ?? [], propertyName];
73
+ this.set(mappingValue, childSchema);
74
+ }
75
+ }
76
+ });
77
+ if (schema.oneOf) schema.oneOf.forEach((schema$1) => {
78
+ if (isReference(schema$1)) {
79
+ const key = this.getKey(schema$1.$ref);
80
+ const refSchema = this.get(schema$1.$ref);
81
+ const propertySchema = refSchema.properties?.[propertyName];
82
+ const canAdd = key && !Object.values(mapping).includes(schema$1.$ref);
83
+ if (canAdd && propertySchema?.enum?.length === 1) mapping[propertySchema.enum[0]] = schema$1.$ref;
84
+ else if (canAdd) mapping[key] = schema$1.$ref;
85
+ }
86
+ });
87
+ if (schema.anyOf) schema.anyOf.forEach((schema$1) => {
88
+ if (isReference(schema$1)) {
89
+ const key = this.getKey(schema$1.$ref);
90
+ const refSchema = this.get(schema$1.$ref);
91
+ const propertySchema = refSchema.properties?.[propertyName];
92
+ const canAdd = key && !Object.values(mapping).includes(schema$1.$ref);
93
+ if (canAdd && propertySchema?.enum?.length === 1) mapping[propertySchema.enum[0]] = schema$1.$ref;
94
+ else if (canAdd) mapping[key] = schema$1.$ref;
95
+ }
96
+ });
97
+ return {
98
+ ...schema.discriminator,
99
+ mapping
100
+ };
101
+ }
102
+ dereferenceWithRef(schema) {
103
+ if (isReference(schema)) return {
104
+ ...schema,
105
+ ...this.get(schema.$ref),
106
+ $ref: schema.$ref
107
+ };
108
+ return schema;
109
+ }
110
+ /**
111
+ * Oas does not have a getResponseBody(contentType)
112
+ */
113
+ #getResponseBodyFactory(responseBody) {
114
+ function hasResponseBody(res = responseBody) {
115
+ return !!res;
116
+ }
117
+ return (contentType) => {
118
+ if (!hasResponseBody(responseBody)) return false;
119
+ if (isReference(responseBody)) return false;
120
+ if (!responseBody.content) return false;
121
+ if (contentType) {
122
+ if (!(contentType in responseBody.content)) return false;
123
+ return responseBody.content[contentType];
124
+ }
125
+ let availablecontentType;
126
+ const contentTypes = Object.keys(responseBody.content);
127
+ contentTypes.forEach((mt) => {
128
+ if (!availablecontentType && matchesMimeType$1.json(mt)) availablecontentType = mt;
129
+ });
130
+ if (!availablecontentType) contentTypes.forEach((mt) => {
131
+ if (!availablecontentType) availablecontentType = mt;
132
+ });
133
+ if (availablecontentType) return [
134
+ availablecontentType,
135
+ responseBody.content[availablecontentType],
136
+ ...responseBody.description ? [responseBody.description] : []
137
+ ];
138
+ return false;
139
+ };
140
+ }
141
+ getResponseSchema(operation, statusCode) {
142
+ if (operation.schema.responses) Object.keys(operation.schema.responses).forEach((key) => {
143
+ const schema$1 = operation.schema.responses[key];
144
+ const $ref = isReference(schema$1) ? schema$1.$ref : void 0;
145
+ if (schema$1 && $ref) operation.schema.responses[key] = this.get($ref);
146
+ });
147
+ const getResponseBody = this.#getResponseBodyFactory(operation.getResponseByStatusCode(statusCode));
148
+ const { contentType } = this.#options;
149
+ const responseBody = getResponseBody(contentType);
150
+ if (responseBody === false) return {};
151
+ const schema = Array.isArray(responseBody) ? responseBody[1].schema : responseBody.schema;
152
+ if (!schema) return {};
153
+ return this.dereferenceWithRef(schema);
154
+ }
155
+ getRequestSchema(operation) {
156
+ const { contentType } = this.#options;
157
+ if (operation.schema.requestBody) operation.schema.requestBody = this.dereferenceWithRef(operation.schema.requestBody);
158
+ const requestBody = operation.getRequestBody(contentType);
159
+ if (requestBody === false) return void 0;
160
+ const schema = Array.isArray(requestBody) ? requestBody[1].schema : requestBody.schema;
161
+ if (!schema) return void 0;
162
+ return this.dereferenceWithRef(schema);
163
+ }
164
+ getParametersSchema(operation, inKey) {
165
+ const { contentType = operation.getContentType() } = this.#options;
166
+ const params = operation.getParameters().map((schema) => {
167
+ return this.dereferenceWithRef(schema);
168
+ }).filter((v) => v.in === inKey);
169
+ if (!params.length) return null;
170
+ return params.reduce((schema, pathParameters) => {
171
+ const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;
172
+ const required = [...schema.required || [], pathParameters.required ? pathParameters.name : void 0].filter(Boolean);
173
+ return {
174
+ ...schema,
175
+ description: schema.description,
176
+ deprecated: schema.deprecated,
177
+ example: schema.example,
178
+ required,
179
+ properties: {
180
+ ...schema.properties,
181
+ [pathParameters.name]: {
182
+ description: pathParameters.description,
183
+ ...property
184
+ }
185
+ }
186
+ };
187
+ }, {
188
+ type: "object",
189
+ required: [],
190
+ properties: {}
191
+ });
192
+ }
193
+ async valdiate() {
194
+ const oasNormalize = new OASNormalize(this.api, {
195
+ enablePaths: true,
196
+ colorizeErrors: true
197
+ });
198
+ return oasNormalize.validate({ parser: { validate: { errors: { colorize: true } } } });
199
+ }
266
200
  };
267
201
 
268
- // src/utils.ts
202
+ //#endregion
203
+ //#region src/utils.ts
269
204
  function isOpenApiV2Document(doc) {
270
- return doc && isPlainObject(doc) && !("openapi" in doc);
205
+ return doc && isPlainObject(doc) && !("openapi" in doc);
271
206
  }
272
207
  function isOpenApiV3_1Document(doc) {
273
- return doc && isPlainObject(doc) && "openapi" in doc && doc.openapi.startsWith("3.1");
208
+ return doc && isPlainObject(doc) && "openapi" in doc && doc.openapi.startsWith("3.1");
274
209
  }
275
210
  function isParameterObject(obj) {
276
- return obj && "in" in obj;
211
+ return obj && "in" in obj;
277
212
  }
213
+ /**
214
+ * Determines if a schema is nullable, considering both the standard `nullable` property and the legacy `x-nullable` extension.
215
+ *
216
+ * @param schema - The schema object to check.
217
+ * @returns `true` if the schema is marked as nullable; otherwise, `false`.
218
+ */
278
219
  function isNullable(schema) {
279
- return schema?.nullable ?? schema?.["x-nullable"] ?? false;
220
+ return schema?.nullable ?? schema?.["x-nullable"] ?? false;
280
221
  }
222
+ /**
223
+ * Determines if the given object is an OpenAPI ReferenceObject.
224
+ *
225
+ * @returns True if {@link obj} is a ReferenceObject; otherwise, false.
226
+ */
281
227
  function isReference(obj) {
282
- return !!obj && isRef(obj);
228
+ return !!obj && isRef(obj);
283
229
  }
230
+ /**
231
+ * Determines if the given object is a SchemaObject with a discriminator property of type DiscriminatorObject.
232
+ *
233
+ * @returns True if {@link obj} is a SchemaObject containing a non-string {@link discriminator} property.
234
+ */
284
235
  function isDiscriminator(obj) {
285
- return !!obj && obj?.["discriminator"] && typeof obj.discriminator !== "string";
236
+ return !!obj && obj?.["discriminator"] && typeof obj.discriminator !== "string";
286
237
  }
238
+ /**
239
+ * Determines whether a schema is required.
240
+ *
241
+ * Returns true if the schema has a non-empty {@link SchemaObject.required} array or a truthy {@link SchemaObject.required} property.
242
+ *
243
+ * @param schema - The schema object to check.
244
+ * @returns True if the schema is required; otherwise, false.
245
+ */
287
246
  function isRequired(schema) {
288
- if (!schema) {
289
- return false;
290
- }
291
- return Array.isArray(schema.required) ? !!schema.required?.length : !!schema.required;
247
+ if (!schema) return false;
248
+ return Array.isArray(schema.required) ? !!schema.required?.length : !!schema.required;
292
249
  }
293
250
  function isOptional(schema) {
294
- return !isRequired(schema);
251
+ return !isRequired(schema);
295
252
  }
296
253
  async function parse(pathOrApi, { oasClass = Oas, canBundle = true, enablePaths = true } = {}) {
297
- if (typeof pathOrApi === "string" && canBundle) {
298
- const config = await loadConfig();
299
- const bundleResults = await bundle({ ref: pathOrApi, config, base: pathOrApi });
300
- return parse(bundleResults.bundle.parsed);
301
- }
302
- const oasNormalize = new OASNormalize(pathOrApi, {
303
- enablePaths,
304
- colorizeErrors: true
305
- });
306
- const document = await oasNormalize.load();
307
- if (isOpenApiV2Document(document)) {
308
- const { openapi } = await swagger2openapi.convertObj(document, {
309
- anchors: true
310
- });
311
- return new oasClass({ oas: openapi });
312
- }
313
- return new oasClass({ oas: document });
254
+ const { loadConfig, bundle } = await import("@redocly/openapi-core");
255
+ if (typeof pathOrApi === "string" && canBundle) {
256
+ const config = await loadConfig();
257
+ const bundleResults = await bundle({
258
+ ref: pathOrApi,
259
+ config,
260
+ base: pathOrApi
261
+ });
262
+ return parse(bundleResults.bundle.parsed);
263
+ }
264
+ const oasNormalize = new OASNormalize(pathOrApi, {
265
+ enablePaths,
266
+ colorizeErrors: true
267
+ });
268
+ const document = await oasNormalize.load();
269
+ if (isOpenApiV2Document(document)) {
270
+ const { openapi } = await swagger2openapi.convertObj(document, { anchors: true });
271
+ return new oasClass({ oas: openapi });
272
+ }
273
+ return new oasClass({ oas: document });
314
274
  }
315
275
  async function merge(pathOrApi, { oasClass = Oas } = {}) {
316
- const instances = await Promise.all(pathOrApi.map((p) => parse(p, { oasClass, enablePaths: false, canBundle: false })));
317
- if (instances.length === 0) {
318
- throw new Error("No OAS instances provided for merging.");
319
- }
320
- const merged = instances.reduce(
321
- (acc, current) => {
322
- return mergeDeep(acc, current.document);
323
- },
324
- {
325
- openapi: "3.0.0",
326
- info: {
327
- title: "Merged API",
328
- version: "1.0.0"
329
- },
330
- paths: {},
331
- components: {
332
- schemas: {}
333
- }
334
- }
335
- );
336
- return parse(merged, { oasClass });
276
+ const instances = await Promise.all(pathOrApi.map((p) => parse(p, {
277
+ oasClass,
278
+ enablePaths: false,
279
+ canBundle: false
280
+ })));
281
+ if (instances.length === 0) throw new Error("No OAS instances provided for merging.");
282
+ const merged = instances.reduce((acc, current) => {
283
+ return mergeDeep(acc, current.document);
284
+ }, {
285
+ openapi: "3.0.0",
286
+ info: {
287
+ title: "Merged API",
288
+ version: "1.0.0"
289
+ },
290
+ paths: {},
291
+ components: { schemas: {} }
292
+ });
293
+ return parse(merged, { oasClass });
337
294
  }
338
295
 
339
- export { HttpMethods, Oas, isDiscriminator, isNullable, isOpenApiV3_1Document, isOptional, isParameterObject, isReference, isRequired, merge, parse };
340
- //# sourceMappingURL=index.js.map
296
+ //#endregion
297
+ export { HttpMethods, Oas, findSchemaDefinition, isDiscriminator, isNullable, isOpenApiV3_1Document, isOptional, isParameterObject, isReference, isRequired, matchesMimeType, merge, parse };
341
298
  //# sourceMappingURL=index.js.map