Address a code review of the git-hardening changes. - single runRaw primitive: every git invocation funnels through it; run() is a thin throw+trim wrapper; the two direct execFileAsync bypasses (commitRaw, assertGitAvailable) removed; one unified error format - `-c core.quotepath=false` is now the argv baseline for ALL commands (was only listTrackedFiles) — removes the latent quoting asymmetry on ls-files -u / diff --name-only; persisted LOCAL config (autocrlf/safecrlf/gpgsign/ attributesFile) kept as-is in ensureRepo - preserve spawn-error message (ENOENT): use `||` not `??` (promisified execFile sets stderr to "" on spawn failure) - contextual error when pinning vault git config; module/vaultGitEnv docs corrected - README: require a system git binary on PATH for local runs - tests: --no-verify honored (failing pre-commit hook), vaultGitEnv pins, core.attributesFile=/dev/null neutralization (593 green)
96 lines
4.1 KiB
Markdown
96 lines
4.1 KiB
Markdown
# docmost-sync
|
|
|
|
Bidirectional sync between Docmost articles and a local Markdown git vault — the
|
|
git repository is the state store. For the full design and the phased
|
|
implementation plan, see [`SPEC.md`](./SPEC.md) (the authoritative spec).
|
|
|
|
> **Status: Increment 1 — monorepo scaffold + read-only `pull` + Phase-0
|
|
> round-trip harness.** Continuous two-way sync is not implemented yet; see the
|
|
> phased plan in `SPEC.md`.
|
|
|
|
It reuses the sibling project **docmost-mcp** as a library: the `DocmostClient`
|
|
REST client and the lossless ProseMirror ↔ Markdown converter are extracted into
|
|
this monorepo (so changes can be backported file-by-file).
|
|
|
|
## Layout
|
|
|
|
This is an npm-workspaces monorepo:
|
|
|
|
- **`packages/docmost-client`** (`docmost-client`) — the Docmost REST client and
|
|
its `lib/` (converter, markdown-document, collaboration, …). Its source layout
|
|
mirrors `docmost-mcp/src/` 1:1 so diffs can be backported by copying files.
|
|
Sync-specific REST methods are added under clearly marked `docmost-sync
|
|
additions` banners.
|
|
- **the repo ROOT** — the sync engine app (`src/`, `test/`, `build/`, `data/`).
|
|
It depends on `docmost-client` and holds the config (`src/settings.ts`),
|
|
filename sanitization (`src/sanitize.ts`), the Phase-0 round-trip idempotency
|
|
harness (`src/roundtrip.ts`), and the read-only `pull` (`src/pull.ts`).
|
|
|
|
## Install & build
|
|
|
|
Requires Node >= 20. For local (non-Docker) runs a system `git` binary must
|
|
also be on `PATH` — the vault state store shells out to it for every operation
|
|
(the daemon fails fast at startup if `git` is missing).
|
|
|
|
```sh
|
|
npm install # links the workspace packages
|
|
npm run build # builds docmost-client, then compiles the app into build/
|
|
```
|
|
|
|
`docmost-client` must build before the app (the app consumes its built output);
|
|
the root `build` script builds the lib first, then runs `tsc`.
|
|
|
|
## Configuration
|
|
|
|
Copy [`.env.example`](./.env.example) to `.env` and fill in real values. The
|
|
config is read through [`src/settings.ts`](./src/settings.ts).
|
|
|
|
| Variable | Required | Meaning |
|
|
| ------------------- | :------: | -------------------------------------------------------- |
|
|
| `DOCMOST_API_URL` | yes | Base URL of our Docmost instance. |
|
|
| `DOCMOST_EMAIL` | yes | Docmost service-user login email. |
|
|
| `DOCMOST_PASSWORD` | yes | Docmost service-user login password. |
|
|
| `DOCMOST_SPACE_ID` | yes | Which Docmost space to mirror. |
|
|
| `VAULT_PATH` | no | Local vault directory (default `data/vault`). |
|
|
| `GIT_REMOTE` | no | Optional git remote the vault pushes to. |
|
|
| `POLL_INTERVAL_MS` | no | Poll interval in ms (default `15000`). |
|
|
| `DEBOUNCE_MS` | no | Debounce window in ms (default `2000`). |
|
|
| `LOG_LEVEL` | no | `debug` \| `info` \| `warn` \| `error` (default `info`). |
|
|
|
|
**Real secrets go in `.env`, which is git-ignored — never commit them.** The
|
|
git remote grants access to the whole vault, so protect it no less than Docmost
|
|
itself (SPEC §12).
|
|
|
|
## Running
|
|
|
|
### Round-trip idempotency harness (Phase 0, SPEC §11)
|
|
|
|
Verifies that `export → import → export` is byte-stable. Runs offline against a
|
|
fixture (the default for CI) — **no Docmost credentials needed**:
|
|
|
|
```sh
|
|
npm run build
|
|
node build/roundtrip.js --fixture test/fixtures/sample-doc.json
|
|
```
|
|
|
|
Or against a live page (needs `.env`):
|
|
|
|
```sh
|
|
node build/roundtrip.js --page <pageId>
|
|
```
|
|
|
|
Exit code is 0 when the markdown is byte-stable, 1 on a markdown divergence
|
|
(CI-able). A document-level divergence after stripping block ids is a known
|
|
SPEC §11 finding and does not fail the run.
|
|
|
|
### Pull (Docmost → filesystem mirror, SPEC §6)
|
|
|
|
Read-only mirror: walks the configured space's page tree and writes one `.md`
|
|
per page under `<VAULT_PATH>/<…ancestors>/<Title>.md`. **Requires a `.env` with
|
|
real Docmost credentials** — it makes live REST calls and does not touch Docmost
|
|
state (read-only this increment):
|
|
|
|
```sh
|
|
npm run pull
|
|
```
|