From 48b4f7e19c6dde0eedf740dcb6fa507269f96a57 Mon Sep 17 00:00:00 2001 From: Bruno Miiller Date: Tue, 19 May 2026 22:10:31 -0300 Subject: [PATCH] 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 --- docs/ARCHITECTURE.md | 71 ++++++++++++++++++++++++++++++++++++++++++++ docs/CONTRIBUTING.md | 56 ++++++++++++++++++++++++++++++++++ docs/DEVELOPMENT.md | 64 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/DEVELOPMENT.md diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..774cb55 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -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.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.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 `/.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. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..e36d9ea --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# Contribuindo + +## Workflow + +1. Branch a partir de `master`: `git checkout -b /` + - `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//head:pr- +git cherry-pick +``` + +Citar o PR upstream na mensagem de commit (`baseado no PR upstream #`). + +## Estilo de código + +- Biome formata e linta (`npm run format`) +- TypeScript strict — evitar `any` +- Funções idealmente 4–20 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/ diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..1a1b3ca --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -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 +```