- TypeScript 59.5%
- JavaScript 22.2%
- Python 7.3%
- PLpgSQL 4.3%
- Astro 3.9%
- Other 2.8%
| .github/workflows | ||
| apps | ||
| docs | ||
| e2e | ||
| infra | ||
| packages | ||
| supabase | ||
| .editorconfig | ||
| .env.example | ||
| .env.install.example | ||
| .gitattributes | ||
| .gitignore | ||
| biome.json | ||
| package.json | ||
| playwright.config.cjs | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.base.json | ||
| turbo.json | ||
runv-square
Monorepo terminal-first para “squares” (praças) públicas/privadas no ecossistema runv.club.
Fonte canónica: Markdown + frontmatter + blocos fenced (ascii, ansi, links, note). ANSI/HTML são alvos de render, não o modelo de dados.
Stack
- pnpm workspaces + Turborepo (
turbo.jsoncomenvMode: "loose"para.envchegar aosdevtasks, p.ex. webServer do Playwright) - Supabase (Postgres + Auth + Storage) — sem SQLite/Prisma para dados de negócio
- apps/api: Fastify
- apps/web: Astro (SSR, leitura pública)
- apps/worker: jobs de render + snapshots
- apps/cli: Commander +
@runv-square/sdk+@runv-square/linux-identity(resolução de utilizador Linux) @runv-square/identity-adapters: portas tipadas (stub) para um futurorunv-server/ bridge SSH@runv-square/i18n: UI pt-BR en + mensagens API/CLI (conteúdo de posts multilingue não é obrigatório em v1)- Biome + Vitest + TypeScript strict
Desenvolvimento local e segurança
- O stack
supabase startusa chaves JWT conhecidas e expõe Studio / pgMeta / APIs sem o mesmo modelo de auth que produção — trata como máquina de dev apenas; ver Segurança do Supabase local em docs/local-dev.md. - API e Astro dev escutam por defeito em
127.0.0.1;API_HOST=0.0.0.0só quando precisares de LAN ou contentores. db resetcom erro 502 após migrações: ver a tabela Troubleshooting em docs/local-dev.md.pnpm smoke:local: o.envna raiz deve apontar para o stack local (SUPABASE_URL=http://127.0.0.1:54321e chaves desupabase status); ver.env.example. Evita trabalhar só em/mnt/z/...ou outros mounts lentos no WSL — preferir clone em~/...(detalhes em docs/local-dev.md).pnpm installcorre umpostinstallna raiz que garante o Chromium do Playwright (necessário parapnpm test:e2e/pnpm smoke:local) além do CLI local do Supabase.
Chaves Supabase (env)
| Ambiente | Variáveis | Uso |
|---|---|---|
| Hosted (produção) | SUPABASE_PUBLISHABLE_KEY, SUPABASE_SECRET_KEY |
Alinhado às chaves “anon” / “service role” do dashboard |
Local (supabase start) |
SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY |
Saídas de supabase status |
- Nunca colocar
SUPABASE_SECRET_KEY/SUPABASE_SERVICE_ROLE_KEYno frontend ou bundles client. - Web só chama leituras públicas (ex.:
API_URL+ endpointsGET).
Comandos (raiz)
| Script | Descrição |
|---|---|
pnpm dev |
turbo dev (API, worker, web em paralelo) |
pnpm build |
Build de todos os pacotes |
pnpm lint |
Biome |
pnpm typecheck |
TypeScript |
pnpm test |
Vitest (parser/renderers) |
pnpm db:start |
supabase start (CLI instalado pelo pnpm install; não precisa de supabase global) |
pnpm db:stop |
supabase stop |
pnpm db:restart |
supabase stop && supabase start (útil após db:reset falhar com 502 apesar do SQL ter corrido) |
pnpm db:reset |
Reset com retry: se falhar (ex. 502 no storage após reiniciar contentores), faz stop → start e volta a tentar |
pnpm db:reset:raw |
supabase db reset sem retry (uma única tentativa) |
pnpm db:reset:debug |
Igual ao db:reset mas com --debug no CLI Supabase em cada tentativa |
pnpm db:typegen:local |
Gera packages/db-types/src/database.types.ts a partir do stack local |
pnpm db:typegen:project |
Gera tipos a partir do projeto hosted (SUPABASE_PROJECT_REF) |
pnpm test:e2e |
Playwright E2E (requer Supabase local + .env completo; ver docs) |
pnpm smoke:local |
db:start + db:reset + typegen + E2E (Docker acessível); a API do smoke usa 3011 por defeito (SMOKE_API_PORT). O runner playwright-smoke.mjs define ENABLE_DEV_PROTOTYPE=true por defeito (global-setup cria boletim-da-escada, Astro mostra o herói na home). Para smoke sem protótipo: ENABLE_DEV_PROTOTYPE=false pnpm smoke:local |
pnpm smoke:local:debug |
Igual ao smoke, mas db:reset com --debug (Supabase); não confundir com pnpm smoke:local --debug (só Playwright) |
pnpm smoke:prototype |
Equivalente ao fluxo de smoke:local com modo desenvolvimento explícito (ENABLE_DEV_PROTOTYPE=true no ambiente antes do pnpm); mantido como atalho legível |
pnpm prototype:seed |
Só corre com ENABLE_DEV_PROTOTYPE=true: insere o square de protótipo e posts (service role); caso contrário sai sem tocar na BD |
pnpm prototype:bootstrap |
db:start + db:reset + db:typegen:local + seed de protótipo (flag ligada só no passo do seed) |
Ver Dev prototype — nunca definir ENABLE_DEV_PROTOTYPE em produção.
Test readiness
Critérios para considerar o projeto pronto para testes de integração local (todos devem passar):
pnpm build— build do monorepopnpm lint— Biomepnpm typecheck— TypeScriptpnpm test— testes unitários (incl. Vitest na API)pnpm test:e2e— E2E (comsupabase start+ chaves no.env; com stack local tambémSUPABASE_JWT_SECRETpara HS256; hosted pode omitir — JWKS; ver docs/local-dev.md)- Fluxo seed E2E (
e2e/global-setup.cjs) — perfil, square pública, draft, publicado, job de render - Worker processa publish/render (snapshot HTML/ANSI disponível via API)
- Rotas web localizadas (
/en/...,/pt-br/...) mostram conteúdo publicado - Rotas API mutáveis exigem JWT verificado (não stub)
Resumo da implementação: did2.md.
Typegen
Após pnpm db:reset ou com o stack local a correr:
pnpm db:typegen:local
Isto mantém packages/db-types como fonte única de tipos de linhas SQL para API, worker e SDK.
Identidade local (Debian / Linux)
- API com
RUNV_LOCAL_IDENTITY_SECRET(obrigatório seNODE_ENV=production; em dev a API usa um valor inseguro por defeito — ver docs/local-dev.md). - No mesmo host que a API (ou túnel só para loopback), corre
square init(alias:runv-square init) comAPI_URL,RUNV_LOCAL_IDENTITY_SECRETe stack Supabase acessível. O CLI resolve o utilizador viagetent passwd/passwde chamaPOST /identity/local/init(só aceite de 127.0.0.1 / ::1 + segredo no header). - Grava a sessão:
export RUNV_ACCESS_TOKEN="..."(impresso no stderr após o JSON de resposta). - Comandos autenticados:
square whoami,square profile:sync,square square:personal,square square:create,square posts:*.
O CLI é instalado com dois nomes:
squarepara uso diáriorunv-squarecomo nome explícito/compatível
Ao correr apenas square, o CLI mostra um onboarding colorido e localizado, explicando o que é um square, o square pessoal de cada utilizador e o fluxo básico para publicar pelo terminal.
Fluxo rápido de publicação por ficheiro:
square nota.md --publish
square nota.ans --square mural-da-oficina --visibility public --publish
square squares:view mural-da-oficina
square posts:read mural-da-oficina nota
square posts:list
square posts:update ID --title "Novo título"
square posts:delete ID
Fluxo rápido de administração local do host:
square admin:profiles:list
square admin:squares:list
square admin:posts:list --status draft
square admin:posts:read POST_ID
square admin:posts:update POST_ID --publish
square admin:jobs:list --status failed
square admin:jobs:requeue POST_ID --target all
Ver também docs/future-runv-server-identity.md (não implementado).
Documentação
- docs/architecture.md
- docs/domain-model.md
- docs/i18n-and-extensions.md
- docs/local-dev.md
- docs/install.md
- docs/storage-baseline.md
- docs/deploy-debian-13.md
- docs/future-runv-server-identity.md
- docs/admin.md
- docs/user.md
Licença
runverse