The reconcile choreography (ensureRepo -> merge-check -> ensureBranch ->
checkout('docmost') -> pull -> push) was hand-rolled in the app orchestrator's
driveCycle, duplicating an order the vendored engine owns and could drift from on
upgrade — the failure mode is data clobber. Lift it into @docmost/git-sync as a
single entry point, `runCycle(deps)`. The orchestrator now calls runCycle and
keeps only the lock (its caller) and the gitmost-specific delete-cap POLICY,
injected as the `resolveApplyClient` hook (the engine does the dry-run, hands the
hook the planned delete count — Infinity if planning failed — and uses whatever
client it returns for the apply). driveCycle drops from ~150 lines to ~30.
Tests:
- engine test/cycle.test.ts: composition (merge-in-progress short-circuit;
ensureRepo->ensureBranch->checkout staging order before the pull; the cap hook
is consulted with the planned count; no dry-run when no hook).
- engine test/cycle-roundtrip.test.ts: runCycle against a REAL VaultGit in a temp
repo with a faked Docmost client — a git-originated CREATE flows pull->push and
the assigned pageId is written back; an unresolved merge short-circuits before
any client call.
- orchestrator spec rewired to mock runCycle and assert the wiring + the
resolveApplyClient cap policy (the engine-internal cycle-order/merge tests moved
to the engine).
Validated end to end on a live stand (real Postgres/Redis + server): a git clone
-> edit -> push over the /git remote round-trips the change into the Docmost page
through the refactored cycle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
122 lines
3.0 KiB
TypeScript
122 lines
3.0 KiB
TypeScript
/**
|
|
* Public surface of `@docmost/git-sync`.
|
|
*
|
|
* Phase A vendors only the PURE converter + pure engine modules
|
|
* from docmost-sync. Server integration (GitmostDataSource, orchestrator,
|
|
* VaultGit, pull/push) is added in later steps.
|
|
*/
|
|
|
|
// Pure converter (markdown <-> ProseMirror, file envelope, canonicalization).
|
|
export {
|
|
serializeDocmostMarkdown,
|
|
serializeDocmostMarkdownBody,
|
|
parseDocmostMarkdown,
|
|
convertProseMirrorToMarkdown,
|
|
markdownToProseMirror,
|
|
canonicalizeContent,
|
|
docsCanonicallyEqual,
|
|
} from "./lib/index";
|
|
export type { DocmostMdMeta } from "./lib/index";
|
|
|
|
// Pure engine (no IO): reconcile planner, vault layout, sanitize, stabilize,
|
|
// loop-guard body hash.
|
|
export {
|
|
planReconciliation,
|
|
decideAbsenceDeletions,
|
|
MASS_DELETE_MIN_EXISTING,
|
|
MASS_DELETE_FRACTION,
|
|
} from "./engine/reconcile";
|
|
export type {
|
|
LiveEntry,
|
|
ExistingEntry,
|
|
WriteEntry,
|
|
MovedEntry,
|
|
ReconciliationPlan,
|
|
DeletionDecision,
|
|
} from "./engine/reconcile";
|
|
|
|
export { buildVaultLayout } from "./engine/layout";
|
|
export type { PageNode, VaultEntry } from "./engine/layout";
|
|
|
|
export { sanitizeTitle, disambiguate } from "./engine/sanitize";
|
|
|
|
export { stabilizePageFile } from "./engine/stabilize";
|
|
export type { PageMeta } from "./engine/stabilize";
|
|
|
|
export { bodyHash } from "./engine/loop-guard";
|
|
|
|
// IO engine: the client seam, the VaultGit git wrapper, the
|
|
// pull (Docmost->FS) + push (FS->Docmost) planners/appliers, and the (pure)
|
|
// settings parser. The engine consumes the native `GitSyncClient` seam (server
|
|
// implements it) — the upstream REST `DocmostClient` is NOT vendored.
|
|
export type { GitSyncClient, GitSyncPageNodeLite } from "./engine/client.types";
|
|
|
|
export {
|
|
VaultGit,
|
|
vaultGitEnv,
|
|
buildCommitMessage,
|
|
BOT_AUTHOR_NAME,
|
|
BOT_AUTHOR_EMAIL,
|
|
DEFAULT_BRANCH,
|
|
} from "./engine/git";
|
|
export type { DiffEntry, MergeResult, CommitOptions } from "./engine/git";
|
|
|
|
export {
|
|
readExisting,
|
|
computePullActions,
|
|
applyPullActions,
|
|
} from "./engine/pull";
|
|
export type {
|
|
ReadExistingDeps,
|
|
PullActionsInput,
|
|
PullActions,
|
|
ApplyPullActionsDeps,
|
|
ApplyResult,
|
|
} from "./engine/pull";
|
|
|
|
export {
|
|
classifyRenameMoves,
|
|
computePushActions,
|
|
applyPushActions,
|
|
runPush,
|
|
parentFolderFile,
|
|
parseArgs,
|
|
LAST_PUSHED_REF,
|
|
DOCMOST_BRANCH,
|
|
LOCAL_AUTHOR_NAME,
|
|
LOCAL_AUTHOR_EMAIL,
|
|
LOCAL_SOURCE_TRAILER,
|
|
} from "./engine/push";
|
|
export type {
|
|
CreateAction,
|
|
UpdateAction,
|
|
DeleteAction,
|
|
RenameMoveAction,
|
|
RenameMoveActionClassified,
|
|
ClassifyRenameMovesDeps,
|
|
PushActions,
|
|
PushActionsInput,
|
|
MetaSide,
|
|
ApplyPushDeps,
|
|
WrittenBackPage,
|
|
PushedPageRecord,
|
|
PushFailure,
|
|
PushNoop,
|
|
ApplyPushResult,
|
|
PushDeps,
|
|
PushRunResult,
|
|
PushParsedArgs,
|
|
} from "./engine/push";
|
|
|
|
export { parseSettings, envSchema } from "./engine/settings";
|
|
export type { Settings } from "./engine/settings";
|
|
|
|
export { loadSettingsOrExit } from "./engine/config-errors";
|
|
|
|
export { runCycle } from "./engine/cycle";
|
|
export type {
|
|
RunCycleDeps,
|
|
RunCycleResult,
|
|
CycleFs,
|
|
} from "./engine/cycle";
|