Skip to content

Commit

Permalink
feat(type-safe-api): support documentation generation for websocket a…
Browse files Browse the repository at this point in the history
…pis (#754)

Convert the OpenAPI spec to AsyncAPI, and use AsyncAPI's documentation generators for html and
markdown documentation

Fixes #742
  • Loading branch information
cogwirrel committed Apr 11, 2024
1 parent 3beec6f commit aad17d9
Show file tree
Hide file tree
Showing 32 changed files with 21,309 additions and 13,678 deletions.
9 changes: 9 additions & 0 deletions .projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion packages/pdk/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The `TypeSafeWebSocketApiProject` projen project sets up the project structure f
- `handlers` - Optionally select the `languages` in which you wish to write lambda handlers for operations in.
- `runtime` - Optionally configure additional generated runtime projects. Include one or more `languages` you want to write your server-side code in. These projects contain generated types defined in your model, as well as type-safe lambda handler wrappers for implementing each operation, and server SDKs for sending messages to connected clients. You'll notice runtime packages are automatically generated for languages you picked for `infrastructure` and `handlers`.
- `library` - Optionally specify additional `libraries` to generate, such as clients or React hooks for use in a React website.
- `documentation` - Optionally specify `formats` to generate documentation in.

## Create your API project

Expand All @@ -39,6 +40,7 @@ npx projen new --from @aws/pdk monorepo-ts --package-manager=pnpm
ModelLanguage,
TypeSafeWebSocketApiProject,
WebSocketLibrary,
WebSocketDocumentationFormat,
} from "@aws/pdk/type-safe-api";
import { InfrastructureTsProject } from "@aws/pdk/infrastructure";
import { CloudscapeReactTsWebsiteProject } from "@aws/pdk/cloudscape-react-ts-website";
Expand Down Expand Up @@ -82,6 +84,12 @@ npx projen new --from @aws/pdk monorepo-ts --package-manager=pnpm
library: {
libraries: [WebSocketLibrary.TYPESCRIPT_WEBSOCKET_HOOKS],
},
// Generate HTML documentation
documentation: {
formats: [
WebSocketDocumentationFormat.HTML,
],
},
});

// Create a website project, which includes an API explorer which is useful for testing our API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ As well as generating lambda handler stubs, when you use the `@handler` Smithy t
=== "TS"

```ts hl_lines="1 11"
import { Api, SayHelloFunction } from "myapi-typescript-infra";
import { WebSocketApi, SayHelloFunction } from "myapi-typescript-infra";

new WebSocketApi(this, id, {
authorizer: new WebSocketIamAuthorizer(),
Expand Down
8 changes: 7 additions & 1 deletion packages/type-safe-api/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 22 additions & 5 deletions packages/type-safe-api/scripts/type-safe-api/common/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ install_packages() {
ts-node@10.9.1 \
ts-command-line-args@2.4.2 \
@redocly/cli@1.0.0-beta.126 \
@asyncapi/cli@1.7.3 \
@asyncapi/html-template@2.3.2 \
@asyncapi/markdown-template@1.5.0 \
reregexp@1.6.1 \
@faker-js/faker@8.1.0 \
@openapitools/openapi-generator-cli@2.6.0 \
Expand All @@ -40,6 +43,22 @@ install_packages() {
projen@0.73.8
}

##
# runs an install command to install the given packages
run_install_command() {
cmd="$@"

if [ "$pkg_manager" == "pnpm" ]; then
runner="$pkg_manager install --reporter=default"
else
runner="$pkg_manager install"
fi

log "running command $runner $cmd"

$runner $cmd
}

##
# installs the passed packages with the package manager in use
_install_packages() {
Expand All @@ -59,6 +78,8 @@ _install_packages() {

# The .committed file contains the identifier of the directory already installed to
_install_dir_identifier=$(cat $_install_packages_committed_file)

log "packages already installed to :: $_install_packages_pdk_base_dir/$_install_dir_identifier"
fi

_install_packages_pdk_dir="$_install_packages_pdk_base_dir/$_install_dir_identifier"
Expand All @@ -69,11 +90,7 @@ _install_packages() {
# Install if any packages are missing
if [ "$_install_packages_should_install" == "true" ]; then
npm init --yes
if [ "$pkg_manager" == "pnpm" ]; then
$pkg_manager install --reporter=default "$@"
else
$pkg_manager install "$@"
fi
run_install_command "$@"
fi

# Mark that we have installed the dependencies (if there's a race and we installed multiple times,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

set -e

# Parse arguments
spec_path=''
output_path=''
while [[ "$#" -gt 0 ]]; do case $1 in
--spec-path) spec_path="$2"; shift;;
--output-path) output_path="$2"; shift;;
esac; shift; done

echo "Generating AsyncAPI HTML documentation..."

working_dir=$(pwd)
script_dir="$( cd -- "$(dirname $([ -L "${BASH_SOURCE[0]:-$0}" ] && readlink -f "${BASH_SOURCE[0]:-$0}" || echo "${BASH_SOURCE[0]:-$0}"))" >/dev/null 2>&1 ; pwd -P )";

# load common package manager helper functions
. "$script_dir/../../common/common.sh"

# Create a temporary directory
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp/}generate-docs-async-api-html.XXXXXXXXX")
cd $tmp_dir

log "async-api-html :: tmp_dir :: $tmp_dir"

# Install dependencies
install_packages

# Generate
run_command asyncapi generate fromTemplate "$working_dir/$spec_path" @asyncapi/html-template@2.3.2 \
--param singleFile=true \
--param outFilename=index.html \
--force-write

# Copy html docs to output path
rm -f $working_dir/$output_path/index.html
cp index.html $working_dir/$output_path/index.html

echo "AsyncAPI HTML documentation generation done!"

# Clean up
cd $working_dir
rm -rf $tmp_dir
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash

set -e

# Parse arguments
spec_path=''
output_path=''
while [[ "$#" -gt 0 ]]; do case $1 in
--spec-path) spec_path="$2"; shift;;
--output-path) output_path="$2"; shift;;
esac; shift; done

echo "Generating AsyncAPI Markdown documentation..."

working_dir=$(pwd)
script_dir="$( cd -- "$(dirname $([ -L "${BASH_SOURCE[0]:-$0}" ] && readlink -f "${BASH_SOURCE[0]:-$0}" || echo "${BASH_SOURCE[0]:-$0}"))" >/dev/null 2>&1 ; pwd -P )";

# load common package manager helper functions
. "$script_dir/../../common/common.sh"

# Create a temporary directory
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp/}generate-docs-async-api-markdown.XXXXXXXXX")
cd $tmp_dir

log "async-api-markdown :: tmp_dir :: $tmp_dir"

# Install dependencies
install_packages

# Generate
run_command asyncapi generate fromTemplate "$working_dir/$spec_path" @asyncapi/markdown-template@1.5.0 \
--param outFilename=index.md \
--force-write

# Copy markdown docs to output path
rm -f $working_dir/$output_path/index.md
cp index.md $working_dir/$output_path/index.md

echo "AsyncAPI Markdown documentation generation done!"

# Clean up
cd $working_dir
rm -rf $tmp_dir
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

set -e

# Parse arguments
spec_path=''
output_path=''
while [[ "$#" -gt 0 ]]; do case $1 in
--spec-path) spec_path="$2"; shift;;
--output-path) output_path="$2"; shift;;
esac; shift; done

working_dir=$(pwd)
script_dir="$( cd -- "$(dirname $([ -L "${BASH_SOURCE[0]:-$0}" ] && readlink -f "${BASH_SOURCE[0]:-$0}" || echo "${BASH_SOURCE[0]:-$0}"))" >/dev/null 2>&1 ; pwd -P )";

# load common package manager helper functions
. "$script_dir/../../common/common.sh"

# Create a temporary directory
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp/}generate-asyncapi-spec.XXXXXXXXX")
cd $tmp_dir

log "generate-asyncapi-spec :: tmp_dir :: $tmp_dir"

# Copy the parse script into the temp directory
cp -r $script_dir/* .

# Install dependencies
install_packages

# Run the parse script
run_command ts-node generate-asyncapi-spec.ts \
--specPath="$working_dir/$spec_path" \
--outputPath="$working_dir/$output_path"

log "generate-asyncapi-spec :: done"

# Clean up
cd $working_dir
rm -rf $tmp_dir

0 comments on commit aad17d9

Please sign in to comment.