dunas

Começar

Instale o dunas, declare seus planos e cobre a primeira assinatura no sandbox.

Você precisa de um app Node com Postgres e de uma conta de teste em pelo menos um provedor.

Instale o pacote

npm install dunas pg

Configure as variáveis de ambiente

Coloque só as do provedor que você vai usar.

.env
DATABASE_URL=postgres://...

WOOVI_APP_ID=...

ABACATEPAY_API_KEY=...
ABACATEPAY_WEBHOOK_SECRET=...

CRON_SECRET=uma-string-longa-e-aleatoria

Declare os planos

Cada plano diz o que inclui. Aqui, o grátis manda 100 mensagens por mês e o Pro manda 5.000 e libera os modelos avançados.

billing/plans.ts
import { feature, plan } from "dunas"

export const messages = feature({ id: "messages", type: "metered" })
export const proModels = feature({ id: "pro_models", type: "boolean" })

export const free = plan({
  id: "free",
  default: true,
  includes: [messages({ limit: 100 })],
})

export const pro = plan({
  id: "pro",
  price: { amountInCents: 4_990, interval: "month" },
  includes: [messages({ limit: 5_000 }), proModels()],
})

Crie a instância

billing/dunas.ts
import { createDunas, pg, woovi } from "dunas"
import { Pool } from "pg"
import { free, pro } from "./plans"

export const billing = createDunas({
  database: pg(new Pool({ connectionString: process.env.DATABASE_URL })),
  plans: [free, pro],
  providers: [woovi({ appId: process.env.WOOVI_APP_ID, sandbox: true })],
  identify: (request) => getUser(request),
})

identify recebe a requisição e devolve quem é o cliente ({ id, name, email }) ou null. Ligue na autenticação que você já tem.

Usa Better Auth?

Troque por identify: fromBetterAuth(auth), importado de dunas/better-auth.

Crie as tabelas

await billing.migrate()

Cria as tabelas dunas_* no seu banco. Pode rodar a cada deploy: o que já existe não muda.

Monte a rota

Uma rota só atende o navegador, os webhooks dos provedores e o cron de renovações.

app/api/dunas/[...path]/route.ts
import { billing } from "@/billing/dunas"

export const GET = billing.handler
export const POST = billing.handler

Crie o cliente

No navegador, o cliente conversa com essa rota e herda os tipos do servidor.

lib/dunas-client.ts
import { createDunasClient } from "dunas/client"
import type { billing } from "@/billing/dunas"

export const dunas = createDunasClient<typeof billing>()

Pronto

O dunas está ligado. Agora:

Nesta página