Thomas Reggi's Profile Image

@thomasreggi 🌸

I invented a CLI tool to organize my typescript projects.

June 23, 2023 (Syndicated From

Cover Image

TLDR: This article is about a command-line tool designed to analyze and enforce a specific hierarchical folder structure within TypeScript projects called tree lint.

I often find myself coding outside the standard guidelines of a framework; no MVC for me. I’m usually deep in the weeds making file-system calls, reading here, writing there, and creating a CLI script using node or deno - something I want to be reusable down the line. I frequently struggle to wrangle all the files and folders I create. I usually start out with the approach to have the whole structure be flat, full of focus and vigilance.

Gif from all gas no breaks of Andrew interviewing a flat-earther, in which the interviewee says "flat gang baby"

However, soon after adopting this philosophy, things start to unravel. The entire folder becomes swamped with too much happening. Without compartmentalization of the files and folders into their respective silos, there’s chaos.

Flat structures in entire projects can make it exceedingly difficult to segment things if you want to break the project out into multiple repositories. I often find myself coding and creating something within that project that could be utilized elsewhere and in other projects. Unfortunately, flat structures make it impossible to easily isolate a single node in the hierarchy, thereby forcing you to dismantle everything.

So, I’ve been trying to create smaller files and more of them, and placing them into different subdirectories where they share some characteristic or logic. I usually attempt to keep all these directories flat at the root of the project to avoid deep nesting, but the same thing repeats itself.

I often create one of these silos, make it perfect, and then realize I’ve duplicated logic from outside the silo that the rest of the code needs. What to do? I’m not a big fan of one “project” that’s siloed reaching into the “cookie-jar” of another project that’s supposedly siloed.

All of this adds to the complexity of a project. Not having a clear hierarchy of how the files and folders interact really throws me off. Even when I “invent” a structure myself, I come back to it days or even hours later, look at it and ask, “What have I done?”

If none of the issues I’ve described resonate with you because you write components in a components folder for a living, please feel free to close this browser tab. This post isn’t for you.

Introducing tree_lint, a CLI tool that scans a directory and advises you on how the hierarchy should appear. It adheres to a few simple rules. These guidelines facilitate the understanding of which code utilizes what. Furthermore, they simplify the process of sectioning off chunks and transforming them into their own repositories.

Now, a repository is worth a thousand words, so it might be best to just go check out the repo and get an understanding of the layout from there:

  1. Each dir is a “project”.
  2. Each project can contain whatever files you want. The convention is ideally a single mod.ts, test.ts etc file.
  3. Dependents of the project live as a sibling next to its mod.ts in a folder and so on, building a hierarchy.
  4. Projects that are not used by any other project will be at the top of the tree.
  5. Projects with only one usage should be nested within that project.
  6. Projects that are used by more than one project are placed as a sibling of the highest (top-most) project in the tree.
  7. Circular projects will be siblings.

There’s a lot of complex logic to get circular dependencies to work correctly and to do this hoisting logic to make things siblings. If you’re interested, feel free to check out the repo.

This might very well just be a “me” problem. But on the off chance that it’s not, I’d love to hear about it. Comment below if this is useful or if you, too, struggle with the agonizing task of organizing “files” and “folders”. I’m now at peace, knowing there’s a lintable solution, and I don’t need to think about it anymore 🧘.