Skip to content

Commit b419aee

Browse files
spamshakerMichał Grzegorzewski
andauthored
fix(#2364): Add support for passing parameters to @apioperation (#2365)
* fix(#2364): Add support for passing parameters to @apioperation This commit introduces the ability to pass parameters directly to the @apioperation decorator, allowing developers to define path parameters within the decorator itself. This simplifies OpenAPI schema generation and improves developer experience by reducing boilerplate code. Changes include: - Added `parameters` option to ApiOperationOptions type - Updated OperationMetadata to include parameters property - Modified @apioperation decorator to accept and store parameter metadata - Added tests to verify parameter handling This change aligns with common usage patterns for OpenAPI specifications and provides a more intuitive way to define API operations with required parameters. #closes #2364 * fix(#2364): Allow adding params via ApiOperation tag This commit fixes issue #2364 by enabling developers to specify parameters directly within the @apioperation decorator. This streamlines OpenAPI schema generation and improves developer experience with a more concise syntax for defining API operations that require specific input parameters. --------- Co-authored-by: Michał Grzegorzewski <[email protected]>
1 parent 5be22d7 commit b419aee

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

.changeset/itchy-jobs-create.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-metadata": patch
3+
---
4+
5+
fix(#2364) for allowing to add params via ApiOperation tag

packages/openapi-metadata/src/decorators/api-operation.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { type OperationMetadata, OperationMetadataStorage } from "../metadata/operation.js";
1+
import {
2+
type OperationMetadata,
3+
OperationMetadataStorage,
4+
OperationParameterMetadataStorage,
5+
} from "../metadata/index.js";
26

37
export type ApiOperationOptions = OperationMetadata;
48

@@ -11,5 +15,8 @@ export type ApiOperationOptions = OperationMetadata;
1115
export function ApiOperation(options: ApiOperationOptions): MethodDecorator {
1216
return (target, propertyKey) => {
1317
OperationMetadataStorage.defineMetadata(target, options, propertyKey);
18+
if (Array.isArray(options.parameters)) {
19+
OperationParameterMetadataStorage.mergeMetadata(target, options.parameters, propertyKey);
20+
}
1421
};
1522
}

packages/openapi-metadata/src/metadata/operation.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { OpenAPIV3 } from "openapi-types";
22
import type { HttpMethods } from "../types.js";
33
import { createMetadataStorage } from "./factory.js";
4+
import type { OperationParameterMetadata } from "./operation-parameter.js";
45

5-
export type OperationMetadata = Omit<OpenAPIV3.OperationObject, "responses"> & {
6+
export type OperationMetadata = Omit<OpenAPIV3.OperationObject, "responses" | "parameters"> & {
67
/**
78
* Operation path.
89
* Can include parameters.
@@ -13,6 +14,11 @@ export type OperationMetadata = Omit<OpenAPIV3.OperationObject, "responses"> & {
1314
* Available methods for this operation.
1415
*/
1516
methods?: HttpMethods[];
17+
18+
/**
19+
* Represents metadata about an operation parameter.
20+
*/
21+
parameters?: OperationParameterMetadata[];
1622
};
1723

1824
export const OperationMetadataKey = Symbol("Operation");

packages/openapi-metadata/test/decorators.test.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import "reflect-metadata";
22
import {
3+
ApiBasicAuth,
4+
ApiBearerAuth,
35
ApiBody,
46
ApiCookie,
7+
ApiCookieAuth,
58
ApiExcludeController,
69
ApiExcludeOperation,
710
ApiExtraModels,
811
ApiHeader,
12+
ApiOauth2,
913
ApiOperation,
1014
ApiParam,
1115
ApiProperty,
@@ -19,26 +23,40 @@ import {
1923
ExtraModelsMetadataStorage,
2024
OperationBodyMetadataStorage,
2125
OperationMetadataStorage,
26+
type OperationParameterMetadata,
2227
OperationParameterMetadataStorage,
2328
OperationResponseMetadataStorage,
2429
OperationSecurityMetadataStorage,
2530
PropertyMetadataStorage,
2631
} from "../src/metadata/index.js";
27-
import { ApiBasicAuth, ApiBearerAuth, ApiCookieAuth, ApiOauth2 } from "../src/decorators/api-security.js";
2832

2933
test("@ApiOperation", () => {
34+
const parameters: OperationParameterMetadata[] = [
35+
{
36+
in: "path",
37+
name: "id",
38+
},
39+
] as const;
40+
3041
class MyController {
31-
@ApiOperation({ summary: "Hello", path: "/test", methods: ["get"] })
42+
@ApiOperation({
43+
summary: "Hello",
44+
path: "/test",
45+
methods: ["get"],
46+
parameters,
47+
})
3248
operation() {}
3349
}
3450

35-
const metadata = OperationMetadataStorage.getMetadata(MyController.prototype, "operation");
36-
37-
expect(metadata).toEqual({
51+
const operationMetadata = OperationMetadataStorage.getMetadata(MyController.prototype, "operation");
52+
const parameterMetadata = OperationParameterMetadataStorage.getMetadata(MyController.prototype, "operation");
53+
expect(operationMetadata).toEqual({
3854
summary: "Hello",
3955
path: "/test",
4056
methods: ["get"],
57+
parameters,
4158
});
59+
expect(parameterMetadata).toEqual(parameters);
4260
});
4361

4462
test("@ApiBody", () => {

0 commit comments

Comments
 (0)