forked from block65/openapi-constructs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoperation.ts
More file actions
105 lines (91 loc) · 3.09 KB
/
operation.ts
File metadata and controls
105 lines (91 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { Construct } from 'constructs';
import type { oas31 } from 'openapi3-ts';
import { RequestBody, type RequestBodyOptions } from './request-body.ts';
import type { Response } from './response.ts';
import type { SecurityRequirement } from './security-requirement.ts';
import type { Tag } from './tag.ts';
import type { ValidParameter } from './types.ts';
import { stripUndefined } from './utils.ts';
import type { HttpMethod } from './http-method.ts';
export interface OperationOptions<TPath extends string = '/'> {
operationId: string;
summary?: string;
description?: string;
tags?: Set<Tag>;
deprecated?: boolean;
parameters?: ValidParameter<TPath>[];
security?: SecurityRequirement;
responses?: {
[statusCode: string | number]: Response;
};
requestBody?: RequestBody | RequestBodyOptions;
order?: number;
}
export class Operation<TPath extends string = '/'> extends Construct {
private readonly options: OperationOptions<TPath>;
public readonly method: HttpMethod;
public readonly order: number;
private requestBody?: RequestBody;
public hasOperationId(operationId: OperationOptions['operationId']): boolean {
return this.options.operationId === operationId;
}
constructor(
scope: Construct,
method: HttpMethod,
options: OperationOptions<TPath>,
) {
super(scope, method);
this.method = method;
this.options = options;
this.order = options.order || 0;
if (options.requestBody) {
this.requestBody =
options.requestBody instanceof RequestBody
? options.requestBody
: new RequestBody(this, method, options.requestBody);
}
}
public validate() {
// const api = Api.of(this).node.findChild;
const duplicateOperation = this.node.scope?.node.children
.filter(
(child): child is Operation =>
child instanceof Operation && child !== this,
)
.find((child) => child.hasOperationId(this.options.operationId));
if (duplicateOperation) {
return [`Duplicate operationId ${this.options.operationId}`];
}
return [];
}
public synth() {
return stripUndefined({
operationId: this.options.operationId,
description: this.options.description || undefined,
summary: this.options.summary || undefined,
tags:
this.options.tags && [...this.options.tags].map((child) => child.name),
deprecated: this.options.deprecated,
...(this.options.parameters && {
parameters: this.options.parameters.map((child) => child.synth()),
}),
...(this.options.security && {
security: [this.options.security.synth()],
}),
...(this.options.tags && {
tags: Array.from(this.options.tags).map((child) => child.name),
}),
...(this.requestBody && {
requestBody: this.requestBody.synth(),
}),
...(this.options.responses && {
responses: Object.fromEntries(
Object.entries(this.options.responses).map(([statusCode, child]) => [
statusCode.toString(),
child.synth(),
]),
),
}),
}) satisfies oas31.OperationObject;
}
}