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

@whodo/app-sdk

v0.4.1

Published

SDK oficial para apps construidos na plataforma Whodo. Acesso a entidades, autenticacao e funcoes serverless via cliente unico.

Readme

@whodo/app-sdk

npm version License: MIT

SDK oficial dos apps construidos na plataforma Whodo — plataforma onde aplicacoes React sao geradas via prompt de IA.

Status: 0.3.x — funcional + backend integrado + URL canonica RESTful. Cliente HTTP, entidades, autenticacao, funcoes, telemetria, retry e suporte a import.meta.env.VITE_WHODO_* implementados (144 testes). URL pattern com appId no path (/api/apps/<appId>/entities/<Name>) — RESTful, debugavel, compativel com cache/CDN. Sistema de permissoes por entidade (public, authenticated, owner, admin). Templates declaram permissoes no clone via getSeedPermissions(). Veja backend/skills/SDK_INTEGRATION.md pro guia completo de integracao backend.

Breaking change vs 0.2.x: URL agora inclui appId no path. SDK 0.2.x chamava /api/apps/entities/X com X-App-Id header; 0.3.x chama /api/apps/<appId>/entities/X. O backend mantem bridge transicional pra aceitar 0.2.x temporariamente, mas apps novos devem usar 0.3.x.


O que este SDK faz

Cada app gerado pela Whodo precisa de quatro coisas no runtime:

  1. Entidades persistentes — coleções de dados que sobrevivem a reload e sao compartilhadas entre usuarios
  2. Autenticacao de usuarios finais — login/logout/sessao com JWT
  3. Funcoes serverless — codigo que precisa rodar com privilegios server-side (validar pagamento, chamar API com chave secreta, etc.)
  4. Observabilidade — telemetria de requests para debug no painel da plataforma

O SDK expoe tudo isso por uma unica instancia configurada com appId + token. Apps escrevem o minimo de codigo possivel: a IA da plataforma copia padroes diretamente do README e dos tipos.


Instalacao

npm install @whodo/app-sdk

Compativel com browsers modernos (ES2022+) e Node 18+. ESM-only — sem build CJS.


Inicializacao

A forma canonica usada pelo scaffold da Whodo:

// lib/whodoClient.ts
import { createClient } from '@whodo/app-sdk';

export const whodo = createClient({
  appId: import.meta.env.VITE_WHODO_APP_ID,
  appBaseUrl: 'https://app.whodo.com.br',
});

createClient resolve appId e token em ordem de prioridade:

  1. Override explicito na config
  2. Query params da URL (?app_id=...&access_token=...) — tokens vindos por URL sao removidos via history.replaceState
  3. localStorage (whodo_app_id, whodo_access_token)
  4. Defaults (geralmente import.meta.env.VITE_WHODO_*)

Esse encadeamento permite o mesmo bundle servir cenarios diferentes (preview no dashboard, app publicado, embed em terceiros) sem reconfiguracao.


API completa

whodo.entities

Acesso CRUD a colecoes do banco do app. Toda propriedade do entities e resolvida via Proxy para uma EntityCollection — nao ha lista finita, qualquer nome funciona. As mesmas colecoes retornam a mesma instancia (whodo.entities.Order === whodo.entities.Order).

// Listar (com sort opcional, formato '-campo' para desc)
const all = await whodo.entities.Order.list();
const recent = await whodo.entities.Order.list('-_created', 50);

// Filtrar (igualdade direta na v0.1; operadores avancados na v0.3)
const pending = await whodo.entities.Order.filter({ status: 'pending' });

// Buscar por ID
const order = await whodo.entities.Order.get('abc-123');

// Criar
const created = await whodo.entities.Order.create({ total: 100, status: 'pending' });

// Atualizar parcialmente (PATCH)
const updated = await whodo.entities.Order.update(created._id, { status: 'paid' });

// Deletar
await whodo.entities.Order.delete(created._id);

| Metodo | HTTP | Path | |---|---|---| | list(sort?, limit?, skip?) | GET | /entities/:name | | filter(query, sort?, limit?, skip?) | GET | /entities/:name?q=... | | get(id) | GET | /entities/:name/:id | | create(data) | POST | /entities/:name | | update(id, data) | PATCH | /entities/:name/:id | | delete(id) | DELETE | /entities/:name/:id |

Todo registro tem campos auto-preenchidos pelo backend: _id, _created, _updated.

whodo.auth

Autenticacao baseada em JWT. Tokens viajam em Authorization: Bearer ... e sao persistidos em localStorage (chave whodo_access_token).

// Login — JWT e auto-persistido; a proxima request ja vai autenticada
const session = await whodo.auth.login('[email protected]', 'senha');
console.log(session.user, session.token);

// Usuario logado atualmente
const me = await whodo.auth.me();

// Boolean rapido (faz roundtrip ao /auth/me)
const isLogged = await whodo.auth.isAuthenticated();

// Logout — sempre limpa storage local, mesmo se servidor falhar
await whodo.auth.logout();

| Metodo | HTTP | Path | |---|---|---| | me() | GET | /auth/me | | login(email, password) | POST | /auth/login | | logout() | POST | /auth/logout | | isAuthenticated() | GET | /auth/me (try/catch) |

whodo.functions

Invocacao de codigo serverless. Suporta payload JSON ou FormData (uploads).

const result = await whodo.functions.invoke<{ paymentId: string }>(
  'processPayment',
  { amount: 100, customerId: 'cust_1' },
);

// Upload via FormData (sem JSON.stringify automatico)
const formData = new FormData();
formData.append('file', fileFromInput);
const upload = await whodo.functions.invoke<{ url: string }>('uploadFile', formData);

| Metodo | HTTP | Path | |---|---|---| | invoke<T>(name, payload?) | POST | /functions/:name |

Lifecycle

// Sobrescrever ou limpar token em runtime
whodo.setToken('new-jwt');
whodo.setToken(null);  // tambem remove de localStorage

// Inspecionar config atual (frozen)
const config = whodo.getConfig();
console.log(config.appId, config.serverUrl, config.token);

// Cleanup ao desmontar (idempotente)
whodo.cleanup();

Configuracao completa

createClient({
  appId: 'meu-app',                      // obrigatorio
  token: 'jwt-inicial',                  // opcional; lido tambem de URL/storage
  appBaseUrl: 'https://app.whodo.com.br',    // default
  serverUrl: 'https://app.whodo.com.br', // override do path da API; default eh `${appBaseUrl}/api`
  requiresAuth: false,                   // se true, redireciona pra login quando sem token
  headers: { 'X-Custom': 'value' },      // headers extras em toda request
  fetch: customFetch,                    // override do fetch global (SSR, testing)
  options: {
    onError: (err) => report(err),       // hook de observabilidade
    telemetry: {
      enabled: true,                     // default true em iframe, no-op fora
      targetOrigin: 'https://app.whodo.com.br', // origem permitida; '*' apenas em dev
    },
  },
});

Tratamento de erros

Todo erro lancado pelo SDK e instancia de WhodoError:

import { WhodoError } from '@whodo/app-sdk';

try {
  await whodo.entities.Order.get('nao-existe');
} catch (err) {
  if (err instanceof WhodoError) {
    console.error(err.code, err.status, err.message, err.requestId);
    if (err.code === 'unauthorized') {
      // redireciona pra login
    }
  }
  throw err;
}

| Campo | Tipo | Descricao | |---|---|---| | message | string | Mensagem PT-BR pronta pra UI | | status | number | HTTP status; 0 para erros nao-HTTP | | code | string | Codigo curto e estavel | | data | unknown | Payload original do servidor | | requestId | string | UUID gerado pelo cliente, correlaciona com logs | | cause | unknown | Erro original (rede/parse) quando aplicavel |

Codigos comuns

| code | status | Quando | |---|---|---| | invalid_config | 0 | appId ausente ou invalido em createClient | | unauthorized | 401 | Token ausente, expirado ou revogado | | forbidden | 403 | Sem permissao no app/entidade | | not_found | 404 | Recurso inexistente | | validation_error | 422 | Payload invalido para a entidade/funcao | | rate_limited | 429 | Limite de requests atingido | | server_error | 5xx | Falha do backend (com retry automatico) | | network_error | 0 | Falha de rede (TypeError do fetch) | | aborted | 0 | AbortSignal disparado | | invalid_json_response | 2xx | 200 com body nao-JSON | | not_implemented | 501 | Endpoint nao implementado no backend ainda |

WhodoError.toJSON() produz uma representacao log-safe sem cause/stack.


Retry e telemetria

Retry automatico ocorre em respostas HTTP 5xx e erros de rede (TypeError). Politica default: 3 tentativas, exponential backoff (200ms, 400ms, 800ms) com jitter de 50-100% para evitar thundering herd. NUNCA retenta 4xx — bug do cliente nao se resolve repetindo.

Telemetria emite eventos whodo:request:start e whodo:request:end via postMessage para window.parent quando o SDK roda em iframe (caso do preview do dashboard Whodo). Cada evento inclui requestId, url, method, status, durationMs. Fora de iframe, e no-op.

Em producao do dashboard, configure options.telemetry.targetOrigin para 'https://app.whodo.com.br' (origem especifica). O default '*' e apenas para desenvolvimento.


Storage e seguranca

Token e armazenado em localStorage:

  • whodo_access_token — JWT corrente
  • whodo_app_id — ID do app (resolvido apenas uma vez por origin)
  • whodo_app_base_url — URL da plataforma
  • whodo_from_url — URL de origem (para redirect pos-login)

Decisao consciente: localStorage em vez de cookie HttpOnly. Vantagem: funciona em qualquer cenario de embed, qualquer origem. Tradeoff: vulneravel a XSS no app gerado. Mitigacoes server-side: TTL curto no JWT (24h), revoke list em Redis, rate limit por token, sessoes ativas inspecionaveis. Para apps com dados sensiveis (financeiro, saude), revisitar essa decisao.

?clear_access_token=true na URL forca remocao do token (util para fluxo de logout iniciado por servico externo).

Tokens vindos por URL (?access_token=...) sao removidos via history.replaceState apos serem persistidos — evita aparecer em Referer headers, screenshots e logs do browser.


TypeScript

Tipagem completa via generics em entities:

interface Order {
  customer_name: string;
  total: number;
  status: 'pending' | 'paid' | 'cancelled';
}

const orders = await whodo.entities.Order.list<Order>();
//    ^? Array<Order & BaseRecord>

const newOrder = await whodo.entities.Order.create<Order>({
  customer_name: 'Maria',
  total: 49.9,
  status: 'pending',
});

BaseRecord adiciona _id, _created, _updated automaticamente.


Browser support

  • ESM-only (sem CJS bundle)
  • ES2022 target — Chrome 94+, Firefox 93+, Safari 16.4+, Edge 94+
  • Node 18+ (com fetch nativo)
  • Compativel com SSR (Next.js, Remix, Astro) via injecao de fetch customizado

Sem dependencias runtime — bundle final do app inclui apenas o SDK (~19 KB ESM minified pre-gzip; ~7 KB pos-gzip).


Desenvolvimento local

git clone <repo-url>
cd packages/whodo-app-sdk
npm install
npm run typecheck   # tsc --noEmit
npm test            # vitest run (135 testes)
npm run test:watch  # vitest watch mode
npm run build       # tsup -> dist/
npm run dev         # tsup --watch

Roadmap

| Versao | Conteudo | Status | |---|---|---| | 0.0.1-alpha | Surface publica + tipos estaveis | concluido | | 0.1.x | HTTP transport, entities CRUD, auth, functions, telemetry, retry | concluido | | 0.2.x | Backend integration: rotas REST, permission system, JWT site (TTL 24h), import.meta.env.VITE_WHODO_*, prefix /api/apps/ | concluido | | 0.3.x | URL canonica /api/apps/<appId>/... (appId no path, RESTful, debugavel). Templates declaram permissoes via getSeedPermissions(). Validacao de cross-app token replay no path | atual | | 0.4.x | Paginacao cursor-based + filter operators ($gt, $in, $regex) | depois | | 0.5.x | Functions com sandbox real + secrets management | depois | | 0.5.x | Realtime subscriptions via WebSocket | futuro | | 0.6.x | Custom domains + SSL automatico | futuro | | 0.7.x | Hardening: revoke list, audit log, refresh tokens, rate limit Redis | futuro | | 1.0.0 | API congelada, security audit, production-ready | TBD |


Manutencao via IA

Esse pacote tem documentacao orientada para agentes de IA / Claude Code em SKILL.md — cobre arquitetura, decisoes de design, gotchas, e guias do tipo "como adicionar X". Leia antes de modificar codigo aqui.


Licenca

MIT (c) 2026 Whodo.