Onboarding do desenvolvedor¶
Tutorial de onboarding para quem vai desenvolver no Slot2Sync: do clone do repositório até rodar o app, buildar, validar a qualidade do código e entender por onde começar.
Para a visão geral do produto, veja o
README.mddo repositório de código. Para arquitetura e decisões, comece por Arquitetura.
1. Pré-requisitos¶
O alvo de produção é Windows nativo. Instale, no Windows (PowerShell como Administrador):
| Ferramenta | Comando |
|---|---|
| Rust | winget install Rustlang.Rustup |
| Microsoft C++ Build Tools | winget install Microsoft.VisualStudio.2022.BuildTools → depois abra o VS Installer e marque a workload "Desenvolvimento para desktop com C++" |
| WebView2 | winget install Microsoft.EdgeWebView2Runtime (já incluso no Windows 10/11 atualizados) |
| Node.js | ≥ 20 LTS (verifique com node --version) |
Referência oficial: tauri.app/start/prerequisites.
Sobre WSL2: este repositório vive em
/mnt/c, masnpm run tauri dev/builddeve rodar no Windows nativo (PowerShell) — build dentro do WSL gera binário Linux, exige as libswebkit2gtke sofre com I/O lento do 9p. Edite o código onde preferir; comandoscargo check/test/clippyrodam bem no WSL (veja a seção 7).
2. Clonar e instalar dependências¶
git clone <url-do-repo>
cd slot2sync
npm install # dependências do frontend
sh scripts/install-hooks.sh # instala o hook que valida Conventional Commits
As dependências do Rust são baixadas automaticamente na primeira compilação
(tauri dev/build ou cargo).
O hook
commit-msg(versionado emscripts/git-hooks/) rejeita commits fora do padrãotipo(escopo): descrição. Como o diretório.git/não é versionado, a instalação precisa ser feita uma vez por clone.
3. Configurar as credenciais OAuth¶
Sem credenciais o app sobe normalmente, mas o botão de conectar ao Drive retorna um erro explicativo. Para habilitar o Drive:
- Crie um projeto no Google Cloud Console, ative a Google Drive API, configure a OAuth consent screen (tipo External, sua conta como test user) e crie uma credencial OAuth Client ID do tipo Desktop app.
- Copie
.env.example→.envna raiz e preencha:
SLOT2SYNC_GOOGLE_CLIENT_ID=seu-client-id
SLOT2SYNC_GOOGLE_CLIENT_SECRET=seu-secret # só no fluxo de dev local sem Worker
O src-tauri/build.rs injeta essas variáveis em build-time (variáveis do shell têm
precedência sobre o .env). O escopo OAuth é drive.file — o app só enxerga o que ele
mesmo cria.
Passo a passo completo do fluxo PKCE, armazenamento de tokens e o proxy Cloudflare Worker usado em produção: Autenticação.
4. Rodar em desenvolvimento¶
No PowerShell (Windows nativo):
npm run tauri dev # compila o Rust na 1ª vez e abre a janela "Slot2Sync"
A janela deve exibir o status do backend pronto — confirma a boundary invoke → Rust
funcionando de ponta a ponta.
5. Build de produção¶
npm run tauri build # gera o instalador/binário de produção
Logs de operação ficam no diretório de logs do app
(%LOCALAPPDATA%\com.slot2sync.app\logs no Windows), com rotação diária.
6. Qualidade de código¶
Rode antes de abrir um PR — é o que a CI valida:
# Frontend
npm run lint # ESLint (inclui i18next/no-literal-string p/ strings hardcoded)
npm run format:check # Prettier (--check); `npm run format` aplica
npm run build # tsc + vite build (o que a CI roda em PR)
npm run i18n:check # paridade de chaves en ⇄ pt (via tsc)
npm run i18n:extract # auditoria: chaves usadas × definidas (órfãs/faltando)
# Backend Rust
cargo fmt --manifest-path src-tauri/Cargo.toml # rustfmt
cargo clippy --manifest-path src-tauri/Cargo.toml # lints
cargo test --manifest-path src-tauri/Cargo.toml # testes unitários
cargo test --manifest-path src-tauri/Cargo.toml <nome_do_teste> # um único teste
sh scripts/check-licenses.sh # licenças das deps (cargo-deny)
- CI (
.github/workflows/ci.yml): em cada PR roda, em jobs paralelos:lint/format:check/i18n:check/builddo frontend; testes Rust em Windows e Linux;clippy(warnings bloqueantes);cargo audit(RustSec); licenças (cargo-deny); cobertura (cargo-tarpaulin→ Codecov). O jobci-passedagrega tudo — é o único required check da proteção de branch. O check Android (cargo checkdo target mobile) está temporariamente desativado — veja Setup de tooling pendente. - Release (
.github/workflows/release.yml): push namaincalcula a versão pelos Conventional Commits, cria a tagapp-v*, monta as release notes (relnotes/vX.Y.md+ API do GitHub) e builda/publica para macOS/Linux/Windows, validando antes os secrets de credenciais.
7. Ambiente WSL (fixes recorrentes)¶
Se você desenvolve a partir do WSL2 (com o repo em /mnt/c):
- Rust não está instalado no WSL: o
wingetinstala apenas no Windows. Para usarcargo check/clippy/testno WSL, instale o Rust separadamente:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# responda "1" (default); depois recarregue:
source ~/.cargo/env
- Cargo lento / poluindo o
/mnt/c: exporte um target dir fora do 9p antes dos comandos cargo:
export CARGO_TARGET_DIR=$HOME/.cache/slot2sync-target
Coloque esse export no seu ~/.bashrc ou ~/.zshrc para não precisar repetir.
Cannot find module @rollup/rollup-linux-x64-gnuao rodarnpm run build: onode_modulesem/mnt/cé compartilhado entre Windows e WSL, e cadanpm installde um lado remove o binário nativo do outro. Correção (aplicar direto, acontece quase toda sessão):
npm install --no-save @rollup/rollup-linux-x64-gnu
8. Por onde começar no código¶
src-tauri/src/ # Backend Rust — TODA a lógica de negócio
├── lib.rs # run(): setup comum + delega para platform/desktop ou platform/mobile
├── commands.rs # Boundary #[tauri::command] — toda ela vive aqui
├── state.rs # AppState (auth, db, engine, last_sync)
├── constants.rs # Pastas do Drive, chaves keyring, triggers (sem magic strings)
├── secrets.rs # Trait SecretStore: KeyringStore (desktop) / SqliteSecretStore (mobile)
├── platform/ # Código exclusivo por plataforma (tray, watcher, autostart vs. init mobile)
├── auth/ # OAuth2 + PKCE, refresh automático de token
├── drive/ # Cliente Google Drive API (reqwest + retry/backoff)
├── emulator/ # Perfis declarativos (profiles.toml) + detecção
├── storage/ # SQLite: manifest, fila offline, emuladores, settings, conflicts
├── sync/ # SyncEngine (diff, conflitos, upload/download) sobre a trait LocalStorage
└── watcher/ # Monitor de processos e de filesystem → gatilhos de sync
src/ # Frontend React — UI "burra": só invoke/emit
├── components/ # Telas e modais
├── hooks/ # Auth, descoberta, sync, conflitos, settings
├── lib/ipc.ts # Único lugar que chama invoke()
└── types/ipc.ts # Espelho TS das structs Rust + nomes de eventos
worker/ # Cloudflare Worker — proxy do token endpoint OAuth
Separação desktop / mobile: código exclusivo do desktop é guardado com
#[cfg(desktop)]e vive emplatform/desktop.rs(bandeja, watcher, autostart) ou em blocos#[cfg(desktop)]emcommands.rs. OSyncEnginee todo o core de sync são agnósticos de plataforma — operam sobre a traitLocalStorage, não sobrestd::fsdiretamente. Detalhes práticos em Como adicionar código por plataforma.
Leituras recomendadas, nesta ordem:
- Arquitetura — o mapa geral, fluxo de dados e gatilhos de sync.
- Referência da boundary IPC — catálogo de comandos, eventos e tipos.
- O documento de
explicacao/oureferencia/da área que você vai mexer — veja o índice.
Atenção à boundary tripla: toda struct/enum que cruza Rust↔TS aparece em três lugares — a struct Rust (
#[serde(rename_all = "camelCase")]), a interface emsrc/types/ipc.tse o wrapper emsrc/lib/ipc.ts. Ao mexer em uma, atualize as três. Detalhes no Referência IPC.
9. Fluxo de contribuição¶
Processo de PR, convenção de commits, credenciais de desenvolvimento e o que evitar num PR
estão em
CONTRIBUTING.md, no
repositório de código — leia antes de abrir um Pull Request.
- Documentação: mudança relevante ou decisão técnica nova? Atualize a página correspondente aqui em Para desenvolvedores ou Referência técnica, e registre a decisão em decisoes/decisoes-tecnicas.md.
- Antes do PR: rode os checks da seção 6 — lint, format e build precisam passar na CI.