-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from reapit/construct/edge-api-swagger
construct: add edge-api-swagger
- Loading branch information
Showing
24 changed files
with
956 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# @reapit-cdk/cross-region-stack-export | ||
|
||
|
||
![npm version](https://img.shields.io/npm/v/@reapit-cdk/cross-region-stack-export) | ||
![npm downloads](https://img.shields.io/npm/dm/@reapit-cdk/cross-region-stack-export) | ||
![coverage: 74.02%25](https://img.shields.io/badge/coverage-74.02%25-orange) | ||
![Integ Tests: X](https://img.shields.io/badge/Integ%20Tests-X-red) | ||
|
||
Allows you to share values between stack across regions and accounts. | ||
|
||
## Package Installation: | ||
|
||
```sh | ||
yarn add --dev @reapit-cdk/cross-region-stack-export | ||
# or | ||
npm install @reapit-cdk/cross-region-stack-export --save-dev | ||
``` | ||
|
||
## Usage | ||
```ts | ||
import { CfnOutput, Stack, App } from 'aws-cdk-lib' | ||
import { CrossRegionStackExport } from '@reapit-cdk/cross-region-stack-export' | ||
import { Bucket } from 'aws-cdk-lib/aws-s3' | ||
|
||
const app = new App() | ||
const euStack = new Stack(app, 'stack-eu', { | ||
env: { | ||
account: '11111111', | ||
region: 'eu-west-1', | ||
}, | ||
}) | ||
|
||
const exporter = new CrossRegionStackExport(euStack, 'exporter') | ||
exporter.setValue('thing', 'avalue') | ||
|
||
const bucket = new Bucket(euStack, 'bucket') | ||
exporter.setValue('bucketArn', bucket.bucketArn) | ||
|
||
const usStack = new Stack(app, 'stack-us', { | ||
env: { | ||
account: '2222222222', | ||
region: 'us-east-1', | ||
}, | ||
}) | ||
|
||
const importer = exporter.getImporter(usStack, 'eu-importer') | ||
|
||
const euThing = importer.getValue('thing') | ||
const euBucket = Bucket.fromBucketArn(usStack, 'eu-bucket', importer.getValue('bucketArn')) | ||
|
||
new CfnOutput(usStack, 'euThing', { | ||
value: euThing, | ||
}) | ||
|
||
new CfnOutput(usStack, 'euBucketName', { | ||
value: euBucket.bucketName, | ||
}) | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
src | ||
tests | ||
.eslintrc.js | ||
tsconfig.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
{ | ||
"name": "@reapit-cdk/edge-api-swagger", | ||
"version": "0.0.0", | ||
"description": "Add a swagger endpoint to your EdgeAPI", | ||
"homepage": "https://github.com/reapit/ts-cdk-constructs/blob/main/packages/constructs/edge-api-swagger", | ||
"readme": "https://github.com/reapit/ts-cdk-constructs/blob/main/packages/constructs/edge-api-swagger/readme.md", | ||
"bugs": { | ||
"url": "https://github.com/reapit/ts-cdk-constructs/issues" | ||
}, | ||
"license": "MIT", | ||
"author": { | ||
"name": "Josh Balfour", | ||
"email": "jbalfour@reapit.com" | ||
}, | ||
"repository": { | ||
"url": "https://github.com/reapit/ts-cdk-constructs.git" | ||
}, | ||
"scripts": { | ||
"build": "reapit-cdk-tsup", | ||
"check": "yarn run root:check -p $(pwd)", | ||
"lint": "reapit-cdk-eslint", | ||
"test": "yarn run root:test -- $(pwd)", | ||
"prepack": "reapit-version-package && yarn build", | ||
"integ": "yarn run root:integ -- $(pwd)", | ||
"jsii:build": "rpt-cdk-jsii", | ||
"jsii:publish": "rpt-cdk-jsii --publish" | ||
}, | ||
"main": "src/index.ts", | ||
"types": "src/index.ts", | ||
"publishConfig": { | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts" | ||
}, | ||
"dependencies": { | ||
"openapi3-ts": "^4.1.2", | ||
"swagger-ui-dist": "^5.9.0", | ||
"typescript": "^5.1.3" | ||
}, | ||
"peerDependencies": { | ||
"@reapit-cdk/edge-api": "workspace:^", | ||
"aws-cdk-lib": "^2.96.2", | ||
"constructs": "^10.2.70" | ||
}, | ||
"devDependencies": { | ||
"@reapit-cdk/eslint-config": "workspace:^", | ||
"@reapit-cdk/integration-tests": "workspace:^", | ||
"@reapit-cdk/jsii": "workspace:^", | ||
"@reapit-cdk/tsup": "workspace:^", | ||
"@reapit-cdk/version-package": "workspace:^", | ||
"aws-cdk-lib": "^2.96.2", | ||
"constructs": "^10.2.70" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# @reapit-cdk/edge-api-swagger | ||
|
||
|
||
![npm version](https://img.shields.io/npm/v/@reapit-cdk/edge-api-swagger) | ||
![npm downloads](https://img.shields.io/npm/dm/@reapit-cdk/edge-api-swagger) | ||
![coverage: 0%25](https://img.shields.io/badge/coverage-0%25-red) | ||
![Integ Tests: X](https://img.shields.io/badge/Integ%20Tests-X-red) | ||
|
||
Add a swagger endpoint to your EdgeAPI | ||
|
||
## Package Installation: | ||
|
||
```sh | ||
yarn add --dev @reapit-cdk/edge-api-swagger | ||
# or | ||
npm install @reapit-cdk/edge-api-swagger --save-dev | ||
``` | ||
|
||
## Usage | ||
```ts | ||
import { Stack, App } from 'aws-cdk-lib' | ||
import { EdgeAPI, EdgeAPILambda } from '@reapit-cdk/edge-api' | ||
import { Code, Runtime } from 'aws-cdk-lib/aws-lambda' | ||
import { EdgeAPISwaggerEndpoint } from '@reapit-cdk/edge-api-swagger' | ||
import { Certificate } from 'aws-cdk-lib/aws-certificatemanager' | ||
import * as path from 'path' | ||
|
||
const app = new App() | ||
const stack = new Stack(app, 'stack-name') | ||
|
||
const certificate = new Certificate(stack, 'certificate', { | ||
domainName: 'example.org', | ||
}) | ||
const api = new EdgeAPI(stack, 'api', { | ||
certificate, | ||
domains: ['example.org', 'example.com'], | ||
devMode: false, | ||
defaultEndpoint: { | ||
destination: 'example.com', | ||
}, | ||
}) | ||
|
||
const lambda = new EdgeAPILambda(stack, 'lambda', { | ||
code: Code.fromAsset(path.resolve('../lambda/dist')), | ||
codePath: path.resolve('../lambda/src/index.ts'), // gets added to the docs | ||
handler: 'index.handler', | ||
runtime: Runtime.NODEJS_18_X, | ||
environment: { | ||
aVariable: 'contents', | ||
}, | ||
}) | ||
|
||
api.addEndpoint({ | ||
pathPattern: '/api/lambda', | ||
lambda, | ||
}) | ||
|
||
api.addEndpoint( | ||
new EdgeAPISwaggerEndpoint(stack, 'docs', { | ||
api, | ||
url: 'https://example.org', | ||
|
||
pathPattern: '/swagger', // optional, defaults to /swagger | ||
|
||
// optional | ||
info: { | ||
title: '', // defaults to Edge API | ||
version: '', // defaults to 1.0.0 | ||
}, | ||
}), | ||
) | ||
|
||
``` |
114 changes: 114 additions & 0 deletions
114
packages/constructs/edge-api-swagger/src/edge-api-swagger-endpoint.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { EdgeAPI, FrontendEndpoint, endpointIsLambdaEndpoint, endpointIsProxyEndpoint } from '@reapit-cdk/edge-api' | ||
import { Construct } from 'constructs' | ||
|
||
import { Bucket } from 'aws-cdk-lib/aws-s3' | ||
import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment' | ||
import { RemovalPolicy } from 'aws-cdk-lib' | ||
import { generateOpenAPIDocs } from './generation/generate-openapi-docs' | ||
import { EndpointInputItem } from './generation' | ||
import { getAbsoluteFSPath } from 'swagger-ui-dist' | ||
import { InfoObject } from 'openapi3-ts/oas30' | ||
|
||
interface EdgeAPISwaggerEndpointProps { | ||
api: EdgeAPI | ||
url: string | ||
pathPattern?: string | ||
info?: InfoObject | ||
} | ||
|
||
const swaggerHtml = (urlPrefix: string) => `<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<meta | ||
name="description" | ||
content="SwaggerUI" | ||
/> | ||
<title>SwaggerUI</title> | ||
<link rel="stylesheet" href="${urlPrefix}/swagger-ui.css" /> | ||
</head> | ||
<body> | ||
<div id="swagger-ui"></div> | ||
<script src="${urlPrefix}/swagger-ui-bundle.js" crossorigin></script> | ||
<script src="${urlPrefix}/swagger-ui-standalone-preset.js" crossorigin></script> | ||
<script> | ||
window.onload = () => { | ||
window.ui = SwaggerUIBundle({ | ||
url: '${urlPrefix}/openapi.json', | ||
dom_id: '#swagger-ui', | ||
}); | ||
}; | ||
</script> | ||
</body> | ||
</html>` | ||
|
||
export class EdgeAPISwaggerEndpoint extends Construct implements FrontendEndpoint { | ||
bucket: Bucket | ||
invalidationItems: string[] | ||
pathPattern: string | ||
|
||
constructor(scope: Construct, id: string, props: EdgeAPISwaggerEndpointProps) { | ||
super(scope, id) | ||
this.pathPattern = props.pathPattern ?? '/swagger' | ||
|
||
const destinationKeyPrefix = this.pathPattern.replace(/^\/+/g, '') | ||
|
||
this.bucket = new Bucket(this, 'bucket', { | ||
websiteIndexDocument: 'index.html', | ||
websiteErrorDocument: destinationKeyPrefix + '/index.html', | ||
removalPolicy: RemovalPolicy.RETAIN, // otherwise deletion will fail on stack destroy due to non-empty bucket | ||
publicReadAccess: true, | ||
blockPublicAccess: { | ||
blockPublicAcls: false, | ||
blockPublicPolicy: false, | ||
ignorePublicAcls: false, | ||
restrictPublicBuckets: false, | ||
}, | ||
}) | ||
|
||
const openapiJson = generateOpenAPIDocs({ | ||
url: props.url, | ||
info: props.info, | ||
endpointsInput: props.api._endpoints.map((endpoint): EndpointInputItem => { | ||
if (endpointIsLambdaEndpoint(endpoint)) { | ||
return { | ||
codePath: endpoint.lambda.codePath, | ||
pathPattern: endpoint.pathPattern, | ||
isFrontend: false, | ||
} | ||
} | ||
if (endpointIsProxyEndpoint(endpoint)) { | ||
return { | ||
isProxy: true, | ||
pathPattern: endpoint.pathPattern, | ||
proxyDestination: endpoint.destination, | ||
} | ||
} | ||
return { | ||
pathPattern: endpoint.pathPattern, | ||
isFrontend: true, | ||
} | ||
}), | ||
}) | ||
|
||
new BucketDeployment(this, 'deployment', { | ||
sources: [ | ||
Source.data('index.html', swaggerHtml(`${props.url}/${destinationKeyPrefix}`)), | ||
Source.jsonData('openapi.json', openapiJson), | ||
Source.asset(getAbsoluteFSPath()), | ||
], | ||
destinationBucket: this.bucket, | ||
destinationKeyPrefix, | ||
retainOnDelete: false, | ||
}) | ||
|
||
this.invalidationItems = [ | ||
'/index.html', | ||
'/openapi.json', | ||
'/swagger-ui-bundle.js', | ||
'/swagger-ui-standalone-preset.js', | ||
'/swagger-ui.css', | ||
] | ||
} | ||
} |
Oops, something went wrong.