Skip to content

Commit e8515dd

Browse files
committed
feat: extend RestApi
- `RestApiWithSpec` simply extends `RestApi`. A user can now `new` `RestApiWithSpec`. - `IRestApiWithSpec` extends `IRestApi` instead of `RestApi` because `RestApiWithSpec` can behave as `RestApi`. - Removes `RestApiFactory` because it is no longer necessary. issue #4
1 parent 426d4ff commit e8515dd

File tree

2 files changed

+25
-134
lines changed

2 files changed

+25
-134
lines changed

src/models.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,7 @@ import { JsonSchemaEx } from './json-schema-ex';
1111
*
1212
* @beta
1313
*/
14-
export interface IRestApiWithSpec extends apigateway.RestApi {
15-
/**
16-
* Underlying
17-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi}
18-
* object.
19-
*
20-
* @remarks
21-
*
22-
* If you directly change this object, the {@link IRestApiWithSpec} instance
23-
* cannot sync with your updates.
24-
*/
25-
underlying: apigateway.RestApi;
26-
14+
export interface IRestApiWithSpec extends apigateway.IRestApi {
2715
/** Root resource ('/') with the features to build the OpenAPI definition. */
2816
root: IBaseResourceWithSpec;
2917

src/rest-api-with-spec.ts

Lines changed: 24 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,12 @@ import {
2626
} from './private/openapi-adapter';
2727
import { resolveResourceId } from './private/utils';
2828

29-
/**
30-
* Factory method of a
31-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi}.
32-
*
33-
* @beta
34-
*/
35-
export type RestApiFactory = (
36-
scope: Construct,
37-
id: string,
38-
props?: apigateway.RestApiProps,
39-
) => apigateway.RestApi;
40-
4129
/**
4230
* Properties for {@link RestApiWithSpec}.
4331
*
4432
* @beta
4533
*/
4634
export interface RestApiWithSpecProps extends apigateway.RestApiProps {
47-
/**
48-
* Factory method of a
49-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi}
50-
* construct.
51-
*
52-
* @remarks
53-
*
54-
* An instance of {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi} will be created if omitted.
55-
*/
56-
newRestApi?: RestApiFactory;
5735
/**
5836
* Info object of the OpenAPI definition.
5937
*
@@ -80,9 +58,6 @@ export interface RestApiWithSpecProps extends apigateway.RestApiProps {
8058
openApiOutputPath: string;
8159
}
8260

83-
const defaultRestApiFactory: RestApiFactory =
84-
(scope, id, props) => new apigateway.RestApi(scope, id, props);
85-
8661
/**
8762
* CDK construct that provisions an API Gateway REST API endpoint and also
8863
* synthesizes the OpenAPI definition for it.
@@ -95,27 +70,25 @@ const defaultRestApiFactory: RestApiFactory =
9570
* Because this construct utilizes the validation as a trigger to start
9671
* synthesis.
9772
*
98-
* The constructor is private.
99-
* Use {@link RestApiWithSpec.createRestApi} instead.
100-
*
10173
* @beta
10274
*/
103-
export class RestApiWithSpec {
75+
export class RestApiWithSpec extends apigateway.RestApi implements IRestApiWithSpec {
10476
/** builder of the OpenAPI definition. */
10577
private builder: OpenApiBuilder;
106-
/** user-facing object returned by `createRestApi`. */
107-
private facade: IRestApiWithSpec;
108-
/** cached root resource. */
109-
private _root: IResourceWithSpec;
78+
/** Root resource with the OpenAPI definition. */
79+
readonly root: IResourceWithSpec;
11080

111-
private constructor(
112-
private readonly restApi: apigateway.RestApi,
81+
/** Initializes a REST API with the OpenAPI specification. */
82+
constructor(
83+
scope: Construct,
84+
id: string,
11385
readonly props: RestApiWithSpecProps,
11486
) {
87+
super(scope, id, props);
11588
this.builder = new OpenApiBuilder({
11689
openapi: '3.1.0',
11790
info: {
118-
title: restApi.restApiName,
91+
title: this.restApiName,
11992
description: props.description,
12093
...props.openApiInfo,
12194
},
@@ -127,99 +100,29 @@ export class RestApiWithSpec {
127100
securitySchemes: {},
128101
},
129102
});
103+
// augments and overrides `root`
104+
this.root = ResourceWithSpec.augmentResource(this.builder, this, this.root);
130105
// synthesizes the OpenAPI definition at validation.
131-
Node.of(restApi).addValidation({
106+
Node.of(this).addValidation({
132107
validate: () => this.synthesizeOpenApi(),
133108
});
134109
}
135110

136-
/**
137-
* Creates an instance of
138-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi}
139-
* that also synthesizes the OpenAPI definition.
140-
*
141-
* @remarks
142-
*
143-
* Specify {@link RestApiWithSpecProps.newRestApi | props.newRestApi}
144-
* if you want to instantiate a subclass of
145-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html | aws_apigateway.RestApi}.
146-
*
147-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApiProps.html#restapiname | props.restApiName}
148-
* is the default value of
149-
* {@link https://spec.openapis.org/oas/latest.html#info-object | info.title}
150-
* in the OpenAPI definition.
151-
* You can override this by specifying the `title` property of
152-
* {@link RestApiWithSpecProps.openApiInfo}.
153-
*
154-
* {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApiProps.html#description | props.description}
155-
* is the default value of
156-
* {@link https://spec.openapis.org/oas/latest.html#info-object | info.description}
157-
* in the OpenAPI definition.
158-
* You can override this by specifying the `description` property of
159-
* {@link RestApiWithSpecProps.openApiInfo}.
160-
*
161-
* @beta
162-
*/
163-
static createRestApi(
164-
scope: Construct,
165-
id: string,
166-
props: RestApiWithSpecProps,
167-
): IRestApiWithSpec {
168-
const newRestApi = props?.newRestApi ?? defaultRestApiFactory;
169-
const restApi = newRestApi(scope, id, props);
170-
const wrapper = new RestApiWithSpec(restApi, props);
171-
wrapper.facade = new Proxy(restApi, {
172-
get: (target, prop, receiver) => {
173-
assert.ok(target === restApi);
174-
switch (prop) {
175-
case 'underlying':
176-
return restApi;
177-
case 'root':
178-
return wrapper.getRoot();
179-
case 'addModel':
180-
return wrapper.getAddModel();
181-
default:
182-
return Reflect.get(target, prop, receiver);
183-
}
184-
},
185-
});
186-
return wrapper.facade;
187-
}
188-
189-
/**
190-
* Returns the root resource augmented with the features to build the OpenAPI
191-
* definition.
192-
*/
193-
private getRoot(): IRestApiWithSpec['root'] {
194-
// reuses the instance
195-
if (this._root != null) {
196-
return this._root;
197-
}
198-
this._root = ResourceWithSpec.augmentResource(
199-
this.builder,
200-
this.facade,
201-
this.restApi.root,
202-
);
203-
return this._root;
204-
}
205-
206111
/**
207112
* Returns the `addModel` function augmented with the features to build the
208113
* OpenAPI definition.
209114
*/
210-
private getAddModel(): IRestApiWithSpec['addModel'] {
211-
return (id, props) => {
212-
// translates the schema
213-
const {
214-
modelOptions,
215-
schema,
216-
} = translateModelOptionsWithSpec(this.restApi, props);
217-
const model = this.restApi.addModel(id, modelOptions);
218-
const modelId = resolveResourceId(Stack.of(this.restApi), model.modelId);
219-
// registers the model as a schema component
220-
this.builder.addSchema(modelId, schema);
221-
return model;
222-
};
115+
addModel(id: string, props: ModelOptionsWithSpec): apigateway.Model {
116+
// translates the schema
117+
const {
118+
modelOptions,
119+
schema,
120+
} = translateModelOptionsWithSpec(this, props);
121+
const model = super.addModel(id, modelOptions);
122+
const modelId = resolveResourceId(Stack.of(this), model.modelId);
123+
// registers the model as a schema component
124+
this.builder.addSchema(modelId, schema);
125+
return model;
223126
}
224127

225128
/** Synthesizes the OpenAPI definition. */
@@ -336,7 +239,7 @@ class ResourceWithSpec {
336239
// creates path-wise parameters shared among all operations under this path
337240
// 1. creates the default path parameter if the path part is a parameter
338241
const defaultParameters = translatePathPart(wrapper.facade);
339-
// 2. overrides the default path parameter with parameters define in
242+
// 2. overrides the default path parameter with parameters defined in
340243
// defaultMethodOptions
341244
const {
342245
parameters,

0 commit comments

Comments
 (0)