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

@forjio/serront

v0.1.0

Published

Serront SDK — typed JS/TS client for the serront.com REST API. Sister to the Python + Go SDKs.

Readme

@forjio/serront

Typed JS/TS client for the serront.com services-storefront REST API.

npm install @forjio/serront
import fs from "node:fs";
import { SerrontClient } from "@forjio/serront";

// Bearer token from `token` or the SERRONT_TOKEN env var — use an
// sk_live_… API key from Dashboard → Settings → API keys.
const client = new SerrontClient({ token: "sk_live_xxx" });

// Storefront — the seller's public profile
const settings = await client.storefront.get(); // null until first put
await client.storefront.put({
  slug: "studio-renata",
  displayName: "Studio Renata",
  bio: "Brand & logo design studio.",
  whatsappNumber: "+628120000000",
  manualBankAccounts: [{ bankName: "BCA", accountNumber: "1234567890", accountHolder: "Renata" }],
  published: true,
});

// Services — the catalog (fixed / hourly / package pricing)
const services = await client.services.list();
const svc = await client.services.create({
  slug: "logo-design",
  name: "Logo design",
  pricingType: "package",
  packages: [
    { name: "Basic", priceIdr: 500_000 },
    { name: "Full identity", priceIdr: 2_500_000 },
  ],
});
await client.services.update(svc.id, { sortOrder: 1 });

// Orders — the order desk
const { orders, counts, cursor, hasMore } = await client.orders.list({
  status: "requested",
  paymentStatus: "payment_claimed",
  q: "wedding",
});
const order = await client.orders.get(orders[0].id); // + full thread
await client.orders.reply(order.id, { body: "On it!", isInternal: false });
await client.orders.update(order.id, { status: "confirmed", quotedPriceIdr: 750_000 });
await client.orders.confirmPayment(order.id);
const proof = await client.orders.downloadProof(order.id); // { data, contentType }

// Modules — Payment (Plugipay) / Marketing (Ripllo) integrations
const modules = await client.modules.get();
await client.modules.set({ payment: true });

// Ledger + payouts (Plugipay-held; Payment module required)
const balance = await client.ledger.balance();
const entries = await client.ledger.entries({ limit: 20 });
const payouts = await client.payouts.list({ status: "pending" });
const payout = await client.payouts.create({ amount: 1_000_000 });
await client.payouts.cancel(payout.id);

// API keys + webhook subscriptions
const { apiKeys } = await client.apiKeys.list();
const created = await client.apiKeys.create({ name: "ci" }); // created.key shown ONCE
const hook = await client.webhookSubscriptions.create({
  url: "https://example.com/serront-hook",
  events: ["serront.order.created.v1"],
}); // hook.secret shown ONCE

// Billing — current plan + upgrade checkout (tiers: free / starter / growth / business)
const { subscription, effectiveTier, tiers } = await client.billing.get();
const { hostedUrl } = await client.billing.checkout("starter"); // redirect the browser here

// Public (buyer) surface — no token required
const view = await client.public.getStorefront("studio-renata");
const placed = await client.public.createOrder("studio-renata", {
  serviceSlug: "logo-design",
  packageName: "Basic",
  buyerName: "Budi",
  buyerEmail: "[email protected]",
  discountCode: "WELCOME10", // Marketing module
});
const check = await client.public.validateDiscount("studio-renata", {
  code: "WELCOME10",
  priceIdr: 500_000,
});
const myOrder = await client.public.getOrder(placed.accessToken);
await client.public.replyOrder(placed.accessToken, { body: "Any update?" });
await client.public.uploadProof(placed.accessToken, {
  data: await fs.promises.readFile("transfer.png"),
  contentType: "image/png",
});
await client.public.claimPayment(placed.accessToken); // "I have transferred"
const pay = await client.public.pay(placed.accessToken); // Payment module → hostedUrl

Endpoints covered

| Resource | Methods | | --- | --- | | storefront | get, put (slug / display / bio / WhatsApp / bank accounts / branding / publish) | | services | list, create (403 LIMIT_REACHED past the tier's service limit), get, update, delete (409 while orders reference it) | | orders | list (status / paymentStatus / serviceId / q / limit / cursor + per-status counts), get, update (status and/or quotedPriceIdr), reply (with isInternal), confirmPayment, downloadProof | | modules | get, set (payment / marketing toggles; first enable provisions the partner workspace) | | ledger | balance, entries (cursor-paged; 409 PAYMENT_MODULE_DISABLED when off) | | payouts | list, create, cancel, balance, getBankAccount, updateBankAccount, markInTransit, markPaid, markFailed | | apiKeys | list, create (plaintext returned once), delete | | webhookSubscriptions | list, create (secret returned once), update (active), delete | | billing | get (subscription + effectiveTier + tier table), checkout(tier) → hosted checkout URL | | public | getStorefront, createOrder, validateDiscount, getOrder, replyOrder, claimPayment, pay, uploadProof (no token) |

Errors throw SerrontError carrying the API envelope's error.code (NOT_FOUND, VALIDATION_ERROR, LIMIT_REACHED, UPGRADE_REQUIRED, INVALID_TRANSITION, …), the HTTP status, and the meta.requestId.

See serront.com/docs/sdk/js for the full method reference.

Family

Sister to: