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

@guapocado/better-auth

v0.0.1

Published

Better Auth plugin for Guapocado billing. It keeps `@guapocado/sdk` as a small framework-agnostic primitives package and layers Better Auth-specific session mapping here.

Downloads

71

Readme

@guapocado/better-auth

Better Auth plugin for Guapocado billing. It keeps @guapocado/sdk as a small framework-agnostic primitives package and layers Better Auth-specific session mapping here.

npm install @guapocado/better-auth
import { guapocado } from "@guapocado/better-auth";
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";

export const auth = betterAuth({
  plugins: [
    organization({
      teams: {
        enabled: true,
      },
    }),
    guapocado({
      apiKey: process.env.GUAPOCADO_API_KEY!,
      customerId: "organization", // "user" | "organization" | "team"
      webhook: {
        path: "/guap",
      },
    }),
  ],
});

The plugin adds authenticated Guapocado endpoints to auth.api:

export async function GET(request: Request) {
  const result = await auth.api.guapocadoHas({
    headers: request.headers,
    body: { key: "advanced-analytics" },
  });

  return Response.json(result);
}

For browser code, install the Guapocado client plugin into Better Auth's client:

import { guapocadoClient } from "@guapocado/better-auth/client";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
  plugins: [guapocadoClient()],
});

const usage = await authClient.guapocado.usage.consume("api-calls", 1);
const checkout = await authClient.guapocado.checkout.create({
  productKey: "pro",
  successUrl: `${location.origin}/billing/success`,
  cancelUrl: `${location.origin}/billing`,
});

The client plugin exposes typed customer, context, entitlement, limit, usage, plans, subscription, and checkout actions under authClient.guapocado. Checkout uses productKey for both recurring and one-time products. planKey is still accepted as a deprecated alias for recurring products.

Use customer.sync() when the current Better Auth session should create or update the corresponding Guapocado customer:

const customer = await authClient.guapocado.customer.sync();

Usage endpoints follow the same naming:

await auth.api.guapocadoUsageBalance({
  headers: request.headers,
  body: { key: "api-calls" },
});

await auth.api.guapocadoUsageConsume({
  headers: request.headers,
  body: { key: "api-calls", amount: 1 },
});

await auth.api.guapocadoUsageRefund({
  headers: request.headers,
  body: { key: "api-calls", amount: 1 },
});

By default, the plugin maps the selected user, organization, or team ID to customerId. Override mapCustomerId if you store dedicated Guapocado customer IDs.

customerId: "organization" requires Better Auth's organization() plugin. customerId: "team" requires organization({ teams: { enabled: true } }). customerId: "user" works with Better Auth core sessions only.

Webhook receiver

The server plugin adds GET/POST /api/auth/guap by default. GET resolves the public URL from the request and registers it with Guapocado using the server API key. The endpoint is created disabled in the Guapocado dashboard, so it must be approved before events are forwarded.

Declare the forwarding intent in billing.config.ts:

export default defineBilling({
  // entitlements and products...
  webhooks: {
    devTunnel: true,
    forwarding: [
      {
        key: "better-auth",
        path: "/api/auth/guap",
        events: "*",
        integration: "better-auth",
        autoRegister: true,
      },
    ],
  },
});

events: "*" subscribes to all Guapocado domain snapshot events: customer.updated, subscription.updated, purchase.completed, purchase.updated, entitlements.updated, invoice.updated, and usage.updated. These are emitted after Stripe has been projected into Guapocado state. Raw Stripe event IDs are kept as internal source metadata, so receivers can store verified Guapocado events without replaying Stripe logic.

With devTunnel: true, guap listen --sandbox --dev can start the dev-only relay and forward approved sandbox events to your local receiver.

Then enable the receiver in the Better Auth plugin. No webhook signing secret is required in user config; the plugin registers the receiver with Guapocado and stores the returned signing secret in its plugin table.

guapocado({
  apiKey: process.env.GUAPOCADO_API_KEY!,
  customerId: "user",
  webhook: {
    path: "/guap",
    events: "*",
    autoRegister: true,
  },
});

Use webhook.publicUrl if your app sits behind a proxy and the request URL is not the externally reachable URL.

For custom identity models, resolve the customerId yourself:

guapocado({
  apiKey: process.env.GUAPOCADO_API_KEY!,
  resolveCustomerId: async (session) => String(session.session?.workspaceId),
});