-
Notifications
You must be signed in to change notification settings - Fork 4k
/
api-definition.ts
205 lines (184 loc) · 5.21 KB
/
api-definition.ts
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import * as s3 from '@aws-cdk/aws-s3';
import * as s3_assets from '@aws-cdk/aws-s3-assets';
import * as cdk from '@aws-cdk/core';
/**
* Represents an OpenAPI definition asset.
* @experimental
*/
export abstract class ApiDefinition {
/**
* Creates an API definition from a specification file in an S3 bucket
* @experimental
*/
public static fromBucket(bucket: s3.IBucket, key: string, objectVersion?: string): S3ApiDefinition {
return new S3ApiDefinition(bucket, key, objectVersion);
}
/**
* Create an API definition from an inline object. The inline object must follow the
* schema of OpenAPI 2.0 or OpenAPI 3.0
*
* @example
* ApiDefinition.fromInline({
* openapi: '3.0.2',
* paths: {
* '/pets': {
* get: {
* 'responses': {
* 200: {
* content: {
* 'application/json': {
* schema: {
* $ref: '#/components/schemas/Empty',
* },
* },
* },
* },
* },
* 'x-amazon-apigateway-integration': {
* responses: {
* default: {
* statusCode: '200',
* },
* },
* requestTemplates: {
* 'application/json': '{"statusCode": 200}',
* },
* passthroughBehavior: 'when_no_match',
* type: 'mock',
* },
* },
* },
* },
* components: {
* schemas: {
* Empty: {
* title: 'Empty Schema',
* type: 'object',
* },
* },
* },
* });
*/
public static fromInline(definition: any): InlineApiDefinition {
return new InlineApiDefinition(definition);
}
/**
* Loads the API specification from a local disk asset.
* @experimental
*/
public static fromAsset(file: string, options?: s3_assets.AssetOptions): AssetApiDefinition {
return new AssetApiDefinition(file, options);
}
/**
* Called when the specification is initialized to allow this object to bind
* to the stack, add resources and have fun.
*
* @param scope The binding scope. Don't be smart about trying to down-cast or
* assume it's initialized. You may just use it as a construct scope.
*/
public abstract bind(scope: cdk.Construct): ApiDefinitionConfig;
}
/**
* S3 location of the API definition file
* @experimental
*/
export interface ApiDefinitionS3Location {
/** The S3 bucket */
readonly bucket: string;
/** The S3 key */
readonly key: string;
/**
* An optional version
* @default - latest version
*/
readonly version?: string;
}
/**
* Post-Binding Configuration for a CDK construct
* @experimental
*/
export interface ApiDefinitionConfig {
/**
* The location of the specification in S3 (mutually exclusive with `inlineDefinition`).
*
* @default - API definition is not an S3 location
*/
readonly s3Location?: ApiDefinitionS3Location;
/**
* Inline specification (mutually exclusive with `s3Location`).
*
* @default - API definition is not defined inline
*/
readonly inlineDefinition?: any;
}
/**
* OpenAPI specification from an S3 archive.
* @experimental
*/
export class S3ApiDefinition extends ApiDefinition {
private bucketName: string;
constructor(bucket: s3.IBucket, private key: string, private objectVersion?: string) {
super();
if (!bucket.bucketName) {
throw new Error('bucketName is undefined for the provided bucket');
}
this.bucketName = bucket.bucketName;
}
public bind(_scope: cdk.Construct): ApiDefinitionConfig {
return {
s3Location: {
bucket: this.bucketName,
key: this.key,
version: this.objectVersion,
},
};
}
}
/**
* OpenAPI specification from an inline JSON object.
* @experimental
*/
export class InlineApiDefinition extends ApiDefinition {
constructor(private definition: any) {
super();
if (typeof(definition) !== 'object') {
throw new Error('definition should be of type object');
}
if (Object.keys(definition).length === 0) {
throw new Error('JSON definition cannot be empty');
}
}
public bind(_scope: cdk.Construct): ApiDefinitionConfig {
return {
inlineDefinition: this.definition,
};
}
}
/**
* OpenAPI specification from a local file.
* @experimental
*/
export class AssetApiDefinition extends ApiDefinition {
private asset?: s3_assets.Asset;
constructor(private readonly path: string, private readonly options: s3_assets.AssetOptions = { }) {
super();
}
public bind(scope: cdk.Construct): ApiDefinitionConfig {
// If the same AssetAPIDefinition is used multiple times, retain only the first instantiation.
if (this.asset === undefined) {
this.asset = new s3_assets.Asset(scope, 'APIDefinition', {
path: this.path,
...this.options,
});
}
if (this.asset.isZipArchive) {
throw new Error(`Asset cannot be a .zip file or a directory (${this.path})`);
}
return {
s3Location: {
bucket: this.asset.s3BucketName,
key: this.asset.s3ObjectKey,
},
};
}
}