refactor(git-sync): internalize the engine — first-class ESM, no vendoring bridge (#119 review)
Closes the architecture item from the #119 review: drop the "vendored from docmost-sync" framing and the CJS↔ESM `Function('import()')` bridge so the engine is a normal first-class gitmost package. Part 1 — vendoring markers removed (prose only, zero behavior change): reworded "VENDORED into gitmost" / "vendored from docmost-sync" / "Engine LOGIC is byte-identical" / "it's a port" comments across the engine. Behavior-bearing strings are untouched: BOT_AUTHOR_NAME/EMAIL and the `Docmost-Sync-Source:` provenance trailers (changing them would break git authorship + the loop-guard). Part 2 — the package is now ESM (matching the sibling @docmost/mcp): `type: module`, tsconfig Node16, `.js` extensions on relative imports, and a static `import { marked }` replacing the `new Function('return import(...)')` / `loadMarked` hack — the bridge is GONE from the package. The CommonJS NestJS server loads the now-ESM engine via a new `git-sync.loader.ts` that mirrors the existing `docmost-client.loader.ts` mcp loader exactly (Function-indirected dynamic import + cached promise + retry-on-reject). The 4 server consumers (orchestrator/datasource/vault-registry/git-http-backend) call `await loadGitSync()` for value exports; types stay `import type` (erased). The converter-gate spec — which needs the real converter — loads the package's TS source via a jest moduleNameMapper + isolatedModules (documented in that spec); the other git-sync specs mock the loader. Verified: engine builds pure ESM (no Function/require leftover), vitest 614, editor-ext build, server + client tsc, full server jest 1397/0. Live stand smoke-test: server starts clean on the ESM engine (no ERR_REQUIRE_ESM), a real sync cycle runs through the loader, and the basic e2e suite is 12/12 (clone via git-http-backend, push, pull, delete, 3-way merge — all through the new loader). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
/**
|
||||
* 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.
|
||||
* Exposes the pure converter (markdown <-> ProseMirror, file envelope,
|
||||
* canonicalization) and the sync engine (reconcile planner, vault layout,
|
||||
* pull/push, the git wrapper, and the settings parser) that the gitmost server
|
||||
* drives in-process.
|
||||
*/
|
||||
|
||||
// Pure converter (markdown <-> ProseMirror, file envelope, canonicalization).
|
||||
@@ -15,8 +16,8 @@ export {
|
||||
markdownToProseMirror,
|
||||
canonicalizeContent,
|
||||
docsCanonicallyEqual,
|
||||
} from "./lib/index";
|
||||
export type { DocmostMdMeta } from "./lib/index";
|
||||
} from "./lib/index.js";
|
||||
export type { DocmostMdMeta } from "./lib/index.js";
|
||||
|
||||
// Pure engine (no IO): reconcile planner, vault layout, sanitize, stabilize,
|
||||
// loop-guard body hash.
|
||||
@@ -25,7 +26,7 @@ export {
|
||||
decideAbsenceDeletions,
|
||||
MASS_DELETE_MIN_EXISTING,
|
||||
MASS_DELETE_FRACTION,
|
||||
} from "./engine/reconcile";
|
||||
} from "./engine/reconcile.js";
|
||||
export type {
|
||||
LiveEntry,
|
||||
ExistingEntry,
|
||||
@@ -33,23 +34,23 @@ export type {
|
||||
MovedEntry,
|
||||
ReconciliationPlan,
|
||||
DeletionDecision,
|
||||
} from "./engine/reconcile";
|
||||
} from "./engine/reconcile.js";
|
||||
|
||||
export { buildVaultLayout } from "./engine/layout";
|
||||
export type { PageNode, VaultEntry } from "./engine/layout";
|
||||
export { buildVaultLayout } from "./engine/layout.js";
|
||||
export type { PageNode, VaultEntry } from "./engine/layout.js";
|
||||
|
||||
export { sanitizeTitle, disambiguate } from "./engine/sanitize";
|
||||
export { sanitizeTitle, disambiguate } from "./engine/sanitize.js";
|
||||
|
||||
export { stabilizePageFile } from "./engine/stabilize";
|
||||
export type { PageMeta } from "./engine/stabilize";
|
||||
export { stabilizePageFile } from "./engine/stabilize.js";
|
||||
export type { PageMeta } from "./engine/stabilize.js";
|
||||
|
||||
export { bodyHash } from "./engine/loop-guard";
|
||||
export { bodyHash } from "./engine/loop-guard.js";
|
||||
|
||||
// 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";
|
||||
// settings parser. The engine consumes the native `GitSyncClient` seam (the
|
||||
// server implements it) rather than any REST client.
|
||||
export type { GitSyncClient, GitSyncPageNodeLite } from "./engine/client.types.js";
|
||||
|
||||
export {
|
||||
VaultGit,
|
||||
@@ -58,21 +59,21 @@ export {
|
||||
BOT_AUTHOR_NAME,
|
||||
BOT_AUTHOR_EMAIL,
|
||||
DEFAULT_BRANCH,
|
||||
} from "./engine/git";
|
||||
export type { DiffEntry, MergeResult, CommitOptions } from "./engine/git";
|
||||
} from "./engine/git.js";
|
||||
export type { DiffEntry, MergeResult, CommitOptions } from "./engine/git.js";
|
||||
|
||||
export {
|
||||
readExisting,
|
||||
computePullActions,
|
||||
applyPullActions,
|
||||
} from "./engine/pull";
|
||||
} from "./engine/pull.js";
|
||||
export type {
|
||||
ReadExistingDeps,
|
||||
PullActionsInput,
|
||||
PullActions,
|
||||
ApplyPullActionsDeps,
|
||||
ApplyResult,
|
||||
} from "./engine/pull";
|
||||
} from "./engine/pull.js";
|
||||
|
||||
export {
|
||||
classifyRenameMoves,
|
||||
@@ -86,7 +87,7 @@ export {
|
||||
LOCAL_AUTHOR_NAME,
|
||||
LOCAL_AUTHOR_EMAIL,
|
||||
LOCAL_SOURCE_TRAILER,
|
||||
} from "./engine/push";
|
||||
} from "./engine/push.js";
|
||||
export type {
|
||||
CreateAction,
|
||||
UpdateAction,
|
||||
@@ -106,18 +107,18 @@ export type {
|
||||
PushDeps,
|
||||
PushRunResult,
|
||||
PushParsedArgs,
|
||||
} from "./engine/push";
|
||||
} from "./engine/push.js";
|
||||
|
||||
export { parseSettings, envSchema } from "./engine/settings";
|
||||
export type { Settings } from "./engine/settings";
|
||||
export { parseSettings, envSchema } from "./engine/settings.js";
|
||||
export type { Settings } from "./engine/settings.js";
|
||||
|
||||
export { loadSettingsOrExit } from "./engine/config-errors";
|
||||
export { loadSettingsOrExit } from "./engine/config-errors.js";
|
||||
|
||||
export { runCycle } from "./engine/cycle";
|
||||
export { runCycle } from "./engine/cycle.js";
|
||||
export type {
|
||||
RunCycleDeps,
|
||||
RunCycleResult,
|
||||
CycleFs,
|
||||
} from "./engine/cycle";
|
||||
} from "./engine/cycle.js";
|
||||
|
||||
export { parsePageFile, serializePageFile } from "./lib/page-file";
|
||||
export { parsePageFile, serializePageFile } from "./lib/page-file.js";
|
||||
|
||||
Reference in New Issue
Block a user