Exploring the world with Aspects
Lately I'm thinking about the organization of our TypeScript projects. I wonder whether it matches how other people organize theirs. Where do people put TypeScript source, and where do they put their output? So far we have everything in
lib. Is that the standard? Is there a standard?
To answer this, I want to look at TypeScript projects on GitHub. Lots of them. In what directories do they have
.ts files, and what do they specify for
outDir in tsconfig?
A search on GitHub, specifying
language:typescript and at least 1000 stars (so they're not just a toy) and no larger than 10MB in size (comparable to ours, not too huge to work with) reveals 307 repositories. Too many for me to look at personally, but a reasonable number for a program to check.
Good thing I have a program that's ready to flip through them. Atomist Aspects are made for this: looking around hundreds of repositories to see how they're different.
I spun up a new Atomist SDM (Software Delivery Machine, an app that automates parts of software development). I installed Aspect support, wrote some tests, and created an Aspect to list all the top-level directories containing TypeScript source. The meat is:
This uses Atomist libraries to grab all
.tsx files from each project cloned from GitHub. It excludes
.d.ts files because they're compiler output. From each of those files, it pulls the first element from the relative path, using Node's
All those top-level directories get returned as a fingerprint of this repository's current contents. It's like a tiny piece of data that identifies one meaningful thing about the code. The SDM stores these in my local Postgres.
To trigger this, I sent my SDM a command to analyze all the repositories I found on GitHub:
atomist analyze github by query --query "language:typescript stars:>=1000 size:<=10000"
When done, it serves a web page locally that describes all the aspects and fingerprints.
Wow, 151 variants. That's a lot of combinations of source directories. I ran some analysis in my local Postgres – having all that in a database means I can poke around. I learned that the most common source directories are:
I wanted to see where these source directories overlapped, and zoom in on repositories that have them. My interface offers this if the repositories are labeled with tags, so I wrote a little more TypeScript to add these tags based on the analysis already done. I also made a second Aspect for the compiler output directory, and taggers for the most common values of that (
build or none).
Now I can use the "Interactive Explorer" page served by my SDM to narrow down the big wheel of repositories by tag. I can look at only the ones with TypeScript in
src, and see that they mostly also have source in either
test , and they mostly output to
dist or else don't specify (so compiler output goes to the same directory as the source).
If you want to click around in this data yourself, clone my SDM and run it.
This tells me that our convention of putting TypeScript source in
lib is not typical. I'll have a conversation with the team, and we might change our standard to putting TypeScript code in
src and output to
dist. That can help with another objective: including TypeScript source in our library distributions, so we can click into it from downstream projects in VSCode. (That's a topic for another post.)
If we decide to change our standard, I can use Aspects to check which of our repositories match the new target, and which are lagging behind. I can even automate that move, and have the Atomist bot offer in chat to fix their projects for them. Further posts here, or follow along with me on Twitch – coming Fall of 2019.