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

@reponova/lang-json

v0.4.0

Published

JSON / JSONC support for RepoNova with schema-aware extraction (package.json, tsconfig*, nx.json, project.json)

Readme

@reponova/lang-json

JSON / JSONC support for RepoNova. Schema-aware: recognises the canonical configuration files of the JS/TS ecosystem (package.json, tsconfig*, nx.json, project.json, lerna.json, turbo.json) and surfaces them as first-class graph entities. Falls back to a generic top-level-keys-as-symbols extraction for everything else. Backed by Microsoft's jsonc-parser — no tree-sitter grammar required, JSONC syntax (// line comments, /* … */ block comments, trailing commas) is supported transparently for every file shape.

Install

reponova lang add @reponova/lang-json

What it extracts

  • Symbols:
    • package.json — the package's name as a constant (so graph_search against the package name resolves to the file), every scripts.* as a function (the shell command becomes the docstring), every bin entry (string AND map form) as a function.
    • tsconfig*.json — surfaces structural metadata only via imports / file-level tags; no per-key symbol noise.
    • nx.jsontargetDefaults.* as function symbols (executor / command in the docstring), namedInputs.* as variable symbols.
    • project.json (Nx) — targets.* as function symbols (executor / command in docstring), tags[] as variable symbols (so Nx scope rules like scope:auth / type:lib become graph facets).
    • turbo.jsonpipeline.* (Turbo 1) AND tasks.* (Turbo 2) as function symbols.
    • Generic JSON / JSONC (anything that doesn't match a known schema) — top-level keys as variable symbols, capped to the configured maxGenericKeys (default 200, see Configuration).
  • Decorators: every symbol carries a single decorator describing its provenance — npm-script, npm-bin, package-name, nx-target, nx-target-default, nx-named-input, nx-tag, turbo-task, json-key. This lets downstream queries filter by source schema.
  • Edges:
    • Imports: dependencies / devDependencies / peerDependencies / optionalDependencies from package.json (each carries <dep>@<spec> in names[0]); tsconfig extends (string AND TS 5.0 array form) and references[].path; compilerOptions.paths.<alias> expanded into one import per target with the alias preserved in names[0] (wildcard aliases carry isWildcard: true); npm workspaces (array form AND { packages: [...] } form), lerna.json packages[], and turbo.json extends[]; Nx plugins[] (string AND { plugin, options } forms) and generators.*.
    • References: Nx project.json implicitDependencies[] as references edges from the project to each declared dependency.
  • File docstring: the package / generic-JSON description field, when present.
  • File-level tags: package.json (always), private and workspaces (when set on a package.json); tsconfig, extends, project-references; nx, monorepo; nx-project, nx-application / nx-library; lerna, turborepo; plain json for the generic fallback.
  • File node kind: module.

Extensions

.json, .jsonc

The schema kind is detected from the basename (case-insensitive, Windows path separators normalised). Custom-suffix tsconfig files (tsconfig.spec.json, tsconfig.lib.json, tsconfig.<anything>.json) are recognised as tsconfig.

Configuration

In reponova.yml:

plugins:
  json:
    enabled: true                # default: true
    maxGenericKeys: 200          # default: 200 — cap on generic-fallback symbols per file
    # patterns: []               # override global patterns for JSON files
    # exclude: []                # override global exclude for JSON files

| Property | Type | Default | Description | |----------|------|---------|-------------| | enabled | boolean | true | Enable/disable JSON file detection and extraction | | maxGenericKeys | number | 200 | Cap on top-level keys surfaced as variable symbols for files that fall into the generic fallback (no recognised schema). Stops large data dumps / translation tables / lookup files from creating thousands of nodes. The cap does NOT apply to schema-recognised files (package.json, tsconfig*, nx.json, project.json, …) which are already structured. Set to a large number (or Infinity) to disable. | | patterns | string[] | [] | Glob patterns to override global file matching for this plugin | | exclude | string[] | [] | Glob patterns to override global exclusions for this plugin |

maxGenericKeys is also accepted as a constructor option for callers that consume the plugin programmatically:

import { JsonExtractor } from "@reponova/lang-json";

const ext = new JsonExtractor({ maxGenericKeys: 500 });   // raise the cap
// or
const ext = new JsonExtractor({ maxGenericKeys: Infinity }); // disable entirely

Resolution semantics

  • Relative tsconfig-style specs (extends, references[].path, paths aliases) resolve against the importing file's directory: "./foo.json" from apps/web/tsconfig.jsonapps/web/foo.json. Path traversal (../) and ./ are normalised.
  • The .json extension is appended when the spec lacks one: "../shared/base" from apps/web/tsconfig.jsonapps/shared/base.json.
  • Directory-style references ("./libs/core") also offer the implicit libs/core/tsconfig.json candidate so directory-style references resolve to the directory's tsconfig.
  • Bare specifiers (react, @tsconfig/node20/tsconfig.json, workspace package names) return [] and are treated as external. node_modules walks, package.json exports field rewriting, and workspace alias resolution are deliberately delegated to RepoNova's upstream import resolver — this plugin only handles relative-path semantics.
  • The bin field on package.json accepts both the single-string form ("bin": "./cli.js" — the synthesised symbol takes the package's short name) and the map form ("bin": { "tool-a": "./a.js", "tool-b": "./b.js" } — one symbol per entry).
  • The private flag on package.json is recognised as both the canonical JSON boolean ("private": true) and the legacy string form ("private": "true") some hand-edited files use.
  • Comments inside JSON files are NOT preserved as symbol docstrings — only the structured description / per-script command body fields are surfaced. Trailing commas and JSONC comments do not break parsing in any file (including package.json, although strict tooling like npm itself does not accept them there).
  • The schema-detection step is filename-only: a package.json placed at /data/package.json is still extracted as a package even if its content is not a real npm manifest. If the content is malformed JSON, the parser tolerates partial recovery and the extractor surfaces whatever it could parse without throwing.

License

MIT — see LICENSE.