Skip to content

Instantly share code, notes, and snippets.

@eladb
Last active January 19, 2021 11:19
Show Gist options
  • Save eladb/68a009cf9c953b04a637bac5c40afdbc to your computer and use it in GitHub Desktop.
Save eladb/68a009cf9c953b04a637bac5c40afdbc to your computer and use it in GitHub Desktop.
Reflecting on the AWS CDK Type System using jsii-reflect
#!/bin/bash
set -euo pipefail
# given an aws-cdk bundle archive (the one published to github releases), extract
# all .jsii manifests and places them under "jsii/*.jsii"
# now they can be used with jsii-reflect
zip=${1:-}
if [ -z "${zip}" ]; then
echo "Usage: $(basename $0) <cdk-bundle-zip>"
exit 1
fi
# make absolute path
zip="$(cd $(dirname ${zip}) && pwd)/$(basename ${zip})"
outdir=$PWD/jsii
rm -fr ${outdir}
mkdir -p ${outdir}
workdir=$(mktemp -d)
(cd ${workdir} && unzip -q ${zip} js/*)
for tarball in $(find ${workdir} -name *.jsii.tgz); do
basename=$(basename ${tarball} .jsii.tgz)
(
staging=$(mktemp -d)
cd ${staging}
if tar -xzv --strip-components=1 -f ${tarball} package/.jsii 2> /dev/null; then
echo ${basename}
mv .jsii ${outdir}/${basename}.jsii
fi
rm -fr ${staging}
)
done

The AWS CDK uses jsii to package it's modules to multiple programming languages. The following document describes how to use a tool called jsii-reflect to explore the CDK's type system.

Create a working directory:

mkdir cdk-explore
cd cdk-explore

Download the .zip release of the CDK from GitHub Releases:

curl -LO https://github.com/awslabs/aws-cdk/releases/download/v0.23.0/aws-cdk-0.23.0.zip

Now, we need to extract all .jsii files from the release. Download the extract-jsii.sh script:

curl -LO "https://gist.github.com/eladb/68a009cf9c953b04a637bac5c40afdbc/raw/extract-jsii.sh"
chmod +x ./extract-jsii.sh

This will create a jsii subdirectory with all CDKK .jsii files.

Next, we'll use the jsii-reflect module to reflect load the entire type system into memory and explore it.

Install the jsii-reflect npm module:

npm i --no-save jsii-reflect

Now, create a file explore.js (if you use VSCode, you'll get nice code completion and stuffs):

const { TypeSystem } = require('jsii-reflect');
const fs = require('fs');
const path = require('path');

const ts = new TypeSystem();

async function main() {
  // load all .jsii files into the type system
  for (const file of fs.readdirSync('./jsii')) {
    await ts.load(path.join('./jsii', file));
  }

  // ready to explore!

  for (const cls of ts.classes) {
    console.log('===========================================================')
    console.log('class name:', cls.name);
    console.log('base class:', cls.base && cls.base.fqn);
    console.log('properties:', cls.properties.map(p => p.name).join());
    console.log('method:', cls.methods.map(m => m.name).join());
  }
}

main().catch(e => {
  console.error(e);
  process.exit(1);
});

Explore Away!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment