Skip to content

Async ​

@scruple/async checks asynchronous control flow, including concurrency, cancellation, cleanup, and unobserved work.

sh
pnpm add -D @scruple/async
ts
import { defineConfig } from "@scruple/core";
import { asyncRules } from "@scruple/async";

export default defineConfig({
  parser,
  provider,
  plugins: { async: asyncRules() },
  rules: { "async/no-unbounded-concurrency": "warn" },
});
RuleChecks
async/no-unbounded-concurrencyPotentially unbounded promise fan-out
async/no-serial-independent-workIndependent awaits run in series
async/require-cancellation-propagationAccepted cancellation not forwarded
async/require-race-loser-cleanupLocally owned race losers abandoned
async/require-abort-listener-cleanupAbort listeners outlive operations
async/no-unobserved-async-workStarted async work is not observed
async/no-async-initializationAsync work hidden in initialization

async/no-unbounded-concurrency ​

Reviews native Promise.all and Promise.allSettled fan-out with visible operation creation and boundary evidence. Fixed tuples and visible batching or limits are accepted. Options: threshold { warning: 0.9, error: 0.97 }, minConfidence 0.7.

async/no-serial-independent-work ​

Reviews async functions with at least two directly awaited calls. It reports only when local evidence shows the operations can start together without changing data, side-effect, error, transaction, lock, rate-limit, or ordering behavior. Options: threshold { warning: 0.9, error: 0.97 }, minConfidence 0.7.

async/require-cancellation-propagation ​

Reviews explicit AbortSignal contracts that call recognized platform fetch. It checks whether the caller's signal is forwarded, including when signals are composed. Options: threshold { warning: 0.9, error: 0.97 }, minConfidence 0.7.

async/require-race-loser-cleanup ​

Reviews native Promise.race and Promise.any calls for locally created work whose losing branches continue without cancellation, settlement observation, or cleanup. Caller-owned and visibly harmless inputs are accepted.

async/require-abort-listener-cleanup ​

Reviews literal abort listeners on signal-like receivers. One-shot listeners and visible removal or disposal are accepted; unresolved ownership or listener lifetime causes abstention.

async/no-unobserved-async-work ​

Reviews conservatively selected promise-producing calls whose result is discarded. Awaiting, returning, chaining, aggregating, or deliberately marking fire-and-forget work with void counts as observation. Calls with unresolved return contracts, framework-managed lifetimes, or otherwise ambiguous ownership cause abstention.

async/no-async-initialization ​

Reviews constructors that visibly start asynchronous work before an explicit lifecycle boundary can observe readiness or failure. Explicit startup factories and readiness contracts are accepted. It abstains when framework bootstrapping, generated code, or an opaque helper owns initialization.

ts
rules: {
  "async/require-cancellation-propagation": [
    "warn",
    { threshold: { warning: 0.95, error: 0.99 } },
  ],
}

Released under the MIT License.