nestjs-openapi 0.1.0 → 0.1.2
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/README.md +27 -41
- package/dist/cli.mjs +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/internal.d.mts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.mjs +1 -1
- package/dist/shared/{nestjs-openapi.B1bBy_tG.mjs → nestjs-openapi.CBj9xHZ4.mjs} +13 -6
- package/dist/shared/{nestjs-openapi.BYUrTaMo.d.mts → nestjs-openapi.OhsaHu32.d.mts} +3 -0
- package/dist/shared/{nestjs-openapi.BYUrTaMo.d.ts → nestjs-openapi.OhsaHu32.d.ts} +3 -0
- package/dist/shared/{nestjs-openapi.DlNMM8Zq.mjs → nestjs-openapi.yWMsjl_8.mjs} +82 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,35 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="docs/public/logo.png" alt="nestjs-openapi" width="120" />
|
|
3
|
+
<h1>nestjs-openapi</h1>
|
|
4
|
+
<p>Static OpenAPI generation for NestJS.<br/>Analyzes TypeScript source directly—no build step, no app bootstrap.</p>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
[](https://www.npmjs.com/package/nestjs-openapi)
|
|
7
|
+
[](LICENSE)
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
<a href="https://nestjs-openapi.vercel.app">Documentation</a> · <a href="https://nestjs-openapi.vercel.app/docs/quick-start">Quick Start</a> · <a href="https://github.com/Newbie012/nestjs-openapi/issues">Report Bug</a>
|
|
10
|
+
</div>
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
<br/>
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|---|---|---|
|
|
12
|
-
| Requires runtime execution | Yes | No |
|
|
13
|
-
| Requires app bootstrap | Yes | No |
|
|
14
|
-
| Preserves generics/unions | No | Yes |
|
|
14
|
+
## Motivation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
`@nestjs/swagger` relies on `reflect-metadata` at runtime, which only exposes basic type signatures. Unions, generics, and literal types are erased. To work around this, you duplicate type information in decorators:
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## Compatibility
|
|
18
|
+
```typescript
|
|
19
|
+
// You already have this type
|
|
20
|
+
status: 'pending' | 'shipped' | 'delivered';
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
// But you also need this decorator to make the spec accurate
|
|
23
|
+
@ApiProperty({ enum: ['pending', 'shipped', 'delivered'] })
|
|
24
|
+
status: 'pending' | 'shipped' | 'delivered';
|
|
25
|
+
```
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
When they drift apart, your spec lies about your API.
|
|
29
28
|
|
|
30
|
-
-
|
|
31
|
-
- Response shortcut decorators like `@ApiOkResponse()` are not read
|
|
32
|
-
- Controller versioning via `@Controller({ path, version })` is not supported
|
|
29
|
+
**nestjs-openapi** reads your TypeScript source directly using the AST. Your types are your spec—no duplication, no drift.
|
|
33
30
|
|
|
34
31
|
## Quick start
|
|
35
32
|
|
|
@@ -59,27 +56,16 @@ Generate:
|
|
|
59
56
|
npx nestjs-openapi generate
|
|
60
57
|
```
|
|
61
58
|
|
|
62
|
-
## Migration from @nestjs/swagger
|
|
63
|
-
|
|
64
|
-
1. Keep your controllers and route decorators as-is.
|
|
65
|
-
2. Move `DocumentBuilder` config into `openapi.config.ts`.
|
|
66
|
-
3. Replace response shortcuts with `@ApiResponse({ status: ... })`.
|
|
67
|
-
4. (Optional) Use `OpenApiModule` to serve the generated spec at runtime.
|
|
68
|
-
|
|
69
|
-
See the full guide in the docs.
|
|
70
|
-
|
|
71
59
|
## Documentation
|
|
72
60
|
|
|
73
|
-
Full documentation
|
|
61
|
+
Full documentation at **[nestjs-openapi.vercel.app](https://nestjs-openapi.vercel.app)**
|
|
74
62
|
|
|
75
|
-
- [Configuration](https://nestjs-openapi.
|
|
76
|
-
- [Security schemes](https://nestjs-openapi.
|
|
77
|
-
- [
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
80
|
-
- [
|
|
81
|
-
- [FAQ](https://nestjs-openapi.dev/docs/faq)
|
|
82
|
-
- [Decorator support](https://nestjs-openapi.dev/docs/guides/decorators)
|
|
63
|
+
- [Configuration](https://nestjs-openapi.vercel.app/docs/guides/configuration)
|
|
64
|
+
- [Security schemes](https://nestjs-openapi.vercel.app/docs/guides/security)
|
|
65
|
+
- [Serving specs at runtime](https://nestjs-openapi.vercel.app/docs/guides/serving)
|
|
66
|
+
- [Migration from @nestjs/swagger](https://nestjs-openapi.vercel.app/docs/recipes/migration)
|
|
67
|
+
- [CI/CD recipe](https://nestjs-openapi.vercel.app/docs/recipes/ci-cd)
|
|
68
|
+
- [FAQ](https://nestjs-openapi.vercel.app/docs/faq)
|
|
83
69
|
|
|
84
70
|
## Contributing
|
|
85
71
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import 'tsx';
|
|
3
|
-
import { g as generate, e as formatValidationResult } from './shared/nestjs-openapi.
|
|
3
|
+
import { g as generate, e as formatValidationResult } from './shared/nestjs-openapi.yWMsjl_8.mjs';
|
|
4
4
|
import minimist from 'minimist';
|
|
5
5
|
import { relative } from 'node:path';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
@@ -9,7 +9,7 @@ import 'node:fs';
|
|
|
9
9
|
import 'ts-morph';
|
|
10
10
|
import 'glob';
|
|
11
11
|
import 'js-yaml';
|
|
12
|
-
import './shared/nestjs-openapi.
|
|
12
|
+
import './shared/nestjs-openapi.CBj9xHZ4.mjs';
|
|
13
13
|
import 'ts-json-schema-generator';
|
|
14
14
|
import 'node:crypto';
|
|
15
15
|
import 'node:url';
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Context, Layer, Option } from 'effect';
|
|
2
|
-
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.
|
|
3
|
-
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.
|
|
2
|
+
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.OhsaHu32.mjs';
|
|
3
|
+
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.OhsaHu32.mjs';
|
|
4
4
|
import { DynamicModule } from '@nestjs/common';
|
|
5
5
|
import { Project, SourceFile, ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
|
|
6
6
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Context, Layer, Option } from 'effect';
|
|
2
|
-
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.
|
|
3
|
-
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.
|
|
2
|
+
import { C as ConfigNotFoundError, O as OpenApiGeneratorConfig, a as ConfigError, R as ResolvedConfig, P as ProjectError, b as ProjectInitError, E as EntryNotFoundError, M as MethodInfo, c as OpenApiPaths$1 } from './shared/nestjs-openapi.OhsaHu32.js';
|
|
3
|
+
export { A as AnalysisError, i as ConfigLoadError, j as ConfigValidationError, G as GenerateOptions, k as GeneratorError, H as HttpMethod, I as InvalidMethodError, e as ParameterLocation, f as ResolvedParameter, h as ReturnTypeInfo, d as generateAsync, g as generateEffect } from './shared/nestjs-openapi.OhsaHu32.js';
|
|
4
4
|
import { DynamicModule } from '@nestjs/common';
|
|
5
5
|
import { Project, SourceFile, ClassDeclaration, MethodDeclaration, Decorator, Symbol, ObjectLiteralExpression, Expression } from 'ts-morph';
|
|
6
6
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { c as categorizeBrokenRefs, d as defineConfig, f as findConfigFile, e as formatValidationResult, g as generate, b as loadAndResolveConfig, a as loadConfig, l as loadConfigFromFile, r as resolveConfig, v as validateSpec } from './shared/nestjs-openapi.
|
|
1
|
+
export { c as categorizeBrokenRefs, d as defineConfig, f as findConfigFile, e as formatValidationResult, g as generate, b as loadAndResolveConfig, a as loadConfig, l as loadConfigFromFile, r as resolveConfig, v as validateSpec } from './shared/nestjs-openapi.yWMsjl_8.mjs';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { Module } from '@nestjs/common';
|
|
5
5
|
export { generateAsync, generate as generateEffect } from './internal.mjs';
|
|
6
|
-
import { P as ProjectInitError, E as EntryNotFoundError } from './shared/nestjs-openapi.
|
|
7
|
-
export { a as ConfigLoadError, C as ConfigNotFoundError, b as ConfigValidationError, I as InvalidMethodError, c as getAllControllers, q as getArrayInitializer, o as getControllerMethodInfos, e as getControllerName, d as getControllerPrefix, j as getControllerTags, h as getDecoratorName, k as getHttpDecorator, f as getHttpMethods, m as getMethodInfo, w as getModuleDecoratorArg, z as getModuleMetadata, g as getModules, s as getStringLiteralValue, u as getSymbolFromIdentifier, l as isHttpDecorator, i as isHttpMethod, v as isModuleClass, n as normalizePath, y as resolveArrayOfClasses, x as resolveClassFromExpression, r as resolveClassFromSymbol, t as transformMethod, p as transformMethods } from './shared/nestjs-openapi.
|
|
6
|
+
import { P as ProjectInitError, E as EntryNotFoundError } from './shared/nestjs-openapi.CBj9xHZ4.mjs';
|
|
7
|
+
export { a as ConfigLoadError, C as ConfigNotFoundError, b as ConfigValidationError, I as InvalidMethodError, c as getAllControllers, q as getArrayInitializer, o as getControllerMethodInfos, e as getControllerName, d as getControllerPrefix, j as getControllerTags, h as getDecoratorName, k as getHttpDecorator, f as getHttpMethods, m as getMethodInfo, w as getModuleDecoratorArg, z as getModuleMetadata, g as getModules, s as getStringLiteralValue, u as getSymbolFromIdentifier, l as isHttpDecorator, i as isHttpMethod, v as isModuleClass, n as normalizePath, y as resolveArrayOfClasses, x as resolveClassFromExpression, r as resolveClassFromSymbol, t as transformMethod, p as transformMethods } from './shared/nestjs-openapi.CBj9xHZ4.mjs';
|
|
8
8
|
import { Context, Effect, Layer } from 'effect';
|
|
9
9
|
import { Project } from 'ts-morph';
|
|
10
10
|
import 'glob';
|
package/dist/internal.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'effect';
|
|
2
|
-
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.
|
|
2
|
+
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.OhsaHu32.mjs';
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'effect';
|
|
2
|
-
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.
|
|
2
|
+
export { G as GenerateOptions, g as generate, d as generateAsync } from './shared/nestjs-openapi.OhsaHu32.js';
|
package/dist/internal.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
import { Project } from 'ts-morph';
|
|
3
|
-
import { E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos, p as transformMethods } from './shared/nestjs-openapi.
|
|
3
|
+
import { E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos, p as transformMethods } from './shared/nestjs-openapi.CBj9xHZ4.mjs';
|
|
4
4
|
|
|
5
5
|
const generate = (options) => Effect.gen(function* () {
|
|
6
6
|
yield* Effect.logInfo("Starting OpenAPI generation").pipe(
|
|
@@ -850,7 +850,7 @@ const isExpandableType = (typeName) => {
|
|
|
850
850
|
if (BUILT_IN_TYPES.has(typeName.split("<")[0])) return false;
|
|
851
851
|
if (typeName.includes(" | ") || typeName.includes(" & ")) return false;
|
|
852
852
|
if (typeName.endsWith("[]")) return false;
|
|
853
|
-
return /^[
|
|
853
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(typeName);
|
|
854
854
|
};
|
|
855
855
|
const tsTypeToString = (typeText) => {
|
|
856
856
|
const trimmed = typeText.trim();
|
|
@@ -1306,10 +1306,16 @@ const tsTypeToOpenApiSchema = (tsType) => {
|
|
|
1306
1306
|
}
|
|
1307
1307
|
}
|
|
1308
1308
|
if (trimmed.includes(" | ")) {
|
|
1309
|
-
const
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
};
|
|
1309
|
+
const allMembers = trimmed.split(" | ").map((t) => t.trim());
|
|
1310
|
+
const hasNull = allMembers.includes("null");
|
|
1311
|
+
const types = allMembers.filter((t) => t !== "undefined" && t !== "null");
|
|
1312
|
+
if (types.length === 0) return { type: "object" };
|
|
1313
|
+
const schema = types.length === 1 ? tsTypeToOpenApiSchema(types[0]) : { oneOf: types.map((type) => tsTypeToOpenApiSchema(type)) };
|
|
1314
|
+
if (!hasNull) return schema;
|
|
1315
|
+
if (schema.$ref) {
|
|
1316
|
+
return { allOf: [{ $ref: schema.$ref }], nullable: true };
|
|
1317
|
+
}
|
|
1318
|
+
return { ...schema, nullable: true };
|
|
1313
1319
|
}
|
|
1314
1320
|
switch (trimmed.toLowerCase()) {
|
|
1315
1321
|
case "string":
|
|
@@ -1327,6 +1333,7 @@ const tsTypeToOpenApiSchema = (tsType) => {
|
|
|
1327
1333
|
return { type: "object" };
|
|
1328
1334
|
case "unknown":
|
|
1329
1335
|
case "any":
|
|
1336
|
+
case "object":
|
|
1330
1337
|
return { type: "object" };
|
|
1331
1338
|
}
|
|
1332
1339
|
if (trimmed === "StreamableFile" || trimmed === "Buffer" || trimmed === "Readable" || trimmed === "ReadableStream") {
|
|
@@ -1345,7 +1352,7 @@ const tsTypeToOpenApiSchema = (tsType) => {
|
|
|
1345
1352
|
type: "object"
|
|
1346
1353
|
};
|
|
1347
1354
|
}
|
|
1348
|
-
if (trimmed.match(/^[
|
|
1355
|
+
if (trimmed.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*(<[^>]+>)?$/)) {
|
|
1349
1356
|
return { $ref: `#/components/schemas/${trimmed}` };
|
|
1350
1357
|
}
|
|
1351
1358
|
return { type: "object" };
|
|
@@ -173,9 +173,12 @@ interface OpenApiSchema {
|
|
|
173
173
|
readonly format?: string;
|
|
174
174
|
readonly $ref?: string;
|
|
175
175
|
readonly oneOf?: readonly OpenApiSchema[];
|
|
176
|
+
readonly allOf?: readonly OpenApiSchema[];
|
|
176
177
|
readonly items?: OpenApiSchema;
|
|
177
178
|
readonly properties?: Record<string, OpenApiSchema>;
|
|
178
179
|
readonly required?: readonly string[];
|
|
180
|
+
/** OpenAPI 3.0 nullable flag */
|
|
181
|
+
readonly nullable?: boolean;
|
|
179
182
|
}
|
|
180
183
|
declare const OpenApiOperation: Schema.Struct<{
|
|
181
184
|
operationId: typeof Schema.String;
|
|
@@ -173,9 +173,12 @@ interface OpenApiSchema {
|
|
|
173
173
|
readonly format?: string;
|
|
174
174
|
readonly $ref?: string;
|
|
175
175
|
readonly oneOf?: readonly OpenApiSchema[];
|
|
176
|
+
readonly allOf?: readonly OpenApiSchema[];
|
|
176
177
|
readonly items?: OpenApiSchema;
|
|
177
178
|
readonly properties?: Record<string, OpenApiSchema>;
|
|
178
179
|
readonly required?: readonly string[];
|
|
180
|
+
/** OpenAPI 3.0 nullable flag */
|
|
181
|
+
readonly nullable?: boolean;
|
|
179
182
|
}
|
|
180
183
|
declare const OpenApiOperation: Schema.Struct<{
|
|
181
184
|
operationId: typeof Schema.String;
|
|
@@ -4,7 +4,7 @@ import { join, dirname, resolve } from 'node:path';
|
|
|
4
4
|
import { Project } from 'ts-morph';
|
|
5
5
|
import { globSync, glob } from 'glob';
|
|
6
6
|
import yaml from 'js-yaml';
|
|
7
|
-
import { C as ConfigNotFoundError, a as ConfigLoadError, b as ConfigValidationError, p as transformMethods, A as extractClassConstraints, B as getRequiredProperties, D as mergeValidationConstraints, E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos } from './nestjs-openapi.
|
|
7
|
+
import { C as ConfigNotFoundError, a as ConfigLoadError, b as ConfigValidationError, p as transformMethods, A as extractClassConstraints, B as getRequiredProperties, D as mergeValidationConstraints, E as EntryNotFoundError, g as getModules, o as getControllerMethodInfos } from './nestjs-openapi.CBj9xHZ4.mjs';
|
|
8
8
|
import { createGenerator } from 'ts-json-schema-generator';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
10
|
import { pathToFileURL } from 'node:url';
|
|
@@ -466,6 +466,12 @@ const extractReferencedSchemas = (paths) => {
|
|
|
466
466
|
if (schema.oneOf) {
|
|
467
467
|
schema.oneOf.forEach(extractFromSchema);
|
|
468
468
|
}
|
|
469
|
+
if (schema.allOf) {
|
|
470
|
+
schema.allOf.forEach(extractFromSchema);
|
|
471
|
+
}
|
|
472
|
+
if (schema.anyOf) {
|
|
473
|
+
schema.anyOf.forEach(extractFromSchema);
|
|
474
|
+
}
|
|
469
475
|
if (schema.properties) {
|
|
470
476
|
Object.values(schema.properties).forEach(extractFromSchema);
|
|
471
477
|
}
|
|
@@ -529,7 +535,14 @@ const extractNestedReferences = (schemas, knownSchemas) => {
|
|
|
529
535
|
};
|
|
530
536
|
const convertToOpenApiSchema = (schema) => {
|
|
531
537
|
const result = {};
|
|
532
|
-
if (schema.type)
|
|
538
|
+
if (Array.isArray(schema.type)) {
|
|
539
|
+
const nonNull = schema.type.filter((t) => t !== "null");
|
|
540
|
+
const isNullable = nonNull.length < schema.type.length;
|
|
541
|
+
result["type"] = nonNull.length === 1 ? nonNull[0] : schema.type;
|
|
542
|
+
if (isNullable && nonNull.length === 1) result["nullable"] = true;
|
|
543
|
+
} else if (schema.type) {
|
|
544
|
+
result["type"] = schema.type;
|
|
545
|
+
}
|
|
533
546
|
if (schema.format) result["format"] = schema.format;
|
|
534
547
|
if (schema.$ref) {
|
|
535
548
|
result["$ref"] = schema.$ref.replace(
|
|
@@ -700,14 +713,81 @@ const transformSchemasForVersion = (schemas, version) => {
|
|
|
700
713
|
])
|
|
701
714
|
);
|
|
702
715
|
};
|
|
716
|
+
const transformOperationToV31 = (operation) => {
|
|
717
|
+
const parameters = operation.parameters?.map((param) => ({
|
|
718
|
+
...param,
|
|
719
|
+
schema: transformSchemaToV31(param.schema)
|
|
720
|
+
}));
|
|
721
|
+
const requestBody = operation.requestBody ? {
|
|
722
|
+
...operation.requestBody,
|
|
723
|
+
content: Object.fromEntries(
|
|
724
|
+
Object.entries(operation.requestBody.content).map(
|
|
725
|
+
([contentType, mediaType]) => [
|
|
726
|
+
contentType,
|
|
727
|
+
{ ...mediaType, schema: transformSchemaToV31(mediaType.schema) }
|
|
728
|
+
]
|
|
729
|
+
)
|
|
730
|
+
)
|
|
731
|
+
} : void 0;
|
|
732
|
+
const responses = Object.fromEntries(
|
|
733
|
+
Object.entries(operation.responses).map(([code, response]) => [
|
|
734
|
+
code,
|
|
735
|
+
response.content ? {
|
|
736
|
+
...response,
|
|
737
|
+
content: Object.fromEntries(
|
|
738
|
+
Object.entries(response.content).map(
|
|
739
|
+
([contentType, mediaType]) => [
|
|
740
|
+
contentType,
|
|
741
|
+
{
|
|
742
|
+
...mediaType,
|
|
743
|
+
schema: transformSchemaToV31(mediaType.schema)
|
|
744
|
+
}
|
|
745
|
+
]
|
|
746
|
+
)
|
|
747
|
+
)
|
|
748
|
+
} : response
|
|
749
|
+
])
|
|
750
|
+
);
|
|
751
|
+
return {
|
|
752
|
+
...operation,
|
|
753
|
+
...parameters && { parameters },
|
|
754
|
+
...requestBody && { requestBody },
|
|
755
|
+
responses
|
|
756
|
+
};
|
|
757
|
+
};
|
|
758
|
+
const HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
759
|
+
"get",
|
|
760
|
+
"put",
|
|
761
|
+
"post",
|
|
762
|
+
"delete",
|
|
763
|
+
"options",
|
|
764
|
+
"head",
|
|
765
|
+
"patch",
|
|
766
|
+
"trace"
|
|
767
|
+
]);
|
|
768
|
+
const transformPathsForVersion = (paths, version) => {
|
|
769
|
+
if (version === "3.0.3") return paths;
|
|
770
|
+
return Object.fromEntries(
|
|
771
|
+
Object.entries(paths).map(([path, pathItem]) => [
|
|
772
|
+
path,
|
|
773
|
+
Object.fromEntries(
|
|
774
|
+
Object.entries(pathItem).map(
|
|
775
|
+
([key, value]) => HTTP_METHODS.has(key) ? [key, transformOperationToV31(value)] : [key, value]
|
|
776
|
+
)
|
|
777
|
+
)
|
|
778
|
+
])
|
|
779
|
+
);
|
|
780
|
+
};
|
|
703
781
|
const transformSpecForVersion = (spec, version) => {
|
|
704
782
|
if (version === "3.0.3") {
|
|
705
783
|
return { ...spec, openapi: version };
|
|
706
784
|
}
|
|
707
785
|
const transformedSchemas = spec.components?.schemas ? transformSchemasForVersion(spec.components.schemas, version) : void 0;
|
|
786
|
+
const transformedPaths = transformPathsForVersion(spec.paths, version);
|
|
708
787
|
return {
|
|
709
788
|
...spec,
|
|
710
789
|
openapi: version,
|
|
790
|
+
paths: transformedPaths,
|
|
711
791
|
...transformedSchemas && {
|
|
712
792
|
components: {
|
|
713
793
|
...spec.components,
|
package/package.json
CHANGED