npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@intuitionrobotics/thunderstorm-codemod

v2.3.4

Published

One-shot migration tool for v0.x to v1.0 of the @intuitionrobotics/* framework. Rewrites legacy module.exports = ... API/aggregator/re-export files to ESM-style export default, and generates static RouteResolver manifests from api/ directories.

Readme

@intuitionrobotics/thunderstorm-codemod

One-shot migration tools for upgrading downstream consumers of the @intuitionrobotics/* framework. Ships three CLI binaries, all designed to be run once per repository (and then deleted from your dev deps).

pnpm dlx @intuitionrobotics/thunderstorm-codemod migrate         ./src/main/api
pnpm dlx @intuitionrobotics/thunderstorm-codemod bootstrap-routes ./src/main/api --out ./src/main/api/routes.ts
pnpm dlx @intuitionrobotics/thunderstorm-codemod check-routes    ./src/main/api --routes ./src/main/api/routes.ts

The bootstrap-routes / check-routes invocations above are short for the bins thunderstorm-bootstrap-routes and thunderstorm-check-routes. Both are published with their own bin entry, so you can wire check-routes into CI directly via: npx --package=@intuitionrobotics/thunderstorm-codemod -- thunderstorm-check-routes ...

What each tool does

thunderstorm-codemod migrate <api-dir>

Three transformations in one pass, all idempotent.

Pass 1 — module.exports rewrite (v0.x → v1). Safe to run on any tree.

| Before | After | |---|---| | module.exports = new ServerApi_X(); | export default new ServerApi_X(); | | module.exports = [a, b, c]; | export default [a, b, c]; | | module.exports = expr; (anything else) | export default expr; | | module.exports = require("X"); | import _reexport from "X";export default _reexport; |

Regex-based; multi-line or conditional module.exports are left alone — review with --dry-run first if you have an unusual layout.

Pass 2 — strip super("path") and collapse _Get/_Post (v1 → v2).

For every ServerApi_* subclass:

  • Removes the URL-fragment argument from the super(...) call.
  • If the parent is ServerApi_Get or ServerApi_Post, rewrites the extends clause to extends ServerApi<T> and injects HttpMethod.GET (or .POST) into the super() args.
  • Updates the import list: replaces ServerApi_Get / ServerApi_Post with ServerApi, adds HttpMethod. Preserves type modifiers on type-only imports (load-bearing under verbatimModuleSyntax).

| Parent class (before migration) | super() args captured | |---|---| | extends ServerApi_Get<...> | super("leaf") → arg 0 → leaf, method=GET | | extends ServerApi_Post<...> | super("leaf") → arg 0 → leaf, method=POST | | extends ServerApi_Redirect | super("leaf", code, url) → arg 0 | | extends ServerApi<...> | super(METHOD, "leaf"[, tag]) → arg 1 |

Recording into the sidecar happens for every ServerApi-family endpoint the codemod sees, even ones with nothing structural to rewrite. That way bootstrap-routes always knows the method for each endpoint when generating the routes file.

The sidecar lives at <api-dir>/.thunderstorm-routes-sidecar.json. Delete it once bootstrap-routes has consumed it.

thunderstorm-bootstrap-routes <api-dir> --out <file.ts>

Reads the sidecar from migrate plus the filesystem layout of <api-dir> and writes a single Express-Router-tree routes file:

// Auto-generated by thunderstorm-bootstrap-routes — initial seed.
// Hand-edit this from here. The tool runs ONCE; do not regenerate.

import {Router} from "express";

import register        from "./v1/register.js";
import endpointExample from "./v1/types-testing/post-without-response-endpoint.js";

const typesTesting = Router();
typesTesting.post("/post-without-response-endpoint", endpointExample.handler);

const v1 = Router();
v1.post("/register", register.handler);
v1.use("/types-testing", typesTesting);

export const apiRoutes: Router = Router();
apiRoutes.use("/v1", v1);

Each leaf gets router.<method>("/path", api.handler) — pure Express, no framework helper. .handler is the cached RequestHandler on every ServerApi instance.

Conventions inherited from the walker:

  • _<name>.ts files are skipped (private helpers — no v2 equivalent).
  • &<name>.ts files were RouteResolver aggregators in v1. They are omitted from the generated routes file. Delete them from your repo after the seed is written; they're vestigial.
  • Directory names become Express Router subtrees mounted at /{dirname}.
  • File basenames are the fallback for leaf URLs when the sidecar has no captured leafPath (e.g. files that were already v2-shape on a re-run).
  • JS reserved words (delete, class, …) used as identifiers get an underscore prefix (_delete, _class) so the emitted file compiles.

After bootstrap-routes writes the file: edit it freely. The tool runs once. From here on, adding an endpoint means writing the handler file and adding one router.<method>("/path", api.handler) line in this routes file.

thunderstorm-check-routes <api-dir> --routes <file.ts>

CI guard. Verifies every leaf endpoint in <api-dir> is mounted somewhere in the routes file. Recognised mount patterns:

  1. router.<verb>(path, api.handler) — the canonical case.
  2. router.<verb>(path, api) — bare identifier in the handler slot (TS would warn at compile time if this doesn't match the Express RequestHandler shape, so it's rare but accepted).
  3. const ... = importedX — destructure or alias from an imported identifier. The check trusts the destructured names are mounted further down without re-walking.
  4. for (const a of importedArray) ... — iteration over an imported array, typical for dynamic DB-API-generator output:
    for (const api of generatedApis)
        router[api.method](`/${api.relativePath}`, api.handler);

Exits 0 if all leaves are mounted; exits 1 with file:line lines for the missing ones; exits 2 on bad CLI args.

End-to-end migration flow

# 1. Inside your consumer repo, on a clean branch:
pnpm dlx @intuitionrobotics/thunderstorm-codemod migrate ./src/main/api

# 2. Generate the initial Express routes file:
pnpm dlx @intuitionrobotics/thunderstorm-codemod bootstrap-routes \
    ./src/main/api --out ./src/main/api/routes.ts

# 3. Delete legacy aggregators the tool flagged but left in place:
find ./src/main/api -name '&*.ts' -delete
grep -l 'new RouteResolver(' ./src/main/api -r | xargs rm -f

# 4. Update your server entrypoint:
#    -   .setInitialRouteResolver(new RouteResolver())
#    -   .registerApis(...)
#    +   .setRoutes(apiRoutes)        // import from ./api/routes.js
#    +   (everything else is unchanged)
#
#    Plus: any ad-hoc endpoint class living outside api/ needs the same
#    Get/Post collapse the codemod did automatically inside api/. See
#    docs/migrating-to-v2.md "Endpoint class outside api/" for the
#    grep + hand-edit checklist.

# 5. Add the CI guard. Once it passes, commit and remove the codemod
#    from your devDependencies — its job is done.
pnpm dlx @intuitionrobotics/thunderstorm-codemod check-routes \
    ./src/main/api --routes ./src/main/api/routes.ts

Known limitations

  • Array-of-endpoints files. A file like export default [new ApiA(), new ApiB()]; is captured in the sidecar with one entry per class, but the bootstrap emits a single import. Hand-edit the generated routes file:
    const [a, b] = arrayFile;
    router.get("/a", a.handler);
    router.post("/b", b.handler);
    Or, for dynamic DB-API-generator arrays, iterate inline:
    for (const api of generatedApis)
        router[api.method](`/${api.relativePath}`, api.handler);
    check-routes accepts both patterns.
  • Direct new ServerApi_Redirect("path", code, url) constructions. Not yet rewritten by the codemod (only subclasses are). The bootstrap falls back to the filename for the mount path. Hand-edit if you need the original URL fragment preserved.
  • Non-string path literals. If super(METHOD, somePath) uses a variable or expression instead of a string literal, the codemod leaves the file alone. Fix manually.
  • Endpoint classes outside api/. The codemod only walks the directory you pass. Endpoint classes in module init code, util files, or anywhere else need a hand-edit (same shape — drop _Get/_Post, add HttpMethod to super, fix imports).
  • Bare .ts files only. .tsx, .js, .cjs, .d.ts, and .test.ts are skipped.
  • Skips node_modules, dist, build, .git. Hidden directories (.<name>) too.

Exit codes

| Code | Meaning | |---|---| | 0 | success | | 1 | one or more files failed to read/transform/write, or an endpoint was unmounted | | 2 | invalid CLI arguments |

Bins

The package exposes four binaries:

| Bin | Purpose | |---|---| | thunderstorm-codemod | umbrella, currently supports migrate | | thunderstorm-bootstrap-routes | one-shot Express routes-file seed | | thunderstorm-check-routes | CI guard: every leaf is mounted | | thunderstorm-gen-routes | legacy v1 RouteResolver-tree generator (deprecated; kept for repos that haven't migrated yet) |