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

@pumped-fn/lite-lint

v1.4.1

Published

Static anti-pattern scanner for @pumped-fn/lite and @pumped-fn/lite-react

Readme

@pumped-fn/lite-lint

Static anti-pattern scanner for @pumped-fn/lite and @pumped-fn/lite-react codebases.

It is lint-like, but intentionally small: it uses the TypeScript parser directly and checks the boundary rules that the lite and lite-react docs teach. The CLI exits nonzero when diagnostics are found.

The rules encode the code review guide.

Usage

pumped-lite-lint src tests
pumped-lite-lint --json src tests
pumped-lite-lint --config pumped-lite-lint.json src tests

Note: In this repo, root pnpm lint builds the tool and scans the kept packages and public docs.

Rules

| Rule | What it rejects | | --- | --- | | pumped/no-module-mocks | vi.mock, jest.mock, and vi.spyOn; use scope presets at the test seam. | | pumped/no-jsdom-backend | Browser-emulator test markers and DOM-suffixed observer tests; rendered observer tests use Vitest Browser Mode. | | pumped/no-test-only-branches | Product branches keyed on test mode; use presets instead. | | pumped/no-definition-handle-suffix | fooAtom, runFlow, txResource, requestTag; rely on inference. | | pumped/no-explicit-atom-type-argument | Explicit type arguments on atom<T>(...); let the atom infer its value and type substitutes with satisfies and Lite.Utils.AtomValue. Direct, aliased, and namespace imports from @pumped-fn/lite are recognized. Known syntactic false negatives: re-exported aliases and wrapper functions. | | pumped/no-immediate-return-binding (warn) | A block-local identifier with an initializer returned unchanged by the immediately following statement when that return is its only same-named reference in the block; inline the expression. Known conservative false negatives: destructuring, multi-declaration statements, aliases, and any other same-spelled identifier in the block. | | pumped/no-direct-flow-composition | Flows calling child flows with hidden ctx.exec({ flow }) or raw same-file flow deps; use controller(childFlow) deps. | | pumped/no-hidden-exec-dependencies | Named inline ctx.exec and scope.run callbacks that close over runtime values. Put graph handles in the operation's deps; receive execution values through params. name and params are required. Inline callbacks and immutable local const callbacks are inspected; mutable bindings, function declarations, unresolved callbacks, and opaque option overwrites fail closed. scope.run receivers are direct createScope() expressions or immutable local const initializer chains. The unshadowed Promise intrinsic is allowed. Mutable and control-flow receiver aliases are conservative false negatives. | | pumped/no-ctx-argument | Factory context parameters passed as values, and inline operations receiving a directly created execution context through params; ctx is a receiver, and ctx-taking contracts should be reified as a flow reached via deps. Direct expressions and immutable local const initializer chains are followed; mutable and control-flow aliases are conservative false negatives. | | pumped/no-shared-scope-factory | Helpers that return preconfigured createScope(...); each use site should own tags, presets, and extensions. | | pumped/no-scope-argument | Exported product helpers accepting scope, and inline operations receiving a directly created scope through params; composition roots and tests own scope. Direct expressions and immutable local const initializer chains are followed; mutable and control-flow aliases are conservative false negatives. | | pumped/no-scope-reach | Atom/flow/resource factories reaching ctx.scope or calling .createContext(...); execution contexts are owned by composition roots. | | pumped/no-render-outside-browser-test | Testing Library render outside *.browser.test.tsx; DOM observer tests run in browser mode. | | pumped/no-ambient-io-outside-boundary | Raw fetch, timers, DOM/storage, random, and clock access outside transport/root declarations. | | pumped/no-react-use-scope | Feature components calling useScope; use graph hooks and useFlow. | | pumped/no-react-use-execution-context | Feature components calling useExecutionContext; use useFlow for UI-triggered flows. | | pumped/no-react-local-state | Feature components mirroring graph-owned state with useState. | | pumped/no-react-manual-execution-context | Feature components creating or closing execution contexts manually. | | pumped/no-internal-example-label | Stale internal example vocabulary in public docs/source. | | pumped/no-implicit-tag-read (warn) | ctx.data.seekTag/getTag reads for a tag not declared in the unit's deps (via tags.required/tags.optional/tags.all), and scope.resolve(...) calls inside factory bodies; declare the dependency instead. | | pumped/no-naked-globals (warn) | Date.now(), new Date(), Math.random(), process.env, fetch, setTimeout/setInterval, and fs/child_process/node:* builtin usage inside atom/flow/resource factory bodies; wrap the global in an adapter atom/resource or a tag. | | pumped/no-preset-outside-test | preset(...) calls in files outside test paths (tests/, *.test.*, *.spec.*); preset is the test seam, production composition supplies implementations through tags. | | pumped/no-module-state (warn) | Module-level let declarations, and module-level mutable object/array/Map/Set literals that are exported unfrozen or closed over by a factory, in files that also define atom/flow/resource units. | | pumped/prefer-destructured-deps (warn) | Atom/flow/resource/tag factories whose second (deps) parameter is a plain identifier read via member access (e.g. deps.store); destructure it in the signature instead (factory: (ctx, { store }) => ...). | | pumped/no-untyped-throw (warn) | throw new Error(...) and other builtin error constructors (TypeError, RangeError, etc.) inside atom/flow/resource factories; throw a domain error class carrying structured fields (kind/op/entity) so traces and edges can discriminate planned vs unplanned failures. Rethrow of a caught identifier (throw error) and user-defined error classes both pass. | | pumped/no-swallowed-error (warn) | Catch clauses inside atom/flow/resource factories that neither rethrow nor reference the caught error (empty catch bodies, catch {} with no throw, or bodies that discard the binding); swallowing the error here blinds the trace seam. Wrapping with a cause (throw new StoreError(msg, error)), rethrowing, or passing the error to a dep (e.g. logging) all pass. | | pumped/no-handle-spread (warn) | Object literals that spread a lite handle ({ ...sharedFlow, tags: [...] }), detected conservatively — the spread identifier is a same-file atom/flow/resource/... creator result, or the object literal also sets a tags property alongside any spread (the retrofit fingerprint); spreads fork node identity and silently miss presets targeting the original. Wrap the shared flow in a thin entry flow (deps: { run: controller(sharedFlow) }, factory: (ctx, { run }) => run.exec(...)) instead. Plain data object spreads are not flagged. | | pumped/no-hidden-exec-params | Inline ctx.exec({ name, fn, params }) functions that use flow execution input without recording it in params. Pass the real arguments through params so extensions can observe the operation. Keep sensitive values there; use logging and observability runtime tags to omit or redact their telemetry. Empty params is only for true zero-input work. Syntactic scope: direct ctx.exec, inline functions, direct local/context captures, immutable const aliases of context access paths, and array-literal params. Dynamic computed member reads require their ancestor object in params; separately evaluated keys are not assumed equal. Referenced functions, transformed or mutable aliases, and computed parameter arrays are not followed. | | pumped/no-handle-factory | Exported function declarations and exported arrow/function expressions that directly return an atom/flow/resource/material/tag, return one through a wrapper such as model(...), or return a same-function local handle. Configure documented core constructors with allowHandleFactories; composition roots remain unrestricted because they return scopes, not handles. Known syntactic false negatives: handles routed through helper calls, assignments, collections, or cross-function aliases. | | pumped/config-via-tags (warn) | A graph factory that reads a direct identifier parameter from its enclosing function. Provider configuration belongs in a module-level tag declared through deps. Configure documented low-level constructors with allowHandleFactories. Known syntactic false negatives: destructured parameters, aliases, and values forwarded through helpers. | | pumped/no-unattributed-await | Inside an atom/flow/resource factory, an awaited (or .then()-chained) call rooted at the factory's deps parameter, unless it's graph machinery (exec/execStream/prepare by method name; resolve only when the dep's initializer is a controller(...) call) or the enclosing flow's tags array carries a step(...) tag imported from @pumped-fn/sdk; awaited foreign calls only happen inside declared spans. for await iteration and sync calls on deps are not flagged, and a nested function parameter that shadows the deps binding name is respected. Known false negatives, accepted for a syntactic rule: exec/execStream/prepare name collisions on non-handle deps, aliased bindings, rest/nested deps patterns, spread-built tags arrays, and un-awaited returned promises. |

The default path walk skips before.* example files, generated output, lockfiles, and dependency directories where examples intentionally contain bad shapes or third-party code.

Severity

Every diagnostic carries a severity of "error" or "warn".

Note: The CLI exits nonzero only when at least one "error" diagnostic is found. "warn" diagnostics still print and appear in --json, but they do not fail the process; pumped/config-via-tags, pumped/no-implicit-tag-read, pumped/no-naked-globals, pumped/no-module-state, pumped/prefer-destructured-deps, pumped/no-untyped-throw, pumped/no-swallowed-error, pumped/no-handle-spread, and pumped/no-immediate-return-binding default to "warn" as an incremental cleanup inventory, while all other rules default to "error".

Config

The API accepts rules and compositionPaths. The CLI reads the same options from the JSON file passed to --config, alongside maxWarnings:

{
  "compositionPaths": ["(?:^|/)(?:probe-[^/]+|smoke-edge)\\.[cm]?[jt]s$"],
  "maxWarnings": 0
}

Each compositionPaths entry is a JavaScript regular-expression source string tested against the normalized absolute file path. A match extends the built-in composition-root filename convention. It allows ambient IO, naked globals, scope factories, scope arguments with the existing glue diagnostic, and unattributed awaits on that path. Other rules still apply. Use it to classify a project-specific composition or acceptance root, not to suppress individual lines.

rules configures per-rule allowlists:

import { scanPaths } from "@pumped-fn/lite-lint"

const result = await scanPaths(["src", "tests"], {
  rules: {
    "pumped/no-implicit-tag-read": { allowImplicit: ["requestId"] },
    "pumped/no-naked-globals": { allowGlobals: ["fetch"] },
    "pumped/no-handle-factory": { allowHandleFactories: ["cliWorker"] },
  },
})

allowImplicit lists tag identifier names that may be read without being declared in deps. allowGlobals lists global names (e.g. "Date.now", "Math.random", "process.env", "fetch", "setTimeout", "setInterval", or a builtin module specifier like "node:fs") that are exempt from no-naked-globals; it is merged with a small built-in allowlist of already-safe statics (JSON, Math, Object, Array, String, Number, structuredClone, URL). allowBuiltins lists builtin error constructor names (e.g. "TypeError") that are exempt from no-untyped-throw; empty by default. allowHandleFactories lists documented low-level constructors such as agent, tool, skill, sub, session, guard, material, channel, schedule, or cliWorker. Use the same list for no-handle-factory and config-via-tags when a constructor intentionally captures its inputs.

API

import { scanPaths, scanText } from "@pumped-fn/lite-lint"

const result = await scanPaths(["src", "tests"])
const diagnostics = scanText(source, "src/file.ts")

Next


Part of pumped-fn — start with the docs or the mental model.