nestjs-openapi-next 1.0.0 → 1.0.1

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.
Files changed (35) hide show
  1. package/.idea/codeStyles/Project.xml +70 -0
  2. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  3. package/.idea/compiler.xml +6 -0
  4. package/.idea/copilot.data.migration.agent.xml +6 -0
  5. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  6. package/.idea/copilot.data.migration.edit.xml +6 -0
  7. package/.idea/easycode.ignore +13 -0
  8. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  9. package/.idea/modules.xml +8 -0
  10. package/.idea/nestjs-openapi-next.iml +8 -0
  11. package/.idea/prettier.xml +6 -0
  12. package/.idea/vcs.xml +6 -0
  13. package/README.md +112 -88
  14. package/dist/constants.d.ts +1 -0
  15. package/dist/constants.js +1 -0
  16. package/dist/decorators/api-tag-group.decorator.d.ts +8 -4
  17. package/dist/decorators/api-tag-group.decorator.js +5 -1
  18. package/dist/decorators/api-webhook.decorator.d.ts +1 -0
  19. package/dist/decorators/api-webhook.decorator.js +8 -0
  20. package/dist/decorators/index.d.ts +1 -0
  21. package/dist/decorators/index.js +1 -0
  22. package/dist/document-builder.d.ts +2 -0
  23. package/dist/document-builder.js +12 -1
  24. package/dist/extra/swagger-shim.d.ts +2 -0
  25. package/dist/extra/swagger-shim.js +8 -0
  26. package/dist/interfaces/denormalized-doc.interface.d.ts +2 -0
  27. package/dist/interfaces/open-api-spec.interface.d.ts +8 -0
  28. package/dist/swagger-explorer.js +8 -1
  29. package/dist/swagger-module.d.ts +2 -0
  30. package/dist/swagger-module.js +67 -7
  31. package/dist/swagger-scanner.js +8 -1
  32. package/dist/swagger-transformer.d.ts +1 -1
  33. package/dist/swagger-transformer.js +13 -5
  34. package/package.json +4 -4
  35. package/bun.lock +0 -2154
@@ -0,0 +1,70 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <code_scheme name="Project" version="173">
3
+ <HTMLCodeStyleSettings>
4
+ <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
5
+ </HTMLCodeStyleSettings>
6
+ <JSCodeStyleSettings version="0">
7
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
8
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
9
+ <option name="FORCE_QUOTE_STYlE" value="true" />
10
+ <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
11
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
12
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
13
+ </JSCodeStyleSettings>
14
+ <JetCodeStyleSettings>
15
+ <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
16
+ </JetCodeStyleSettings>
17
+ <TypeScriptCodeStyleSettings version="0">
18
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
19
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
20
+ <option name="FORCE_QUOTE_STYlE" value="true" />
21
+ <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
22
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
23
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
24
+ </TypeScriptCodeStyleSettings>
25
+ <VueCodeStyleSettings>
26
+ <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
27
+ <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
28
+ </VueCodeStyleSettings>
29
+ <codeStyleSettings language="HTML">
30
+ <option name="SOFT_MARGINS" value="80" />
31
+ <indentOptions>
32
+ <option name="INDENT_SIZE" value="2" />
33
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
34
+ <option name="TAB_SIZE" value="2" />
35
+ </indentOptions>
36
+ </codeStyleSettings>
37
+ <codeStyleSettings language="JAVA">
38
+ <indentOptions>
39
+ <option name="USE_TAB_CHARACTER" value="true" />
40
+ <option name="SMART_TABS" value="true" />
41
+ </indentOptions>
42
+ </codeStyleSettings>
43
+ <codeStyleSettings language="JavaScript">
44
+ <option name="SOFT_MARGINS" value="80" />
45
+ <indentOptions>
46
+ <option name="INDENT_SIZE" value="2" />
47
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
48
+ <option name="TAB_SIZE" value="2" />
49
+ </indentOptions>
50
+ </codeStyleSettings>
51
+ <codeStyleSettings language="TypeScript">
52
+ <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
53
+ <option name="SOFT_MARGINS" value="80" />
54
+ <indentOptions>
55
+ <option name="INDENT_SIZE" value="2" />
56
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
57
+ <option name="TAB_SIZE" value="2" />
58
+ </indentOptions>
59
+ </codeStyleSettings>
60
+ <codeStyleSettings language="Vue">
61
+ <option name="SOFT_MARGINS" value="80" />
62
+ <indentOptions>
63
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
64
+ </indentOptions>
65
+ </codeStyleSettings>
66
+ <codeStyleSettings language="kotlin">
67
+ <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
68
+ </codeStyleSettings>
69
+ </code_scheme>
70
+ </component>
@@ -0,0 +1,5 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
4
+ </state>
5
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="TypeScriptCompiler">
4
+ <option name="useServicePoweredTypesEnabledManually" value="true" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AgentMigrationStateService">
4
+ <option name="migrationStatus" value="COMPLETED" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Ask2AgentMigrationStateService">
4
+ <option name="migrationStatus" value="COMPLETED" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="EditMigrationStateService">
4
+ <option name="migrationStatus" value="COMPLETED" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,13 @@
1
+ .idea
2
+ .vscode
3
+ node_modules/
4
+ dist/
5
+ vendor/
6
+ cache/
7
+ .*/
8
+ *.min.*
9
+ *.test.*
10
+ *.spec.*
11
+ *.bundle.*
12
+ *.bundle-min.*
13
+ *.log
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/nestjs-openapi-next.iml" filepath="$PROJECT_DIR$/.idea/nestjs-openapi-next.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="inheritedJdk" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ </component>
8
+ </module>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PrettierConfiguration">
4
+ <option name="myConfigurationMode" value="AUTOMATIC" />
5
+ </component>
6
+ </project>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
package/README.md CHANGED
@@ -1,39 +1,32 @@
1
1
  # nestjs-openapi-next
2
2
 
3
- This repository is a fork of `@nestjs/swagger` (upstream: `nestjs/swagger`).
4
-
5
- Its goal is to add first-class support for key **OpenAPI 3.2** features (see PR #1), while keeping compatibility with existing `@nestjs/swagger` usage as much as possible.
6
-
7
- > Note: `package.json` currently still uses the package name `@nestjs/swagger`. If your project also depends on the upstream package, use lockfiles / overrides / resolutions to avoid dependency conflicts.
8
-
9
- ## What this fork adds (PR #1)
10
-
11
- - **HTTP `QUERY` method (OAS 3.2)**
12
- - `@ApiQueryMethod()` to explicitly emit an OpenAPI `query` operation.
13
- - **Enhanced Tags (OAS 3.2)**
14
- - `@ApiTagGroup()` to define tag metadata including `parent` and `kind`, merged into top-level `document.tags`.
15
- - `DocumentBuilder.addTag()` supports an additional `summary` field.
16
- - **Streaming responses (OAS 3.2)**
17
- - `@ApiStreamingResponse()` to emit per-item schema via `itemSchema` (e.g. SSE `text/event-stream`).
18
- - **OAuth 2.0 Device Authorization Flow (OAS 3.2 / RFC 8628)**
19
- - OpenAPI typings include `flows.deviceAuthorization`.
20
- - `@ApiSecurityDeviceFlow()` convenience decorator for security requirements.
3
+ `nestjs-openapi-next` is a fork of `@nestjs/swagger` (upstream: `nestjs/swagger`).
4
+ The goal is to keep upstream behavior as compatible as possible while adding a set of **OpenAPI 3.2** features and widely-used **OpenAPI extension fields** (`x-`) that are commonly consumed by tools like Redoc.
5
+
6
+ ## Key differences from upstream
7
+
8
+ - **Richer OpenAPI 3.2 typings**
9
+ - e.g. `TagObject.summary`, `OAuthFlowsObject.deviceAuthorization`, etc.
10
+ - **Enhanced tag support**
11
+ - `@ApiTag(options)` (class/controller-level): defines tag metadata (`summary`, `x-displayName`, `description`, `parent`, `kind`, ...) and merges it into the top-level `document.tags`.
12
+ - `x-displayName` support for tags, mirrored with `summary` (setting either results in both fields being written with the same value).
13
+ - Root-level `x-tagGroups` support (commonly used by Redoc). If you use `parent` to form relationships, `x-tagGroups` is auto-derived; you can also set it explicitly via `DocumentBuilder`.
14
+ - **Additional OAS 3.2 behaviors**
15
+ - HTTP `QUERY` method via `@ApiQueryMethod()` (emits `paths['/x'].query`).
16
+ - Streaming responses via `@ApiStreamingResponse()` (`itemSchema`, e.g. SSE `text/event-stream`).
17
+ - OAuth2 Device Authorization Flow typing + `@ApiSecurityDeviceFlow()` helper.
18
+ - **Convenience APIs**
19
+ - `DocumentBuilder.addServerWithName()` for a non-standard-but-common `server.name`.
21
20
 
22
21
  Test coverage: `test/openapi-3-2.spec.ts`.
23
22
 
24
23
  ## Compatibility
25
24
 
26
25
  - **NestJS**: peerDependencies target `@nestjs/common` / `@nestjs/core` `^11.0.1`
27
- - **Runtime deps**: generally aligned with `@nestjs/swagger` (e.g. `reflect-metadata`, optional `class-validator` / `class-transformer`, etc.)
26
+ - **Runtime deps**: aligned with upstream `@nestjs/swagger` (`reflect-metadata`, optional `class-validator` / `class-transformer`, etc.)
28
27
 
29
28
  ## Installation
30
29
 
31
- ### Install from this fork (recommended for OAS 3.2 extensions)
32
-
33
- ```bash
34
- npm i --save github:undownding/nestjs-openapi-next
35
- ```
36
-
37
30
  ### Install from npm
38
31
 
39
32
  ```bash
@@ -44,98 +37,121 @@ npm i --save nestjs-openapi-next
44
37
 
45
38
  See the official Nest OpenAPI tutorial: `https://docs.nestjs.com/openapi/introduction`
46
39
 
47
- Typical setup (minimal skeleton):
48
-
49
40
  ```ts
50
41
  import { NestFactory } from '@nestjs/core';
51
- import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
42
+ import { DocumentBuilder, SwaggerModule } from 'nestjs-openapi-next';
52
43
 
53
- // ...
54
44
  const app = await NestFactory.create(AppModule);
55
45
 
56
46
  const config = new DocumentBuilder()
57
47
  .setTitle('Example')
58
48
  .setDescription('API description')
59
49
  .setVersion('1.0')
60
- // If you want to declare OAS 3.2 in the document, set it explicitly:
50
+ // If you want the document to declare OAS 3.2, set it explicitly:
61
51
  .setOpenAPIVersion('3.2.0')
62
52
  .build();
63
53
 
64
54
  const document = SwaggerModule.createDocument(app, config);
65
55
  SwaggerModule.setup('api', app, document);
66
-
67
- await app.listen(3000);
68
56
  ```
69
57
 
70
- ## OpenAPI 3.2 extensions
58
+ ## Usage
71
59
 
72
- ### 1) HTTP QUERY method: `@ApiQueryMethod()`
60
+ ### 1) `@ApiTag(options)` (recommended) and deprecation of `@ApiTagGroup()`
73
61
 
74
- OAS 3.2 supports a `query` operation under `paths`. This decorator makes a Nest handler emit a `query` operation **in the generated OpenAPI document**.
62
+ `@ApiTag(options)` is the primary decorator for defining tag metadata at the controller level.
63
+
64
+ `@ApiTagGroup(options)` is kept as a backward-compatible alias, but is **deprecated** and may be removed in a future major version.
75
65
 
76
66
  ```ts
77
- import { Controller, Post } from '@nestjs/common';
78
- import { ApiQueryMethod } from '@nestjs/swagger';
67
+ import { Controller, Get } from '@nestjs/common';
68
+ import { ApiTag } from 'nestjs-openapi-next';
79
69
 
80
- @Controller()
81
- export class QueryController {
82
- @Post('search')
83
- @ApiQueryMethod()
84
- search() {
85
- return { ok: true };
70
+ @ApiTag({
71
+ name: 'Customers',
72
+ summary: 'Customers'
73
+ // you may also set: 'x-displayName': 'Customers'
74
+ })
75
+ @Controller('customers')
76
+ export class CustomersController {
77
+ @Get()
78
+ list() {
79
+ return [];
86
80
  }
87
81
  }
88
82
  ```
89
83
 
90
- - Output: `document.paths['/search'].query` is defined (and `post` is not emitted for that handler).
91
- - Important: this does **not** change Nest routing at runtime — it only affects the generated OpenAPI document.
84
+ ### 2) Tag `x-displayName` (mirrored with `summary`)
85
+
86
+ This fork treats tag `summary` and `x-displayName` as equivalent display fields:
92
87
 
93
- ### 2) Enhanced Tags: `@ApiTagGroup()`
88
+ - set either one;
89
+ - the generated `document.tags` will contain **both** `summary` and `x-displayName` with the same value.
94
90
 
95
- OAS 3.2 Enhanced Tags allow nesting and classification via `parent` and `kind`.
91
+ ### 3) Root-level `x-tagGroups` (tag grouping)
92
+
93
+ #### Auto-derived (recommended)
94
+
95
+ If you use tag `parent` relationships (via `@ApiTag()`), the root-level `x-tagGroups` will be derived automatically:
96
96
 
97
97
  ```ts
98
- import { Controller, Get } from '@nestjs/common';
99
- import { ApiTagGroup } from '@nestjs/swagger';
100
-
101
- @ApiTagGroup({
102
- name: 'Cats',
103
- summary: 'Cats',
104
- description: 'Cat operations',
105
- parent: 'Admin',
106
- kind: 'nav'
107
- })
108
- @Controller('cats')
109
- export class CatsController {
110
- @Get()
111
- list() {
112
- return [];
113
- }
114
- }
98
+ @ApiTag({ name: 'Customers' })
99
+ @Controller('customers')
100
+ export class CustomersController {}
101
+
102
+ @ApiTag({ name: 'Customer Authentication', parent: 'Customers' })
103
+ @Controller('auth')
104
+ export class AuthController {}
105
+ ```
106
+
107
+ Illustrative output:
108
+
109
+ ```yaml
110
+ tags:
111
+ - name: Customers
112
+ - name: Customer Authentication
113
+ x-tagGroups:
114
+ - name: Customers
115
+ tags:
116
+ - Customers
117
+ - Customer Authentication
115
118
  ```
116
119
 
117
- - `@ApiTagGroup()` also ensures operations are tagged (internally it behaves like applying `@ApiTags(name)`).
118
- - During scanning, tag group metadata is merged into top-level `document.tags` and then merged with tags coming from `DocumentBuilder`.
120
+ #### Manual configuration
119
121
 
120
- #### `DocumentBuilder.addTag()` supports `summary`
122
+ You can also set `x-tagGroups` explicitly via `DocumentBuilder.addTagGroup()`:
121
123
 
122
124
  ```ts
123
- new DocumentBuilder()
124
- .addTag('Cats', 'Cat operations', undefined, 'Cats')
125
+ const config = new DocumentBuilder()
126
+ .setTitle('t')
127
+ .setVersion('1')
128
+ .addTag('Customers')
129
+ .addTag('Customer Authentication')
130
+ .addTagGroup('Customers', ['Customers', 'Customer Authentication'])
125
131
  .build();
126
132
  ```
127
133
 
128
- Signature (adds the 4th argument compared to upstream):
134
+ ### 4) HTTP `QUERY` method: `@ApiQueryMethod()`
129
135
 
130
- - `addTag(name, description?, externalDocs?, summary?)`
136
+ ```ts
137
+ import { Controller, Post } from '@nestjs/common';
138
+ import { ApiQueryMethod } from 'nestjs-openapi-next';
131
139
 
132
- ### 3) Streaming responses: `@ApiStreamingResponse()` (`itemSchema`)
140
+ @Controller()
141
+ export class QueryController {
142
+ @Post('search')
143
+ @ApiQueryMethod()
144
+ search() {
145
+ return { ok: true };
146
+ }
147
+ }
148
+ ```
133
149
 
134
- For streaming responses (e.g. SSE), OAS 3.2 supports describing each streamed item via `itemSchema` under the media type.
150
+ ### 5) Streaming responses: `@ApiStreamingResponse()` (`itemSchema`)
135
151
 
136
152
  ```ts
137
153
  import { Controller, Get } from '@nestjs/common';
138
- import { ApiProperty, ApiStreamingResponse } from '@nestjs/swagger';
154
+ import { ApiProperty, ApiStreamingResponse } from 'nestjs-openapi-next';
139
155
 
140
156
  class SseItemDto {
141
157
  @ApiProperty()
@@ -156,17 +172,11 @@ export class EventsController {
156
172
  }
157
173
  ```
158
174
 
159
- Result (illustrative):
160
-
161
- - `responses['200'].content['text/event-stream'].itemSchema` -> `#/components/schemas/SseItemDto`
162
-
163
- ### 4) OAuth2 Device Authorization Flow: `flows.deviceAuthorization` + `@ApiSecurityDeviceFlow()`
164
-
165
- Define the OAuth2 scheme (with `flows.deviceAuthorization`) via `DocumentBuilder.addOAuth2()`, then declare per-operation requirements with the decorator.
175
+ ### 6) OAuth2 Device Authorization Flow: `flows.deviceAuthorization` + `@ApiSecurityDeviceFlow()`
166
176
 
167
177
  ```ts
168
178
  import { Controller, Get } from '@nestjs/common';
169
- import { ApiSecurityDeviceFlow, DocumentBuilder } from '@nestjs/swagger';
179
+ import { ApiSecurityDeviceFlow, DocumentBuilder } from 'nestjs-openapi-next';
170
180
 
171
181
  @Controller()
172
182
  export class SecuredController {
@@ -196,15 +206,29 @@ const config = new DocumentBuilder()
196
206
  .build();
197
207
  ```
198
208
 
199
- Notes:
209
+ ### 7) OpenAPI 3.1 Webhooks: `@ApiWebhook()`
200
210
 
201
- - `@ApiSecurityDeviceFlow()` is a convenience wrapper around `@ApiSecurity(name, scopes)` for requirements.
202
- - The device flow scheme definition still comes from `addOAuth2({ flows: { deviceAuthorization: ... } })`.
211
+ OpenAPI 3.1 introduces a root-level `webhooks` object for out-of-band callbacks
212
+ initiated by the API provider.
203
213
 
204
- ## Upstream relationship / migration notes
214
+ This fork supports emitting webhook operations via a decorator:
215
+
216
+ ```ts
217
+ import { Controller, Post } from '@nestjs/common';
218
+ import { ApiWebhook } from '@nestjs/swagger';
219
+
220
+ @Controller()
221
+ export class StripeWebhooksController {
222
+ @Post('stripe')
223
+ @ApiWebhook('stripeEvent')
224
+ stripe() {
225
+ return { ok: true };
226
+ }
227
+ }
228
+ ```
205
229
 
206
- - The OAS 3.2 support in PR #1 is implemented as an additive extension to minimize breaking changes.
207
- - If you don’t use the new decorators/fields, behavior should be broadly compatible with upstream `@nestjs/swagger`.
230
+ The generated document will contain `document.webhooks.stripeEvent.post`, and the
231
+ corresponding route will **not** be emitted under `document.paths`.
208
232
 
209
233
  ## License
210
234
 
@@ -7,6 +7,7 @@ export declare const DECORATORS: {
7
7
  API_TAGS: string;
8
8
  API_TAG_GROUP: string;
9
9
  API_QUERY_METHOD: string;
10
+ API_WEBHOOK: string;
10
11
  API_CALLBACKS: string;
11
12
  API_PARAMETERS: string;
12
13
  API_HEADERS: string;
package/dist/constants.js CHANGED
@@ -10,6 +10,7 @@ exports.DECORATORS = {
10
10
  API_TAGS: `${exports.DECORATORS_PREFIX}/apiUseTags`,
11
11
  API_TAG_GROUP: `${exports.DECORATORS_PREFIX}/apiTagGroup`,
12
12
  API_QUERY_METHOD: `${exports.DECORATORS_PREFIX}/apiQueryMethod`,
13
+ API_WEBHOOK: `${exports.DECORATORS_PREFIX}/apiWebhook`,
13
14
  API_CALLBACKS: `${exports.DECORATORS_PREFIX}/apiCallbacks`,
14
15
  API_PARAMETERS: `${exports.DECORATORS_PREFIX}/apiParameters`,
15
16
  API_HEADERS: `${exports.DECORATORS_PREFIX}/apiHeaders`,
@@ -1,11 +1,15 @@
1
1
  import { TagObject } from '../interfaces/open-api-spec.interface';
2
- export type ApiTagGroupKind = 'audience' | 'badge' | 'nav' | (string & {});
3
- export interface ApiTagGroupOptions extends Pick<TagObject, 'name' | 'summary' | 'description' | 'externalDocs' | 'parent' | 'kind'> {
2
+ export type ApiTagKind = 'audience' | 'badge' | 'nav' | (string & {});
3
+ export type ApiTagGroupKind = ApiTagKind;
4
+ export interface ApiTagOptions extends Pick<TagObject, 'name' | 'summary' | 'x-displayName' | 'description' | 'externalDocs' | 'parent' | 'kind'> {
4
5
  name: string;
5
6
  summary?: string;
7
+ 'x-displayName'?: string;
6
8
  description?: string;
7
9
  externalDocs?: TagObject['externalDocs'];
8
10
  parent?: string;
9
- kind?: ApiTagGroupKind;
11
+ kind?: ApiTagKind;
10
12
  }
11
- export declare function ApiTagGroup(options: ApiTagGroupOptions): ClassDecorator;
13
+ export declare function ApiTag(options: ApiTagOptions): ClassDecorator;
14
+ export declare function ApiTagGroup(options: ApiTagOptions): ClassDecorator;
15
+ export type ApiTagGroupOptions = ApiTagOptions;
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiTag = ApiTag;
3
4
  exports.ApiTagGroup = ApiTagGroup;
4
5
  const constants_1 = require("../constants");
5
6
  const api_use_tags_decorator_1 = require("./api-use-tags.decorator");
6
- function ApiTagGroup(options) {
7
+ function ApiTag(options) {
7
8
  return (target) => {
8
9
  const previous = Reflect.getMetadata(constants_1.DECORATORS.API_TAG_GROUP, target) || [];
9
10
  Reflect.defineMetadata(constants_1.DECORATORS.API_TAG_GROUP, [...previous, options], target);
@@ -11,3 +12,6 @@ function ApiTagGroup(options) {
11
12
  return target;
12
13
  };
13
14
  }
15
+ function ApiTagGroup(options) {
16
+ return ApiTag(options);
17
+ }
@@ -0,0 +1 @@
1
+ export declare function ApiWebhook(name?: string): MethodDecorator;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiWebhook = ApiWebhook;
4
+ const constants_1 = require("../constants");
5
+ const helpers_1 = require("./helpers");
6
+ function ApiWebhook(name) {
7
+ return (0, helpers_1.createMethodDecorator)(constants_1.DECORATORS.API_WEBHOOK, name !== null && name !== void 0 ? name : true);
8
+ }
@@ -17,6 +17,7 @@ export * from './api-produces.decorator';
17
17
  export { ApiProperty, ApiPropertyOptional, ApiPropertyOptions, ApiResponseProperty } from './api-property.decorator';
18
18
  export * from './api-query.decorator';
19
19
  export * from './api-query-method.decorator';
20
+ export * from './api-webhook.decorator';
20
21
  export * from './api-response.decorator';
21
22
  export * from './api-streaming-response.decorator';
22
23
  export * from './api-security.decorator';
@@ -37,6 +37,7 @@ Object.defineProperty(exports, "ApiPropertyOptional", { enumerable: true, get: f
37
37
  Object.defineProperty(exports, "ApiResponseProperty", { enumerable: true, get: function () { return api_property_decorator_1.ApiResponseProperty; } });
38
38
  __exportStar(require("./api-query.decorator"), exports);
39
39
  __exportStar(require("./api-query-method.decorator"), exports);
40
+ __exportStar(require("./api-webhook.decorator"), exports);
40
41
  __exportStar(require("./api-response.decorator"), exports);
41
42
  __exportStar(require("./api-streaming-response.decorator"), exports);
42
43
  __exportStar(require("./api-security.decorator"), exports);
@@ -12,9 +12,11 @@ export declare class DocumentBuilder {
12
12
  setLicense(name: string, url: string): this;
13
13
  setOpenAPIVersion(version: string): this;
14
14
  addServer(url: string, description?: string, variables?: Record<string, ServerVariableObject>): this;
15
+ addServerWithName(name: string, url: string, description?: string, variables?: Record<string, ServerVariableObject>): this;
15
16
  setExternalDoc(description: string, url: string): this;
16
17
  setBasePath(path: string): this;
17
18
  addTag(name: string, description?: string, externalDocs?: ExternalDocumentationObject, summary?: string): this;
19
+ addTagGroup(name: string, tags: string[]): this;
18
20
  addExtension(extensionKey: string, extensionProperties: any, location?: ExtensionLocation): this;
19
21
  addSecurity(name: string, options: SecuritySchemeObject): this;
20
22
  addGlobalResponse(...respones: ApiResponseOptions[]): this;
@@ -48,6 +48,10 @@ class DocumentBuilder {
48
48
  this.document.servers.push({ url, description, variables });
49
49
  return this;
50
50
  }
51
+ addServerWithName(name, url, description, variables) {
52
+ this.document.servers.push({ name, url, description, variables });
53
+ return this;
54
+ }
51
55
  setExternalDoc(description, url) {
52
56
  this.document.externalDocs = { description, url };
53
57
  return this;
@@ -57,14 +61,21 @@ class DocumentBuilder {
57
61
  return this;
58
62
  }
59
63
  addTag(name, description = '', externalDocs, summary) {
64
+ const normalizedSummary = summary;
60
65
  this.document.tags = this.document.tags.concat((0, lodash_1.pickBy)({
61
66
  name,
62
- summary,
67
+ summary: normalizedSummary,
68
+ 'x-displayName': normalizedSummary,
63
69
  description,
64
70
  externalDocs
65
71
  }, (0, lodash_1.negate)(lodash_1.isUndefined)));
66
72
  return this;
67
73
  }
74
+ addTagGroup(name, tags) {
75
+ const existing = this.document['x-tagGroups'] || [];
76
+ this.document['x-tagGroups'] = existing.concat({ name, tags });
77
+ return this;
78
+ }
68
79
  addExtension(extensionKey, extensionProperties, location = 'root') {
69
80
  if (!extensionKey.startsWith('x-')) {
70
81
  throw new Error('Extension key is not prefixed. Please ensure you prefix it with `x-`.');
@@ -71,9 +71,11 @@ export declare function ApiSchema(): () => void;
71
71
  export declare function ApiSecurity(): () => void;
72
72
  export declare function ApiSecurityDeviceFlow(): () => void;
73
73
  export declare function ApiTags(): () => void;
74
+ export declare function ApiTag(): () => void;
74
75
  export declare function ApiTagGroup(): () => void;
75
76
  export declare function ApiCallbacks(): () => void;
76
77
  export declare function ApiQueryMethod(): () => void;
78
+ export declare function ApiWebhook(): () => void;
77
79
  export declare function ApiStreamingResponse(): () => void;
78
80
  export declare function ApiLink(): () => void;
79
81
  export declare function ApiDefaultGetter(): () => void;
@@ -73,9 +73,11 @@ exports.ApiSchema = ApiSchema;
73
73
  exports.ApiSecurity = ApiSecurity;
74
74
  exports.ApiSecurityDeviceFlow = ApiSecurityDeviceFlow;
75
75
  exports.ApiTags = ApiTags;
76
+ exports.ApiTag = ApiTag;
76
77
  exports.ApiTagGroup = ApiTagGroup;
77
78
  exports.ApiCallbacks = ApiCallbacks;
78
79
  exports.ApiQueryMethod = ApiQueryMethod;
80
+ exports.ApiWebhook = ApiWebhook;
79
81
  exports.ApiStreamingResponse = ApiStreamingResponse;
80
82
  exports.ApiLink = ApiLink;
81
83
  exports.ApiDefaultGetter = ApiDefaultGetter;
@@ -309,6 +311,9 @@ function ApiSecurityDeviceFlow() {
309
311
  function ApiTags() {
310
312
  return () => { };
311
313
  }
314
+ function ApiTag() {
315
+ return () => { };
316
+ }
312
317
  function ApiTagGroup() {
313
318
  return () => { };
314
319
  }
@@ -318,6 +323,9 @@ function ApiCallbacks() {
318
323
  function ApiQueryMethod() {
319
324
  return () => { };
320
325
  }
326
+ function ApiWebhook() {
327
+ return () => { };
328
+ }
321
329
  function ApiStreamingResponse() {
322
330
  return () => { };
323
331
  }
@@ -3,6 +3,8 @@ export interface DenormalizedDoc extends Partial<OpenAPIObject> {
3
3
  root?: {
4
4
  method: string;
5
5
  path: string;
6
+ isWebhook?: boolean;
7
+ webhookName?: string;
6
8
  } & OperationObject;
7
9
  responses?: ResponsesObject;
8
10
  }