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

@suluk/effect

v0.16.0

Published

Effect-native routes for the v4 contract: `sulukFn` — a composable unit carrying a SLICE of the core `Request` — composed ONLY through `sulukFmt` (linear pipeline) / `sulukFmt.all` (fan-out → a derived `{ a, b }` body). Every layer (MODEL/SERVICE/ROUTE) i

Readme

@suluk/effect

Effect-native routes whose v4 contract responses are DERIVED from the handler's types. Stop returning generic ProblemDetails for every error and hardcoding 200 — let the Effect error channel and the success type bubble up.

New here? Read ../../AUTHORING.md first — the one-page mental model (one unit sulukFn, two compositions sulukFmt / sulukFmt.all, one projection sulukRoute). This README covers effectRoute, the direct single-route primitive that sulukRoute projects onto — reach for it when a route has no model/service layering.

The two problems it solves

  1. Detailed error types, not generic ProblemDetails. Define errors as typed Effect Data.TaggedErrors carrying their HTTP status + a body schema. A route lists the errors it can produce; each becomes a distinct, typed response (its own status + schema) in the emitted v4 document. Because Effect unions the error channel automatically as you compose functions, the set of errors a route can produce is its E type — and effectRoute's signature type-enforces that every declared error matches: you can't under-declare the ways it throws.

  2. Success status inference, not a hardcoded 200. The success status is derived from the method (POST→201, DELETE→204, else 200), overridable per route, and per-request via respond() / Created() / … — so it reflects the semantics.

Usage

import { Effect } from "effect";
import { z } from "zod";
import { httpError, effectRoute } from "@suluk/effect";

// a typed error: its HTTP status + the ACTUAL body shape the caller receives
const InsufficientCredits = httpError("InsufficientCredits", 402, z.object({ required: z.number(), balance: z.number() }));

const { contract, handler } = effectRoute({
  method: "post", path: "/api/credits/debit", name: "debitCredits", scopes: ["credits:write"],
  ok: { schema: z.object({ ok: z.literal(true) }) },   // 201 by convention (POST); override with ok.status
  errors: [InsufficientCredits],                        // → a typed 402 response { required, balance }
  run: (c) =>
    Effect.gen(function* () {
      const { userId, amount } = yield* readBody(c);
      const ok = yield* Credits.debit(userId, amount);  // a service that fails with InsufficientCredits → bubbles to E
      if (!ok) return yield* new InsufficientCredits({ required: amount, balance: yield* Credits.balance(userId) });
      return { ok: true as const };
    }),
});

// spread `contract` into your route list (emitV4 / Scalar / SDK now show the typed 402, not ProblemDetails);
// mount `handler` at post /api/credits/debit.
  • run fails only with the declared errorsEffect<Body, InstanceType<errors[number]>, never>. Declaring fewer than the code throws is a type error (the error channel is exact). The never requirement means the handler is fully provided (Effect.provide(...) your layers before returning).
  • A defect (Effect.die, an unexpected throw) → a 500 ProblemDetails, surfaced not swallowed — a handler can always die.
  • The runtime maps a tagged failure to its status + its typed body (exactly the error's schema fields).

What emitV4 produces

The route's responses carry the success + one typed response per error, so the v4 document (and everything derived from it — Scalar, the SDK, testgen) shows the actual error shapes. The always-synthesized 500 (and 401/403 for scoped ops) stay generic ProblemDetails — those are the failure modes any handler shares.

Peer deps: effect ^3, hono ^4, zod ^4. CANDIDATE tooling.