zesty-baas
v1.0.0
Published
Zesty BaaS - Framework Serverless para Cloudflare Workers com D1, Hono e Autenticação Nativa.
Downloads
16
Maintainers
Readme
Zesty BaaS Framework 🚀
O Zesty BaaS é um framework Backend-as-a-Service de altíssimo desempenho, construído nativamente para o Edge (Cloudflare Workers). Ele unifica Autenticação, Banco de Dados (D1) e Roteamento Avançado em uma DX (Developer Experience) impecável.
🧩 Arquitetura 100% Modular (Tree-Shaking)
Você perguntou: "Se eu quiser usar apenas Auth, ou apenas Banco, preciso baixar tudo?"
A resposta é: Você baixa o pacote, mas o seu aplicativo só carrega o que usar!
O Zesty é projetado com exportações modulares e suporta Tree-Shaking. Isso significa que o compilador do Cloudflare (Wrangler) vai analisar o seu código e descartar completamente qualquer módulo do Zesty que você não tenha importado.
- Quer usar só o Auth? Importe apenas o
getAuth. O peso do ZestyRouter não entrará no seu projeto. - Quer usar só o Banco? Importe apenas o
getDbClient. - Quer a experiência completa? Importe o
ZestyRouter.
Você tem liberdade total para acoplar ou desacoplar ferramentas.
🛠 Recursos do Zesty BaaS
1. ZestyRouter (Controller Pattern)
Um motor de roteamento ultra-declarativo construído sobre o Hono.
- Validação Nativa (Zod): Valida corpos de requisição antes de bater no seu código.
- RBAC Integrado: Proteja rotas com papéis de usuário (
user,tenant_admin,super_admin) passando apenas um arrayrbac: ["tenant_admin"]. - Try/Catch Global: Chega de escrever dezenas de blocos
try/catch. Erros não tratados viram automaticamente respostas500limpas. - Injeção de Dependência: O usuário autenticado, o banco de dados e o corpo validado já são injetados diretamente na sua função.
- Idempotência Granular: Rotas
POSTePUTexigem a chavex-idempotency-keypara prevenir duplicidades, mas você pode desativar isso por rota usandoidempotent: false.
2. Autenticação Core & Steam OpenID (Better Auth Edge)
- Multi-Tenant: Isolamento completo de usuários por
tenantId. - JWT no Edge: Login sem estado (stateless) para máxima velocidade em CDNs.
- Steam Plugin (Nativo Zesty): Autenticação OAuth OpenID 2.0 nativa direto com os servidores da Valve. O Zesty valida a assinatura, busca o Avatar e o Username na
Steam Web APIe cria o tenant de forma isolada!
3. Banco de Dados (D1 + Drizzle ORM)
- Tipagem Forte: O banco retorna objetos TypeScript com base no schema.
- Consistência Read-After-Write (Bookmarks): Lida com o cache distribuído do D1 automaticamente.
4. ZestyStorage (Cloudflare R2 + AWS S3 API)
- Uploads de Assets Gigantes: Esqueça o limite de 100MB do Cloudflare Worker. O
ZestyStoragegera URLs pré-assinadas (Presigned URLs) criptograficamente seguras para o seu jogo (ou frontend) fazer upload e download diretos do R2! - Isolamento de Tenants no Storage: Usuários não conseguem acessar nem sobrescrever pastas de outros tenants, garantido pela assinatura da AWS V4.
📖 Mini Tutorial: Do Zero à API Completa
Veja como é simples inicializar um servidor com Banco, Auth, Storage e uma API segura.
Passo 1: Inicializando o Zesty
Crie o seu ponto de entrada (ex: src/index.ts) e instancie o servidor com suas opções globais.
import { createZestyApp } from "./core";
import { financesApp } from "./routes/finances";
import { storageApp } from "./routes/storage";
import { SteamAuthPlugin } from "./core/auth/steamPlugin";
const app = createZestyApp({
jwtSecret: (env) => env.JWT_SECRET,
d1Binding: (env) => env.DB,
// R2 Config (S3 Compatível)
r2Credentials: {
accountId: "SUA_ACCOUNT_ID",
accessKeyId: "CHAVE_R2",
secretAccessKey: "SECRET_R2",
bucketName: "assets"
},
auth: {
plugins: [
// Acopla o Plugin Nativo da Steam!
SteamAuthPlugin({
realm: "https://api.seusaas.com",
returnUrl: "https://api.seusaas.com/steam/callback",
apiKey: "SUA_STEAM_API_KEY_DA_VALVE" // Necessário para puxar avatar
})
]
}
});
// Acopla as rotas
app.route("/finances", financesApp);
app.route("/storage", storageApp);
export default app;Passo 2: Roteador, Validação Zod e Idempotência
Na sua rota (src/routes/storage.ts), o ZestyRouter faz a mágica. Exemplo de rota de Upload/Download:
import { ZestyRouter, z, ZestyStorage } from "../core";
const storageApp = new ZestyRouter();
const presignSchema = z.object({
filename: z.string().min(1),
expiresInSeconds: z.number().optional()
});
// O Front/Unreal pedirá o Link Seguro por aqui
storageApp.zestyPost("/presign", {
auth: true,
body: presignSchema,
idempotent: false // Desativa idempotência para requisições rápidas
}, async (c, { user, storageCredentials, body }) => {
// ZestyStorage injeta o tenant automaticamente: a pasta gerada será "tenantId/filename"
const zestyStorage = new ZestyStorage(c.var.storage, user.tenantId, storageCredentials);
// Cria URL de assinatura AWS v4 com 1 linha!
const result = await zestyStorage.createPresignedUploadUrl(body.filename, body.expiresInSeconds);
return c.json(result, 201);
});
export { storageApp };🎮 Integração Frontend & Unreal Engine
Como a sua Engine (ou SDK Web) vai interagir com as URLs Assinadas do ZestyStorage e com a Autenticação da Steam?
Exemplo 1: Autenticação via Steam (OpenID)
Na Unreal Engine (via WebBrowser widget) ou no Navegador padrão, basta abrir a URL para iniciar a jornada:
// O navegador redireciona para a página verde oficial da Steam
window.location.href = "https://api.seusaas.com/steam/login";
// Quando o usuário fizer login lá, ele será devolvido para /steam/callback
// O backend vai validar a assinatura da Valve, criar o JWT e logá-lo!Exemplo 2: Upload de arquivo gigante (.pak) com Progresso
Seja no seu SDK Frontend Web ou na biblioteca HTTP do C++ (Unreal), o fluxo é o mesmo:
// 1. Pede a URL mágica de upload pro Zesty
const res = await fetch("https://api.seusaas.com/storage/presign", {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": `Bearer MEU_TOKEN` },
body: JSON.stringify({ filename: "massive_patch.pak" }) // Zesty crava o tenantId na url!
});
const data = await res.json();
// data.url contém o link "https://meubucket.r2...X-Amz-Signature=..."
// 2. Faz o Upload direto no Storage (Bypassando os 100MB do Worker)
const xhr = new XMLHttpRequest(); // Na Unreal seria IHttpRequest->ProcessRequest()
xhr.upload.addEventListener("progress", (e) => {
let pct = Math.round((e.loaded / e.total) * 100);
console.log("Enviando na Velocidade da Luz: " + pct + "%"); // Barra de UI
});
xhr.open("PUT", data.url, true);
xhr.setRequestHeader("Content-Type", "application/octet-stream"); // Obrigatório bater com a assinatura!
xhr.send(arquivoPakGigante); // Transfere 2GB sem lag no servidor web!Exemplo 3: Download Direto e Seguro (.pak)
Não envie requisições pesadas de download por dentro do ZestyRouter. Gire uma URL de download!
const res = await fetch("https://api.seusaas.com/storage/presign-download", {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": `Bearer MEU_TOKEN` },
body: JSON.stringify({ filename: "massive_patch.pak" })
});
const data = await res.json();
// Inicie o download imediatamente (Stream 100% hospedado no R2!)
window.location.href = data.url; 🔒 Segurança Zesty Integrada
Apenas usando os métodos declarativos .zestyGet e .zestyPost, seu App automaticamente possui proteção contra:
- Mass Assignment: O Zod ignora chaves extras no JSON.
- SQL Injection: O Drizzle ORM usa bind parameters.
- BOLA e IDOR: O isolamento via
user.tenantIdprevine acesso a dados alheios em banco e em arquivos do R2. - Idempotency: Requisições
POSTrepetidas por falha de rede são bloqueadas. - Signature Forgery: O plugin Steam verifica a URL callback nativamente contra invasores tentando forjar OpenID.
