Add docs/ARCHITECTURE, CONTRIBUTING and DEVELOPMENT

- ARCHITECTURE.md: high-level view of FakeFs abstraction, sync flow, state
- DEVELOPMENT.md: mise setup + npm commands + local install
- CONTRIBUTING.md: workflow, English commit conventions, upstream PR cherry-pick
This commit is contained in:
Bruno Miiller 2026-05-19 22:10:31 -03:00
parent 9dde1bcdc8
commit 48b4f7e19c
3 changed files with 191 additions and 0 deletions

71
docs/ARCHITECTURE.md Normal file
View File

@ -0,0 +1,71 @@
# Arquitetura
Plugin Obsidian (TypeScript) que sincroniza vaults com serviços de armazenamento remoto (WebDAV, S3, Dropbox, OneDrive, etc).
## Estrutura
```
src/ código público (MIT)
├── main.ts entry point, estende Plugin do Obsidian (~2k linhas)
├── settings.ts UI de settings (~3k linhas)
├── fsAll.ts abstração FakeFs — interface comum dos backends
├── fsGetter.ts roteamento backend → instância (switch por tipo)
├── fs<Backend>.ts implementações: S3, WebDAV, Dropbox, OneDrive, Webdis, Local, Encrypt
├── localdb.ts IndexedDB via LocalForage — state local
├── configPersist.ts serialização da config no disco do plugin
├── i18n.ts Mustache + moment, idiomas em src/langs/
└── ...
pro/ código tier pago (PolyForm Strict License)
├── src/
│ ├── sync.ts motor de sincronização (~2k linhas, doActualSync + dispatchDecision)
│ ├── fs<Backend>.ts GoogleDrive, Box, pCloud, YandexDisk, Koofr, Azure, OnedriveFull
│ └── ...
└── tests/
tests/ testes Mocha (estrutura básica, sem cobertura do core)
docs/ documentação
.github/workflows/ CI
```
## Abstração FakeFs
Todo backend implementa a classe abstrata `FakeFs` (`src/fsAll.ts`):
```typescript
abstract class FakeFs {
walk() / walkPartial() / stat() / mkdir() / writeFile()
readFile() / rename() / rm()
checkConnect() / getUserDisplayName() / revokeAuth() / allowEmptyFile()
}
```
`fsGetter.ts` faz o roteamento via switch — ao adicionar backend novo, registrar nele.
## Fluxo de sincronização
1. `main.ts` dispara sync (manual, auto-sync, evento de save)
2. `pro/src/sync.ts:doActualSync()` carrega árvore local + remota
3. Diff 3-way usando snapshot anterior (`prevSyncRecordsTbl` em IndexedDB)
4. `dispatchDecision()` aplica decisão por entry (copy, merge, delete, skip)
5. Conflitos: 3-way merge via `node-diff3` (apenas Markdown < 1MB, tier pro)
6. Erros agregados em `AggregateError`; falha até 3x antes de abortar
## State
LocalForage (IndexedDB) com 8 tabelas em `src/localdb.ts`:
- `prevSyncRecordsTbl` — snapshot da última sync
- `fileContentHistoryTbl` — histórico de conteúdo (smart conflict)
- `syncPlansTbl` — log das operações planejadas
- `versionTbl`, `loggerOutputTbl`, `profilerResultsTbl` — metadados
Config persiste via API do Obsidian em `<vault>/.obsidian/plugins/remotely-save/data.json`,
com obfuscação base64 reverse (decorativa, não criptográfica).
## Pontos de atenção
- **mtime no WebDAV**: padrão WebDAV não define mtime — Nextcloud expõe via header custom (`OC-LastModified`). Inconsistência pode causar falsa detecção de modificação.
- **OAuth2 duplicado**: cada backend implementa fluxo próprio (~100-300 linhas duplicadas). Sem extração comum.
- **Sem retry HTTP**: 429/503 quebram sync. PR upstream #1034 propõe retry para WebDAV.
- **141 `: any` residuais**: concentrados em callbacks de error e payloads OAuth2.

56
docs/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,56 @@
# Contribuindo
## Workflow
1. Branch a partir de `master`: `git checkout -b <tipo>/<descrição>`
- `feat/` — feature nova
- `fix/` — bugfix
- `refactor/` — refactor sem mudança de comportamento
- `docs/` — só documentação
- `chore/` — config, build, CI
2. Commits pequenos, foco único
3. Antes de abrir PR: `npm run format && npm test && npm run build`
4. Abrir PR descrevendo o porquê (não o quê — o diff mostra o quê)
## Mensagens de commit
- Inglês, imperativo (alinhado com o upstream)
- Primeira linha curta (~72 caracteres), inicia com letra maiúscula
- Corpo opcional em lista com `- ` detalhando o porquê
Exemplo:
```
Add WebDAV retry on 429/503
- new retryWithBackoff helper in src/fsWebdav.ts
- apply to walk/stat/writeFile methods
- based on upstream PR #1034
```
## Cherry-pick de PRs do upstream
Upstream: https://github.com/remotely-save/remotely-save
```bash
git remote add upstream https://github.com/remotely-save/remotely-save.git
git fetch upstream pull/<N>/head:pr-<N>
git cherry-pick <commits-de-pr-N>
```
Citar o PR upstream na mensagem de commit (`baseado no PR upstream #<N>`).
## Estilo de código
- Biome formata e linta (`npm run format`)
- TypeScript strict — evitar `any`
- Funções idealmente 420 linhas; refatorar se passar
- Nomes específicos, não `data`/`handler`/`Manager`
- Sem comentários óbvios — explicar só o porquê quando não-trivial
- Early returns (no máximo 2 níveis de aninhamento)
## Testes
- Toda feature ou bugfix inclui teste
- Cobertura mínima do core: a definir (atualmente sem threshold)
- Localização: `tests/` para src/, `pro/tests/` para pro/

64
docs/DEVELOPMENT.md Normal file
View File

@ -0,0 +1,64 @@
# Desenvolvimento
## Setup
Pré-requisito: [mise](https://mise.jdx.dev/) instalado.
```bash
mise install # instala Node conforme mise.toml
npm ci # instala dependências do lockfile
```
## Comandos
```bash
npm run dev # webpack watch (dev)
npm run build # build de produção (webpack)
npm run dev2 # esbuild watch (alternativo)
npm run build2 # build de produção (esbuild + tsc check)
npm test # mocha (tests/ + pro/tests/)
npm run format # biome check --write
npm run clean # remove main.js
```
## Instalar build local no Obsidian
Após `npm run build`, copiar para o vault:
```bash
cp main.js manifest.json styles.css \
/path/to/vault/.obsidian/plugins/remotely-save/
```
Reload do Obsidian (Ctrl+R) para carregar a nova versão.
## Testes
Framework: Mocha + chai-as-promised + tsx (sem transpile separado).
Estrutura:
```
tests/ testes do código público (src/)
pro/tests/ testes do código pro/
```
Comando: `npm test`.
## Lint/format
Biome (`biome.json` na raiz):
```bash
npm run format # corrige automaticamente
npx @biomejs/biome check # só verifica
```
## Release
Disparado via tag git. Workflow `.github/workflows/release.yml` constrói e publica artefatos:
```bash
git tag x.y.z
git push origin x.y.z
```