Aalexbit-codemod

js-dependency-mining

Mine and classify JS/TS package dependencies (manifests + lockfiles); read-only metrics

miningmetricsdependenciesmonorepo
Public
25 executions
0 stars
How to Use
Run this codemod on your codebase using one of the following commands

The easiest way to run this codemod without installing anything globally:

Documentation

js-dependency-mining

Read-only mining codemod: scans package.json manifests (single-package repos and monorepos) together with package-lock.json, pnpm-lock.yaml, or yarn.lock, classifies each dependency, and emits js-dependency-mining metrics. It does not modify source files.

No fs capability required — no Node fs or path imports. The workflow only targets **/package.json. Lockfiles are loaded with jssgTransform and small JSON/YAML transforms that capture root.root().text() (same mechanism as cross-file edits in the JSSG docs).

Classifications

Each finding is keyed by owner package (workspace-relative path), package name, and edge type (direct | transitive). Metric dimensions include:

FieldValues
packageNamenpm package name
declaredVersionRange or spec from the manifest (empty for transitive-only rows)
ownerPackageWorkspace-relative owning package path
manifestPathPath to package.json (relative to workspace root)
edgeTypedirect, transitive
purposeruntime, dev, test, build, optional, unknown
originregistry, vcs, local, workspace, vendored, internal, unknown
versionPolicypinned, ranged, prerelease, unknown

Workspace root

While processing a manifest, the codemod walks up the directory path and uses jssgTransform to probe for package-lock.json (language json), pnpm-lock.yaml / yarn.lock / pnpm-workspace.yaml (language yaml), and reads sibling package.json files to detect npm workspaces. The first directory that qualifies as a workspace root wins; the manifest is then resolved relative to that root.

Pipeline

  1. Workspace root — Walk upward from the manifest; at each level, try lockfiles and workspace markers via jssgTransform until a root is found.
  2. Lockfile — From that root, load the preferred lockfile in order npm → pnpm → yarn using jssgTransform + capture transforms (json for package-lock.json, yaml for pnpm/yarn). Parse with JSON.parse / js-yaml / the built-in yarn-classic parser.
  3. Metrics — For each dependency block in the manifest, emit direct rows; subtract directs from the lockfile transitive closure and emit transitive rows.

Workspace package names (for origin=workspace heuristics) are accumulated in a module-level registry as each package.json in the run is seen — no codemod:workflow state.

Configuration

Parameters are declared in workflow.yaml (params.schema) and merge with built-in defaults (extra test/build lists, default vendored fragments, etc.).

Where to edit them

  • Codemod Insight UI — When you run this workflow in Insight, each parameter appears as a labeled field. You can change values there without editing YAML; that is the easiest way to tune classification for a run or saved job.
  • CLI — Pass --param key=value to codemod workflow run (repeat for multiple keys), e.g. --param internal_scopes=@acme --param test_packages=playwright.

Parameters and examples (values are comma-separated unless noted):

ParameterExampleWhat it does
internal_scopes@acme,@calcomScope prefixes for origin=internal. Packages whose names start with these (e.g. @acme/foo) are treated as internal when not better classified as workspace/VCS/local.
test_packagesstorybook,@storybook/reactExtra names merged into the test-tool list. If listed in devDependencies, purpose can be test (instead of generic dev).
build_packagesturbo,tsc-aliasExtra names merged into the build-tool list. If listed in devDependencies, purpose can be build.
vendored_path_fragmentspatches/,/vendor/Extra path substrings. For file: / link: dependency specs, if the path contains one of these (in addition to defaults like vendor/), origin can be vendored.

Implementation notes

  • No fs / path imports. Path operations use pure-string helpers. jssgTransform reads lockfiles under the workflow target; paths must stay within that target (per JSSG rules).
  • jssgTransform in jssg test is a no-op — lockfiles are not loaded in unit tests, so snapshots typically show direct dependencies only. Real runs (codemod workflow run / Insight) load lockfiles and emit transitive rows.
  • Yarn classic lockfiles are read with language yaml for parsing; the custom line parser runs on the captured text. If ast-grep cannot parse a particular yarn.lock, that lock may be skipped (catch and continue).
  • Transitive dependencies are derived from the lockfile closure minus direct declarations (npm and pnpm v9 snapshots supported; yarn classic is best-effort).
  • Conservative: ambiguous cases use unknown where classification would be a guess (e.g. transitive purpose).
  • pnpm pnpm-lock.yaml is deserialized from the tree-sitter YAML AST (inline helpers in scripts/codemod.ts) inside a jssgTransform callback — no third-party YAML library, so Insight bundling stays simple.

Ready to contribute?

Build your own codemod and share it with the community.