alinea
Version:
Headless git-based CMS
111 lines (109 loc) • 2.9 kB
JavaScript
import "../../chunks/chunk-NZLE2WMY.js";
// src/core/source/Source.ts
import { accumulate } from "../util/Async.js";
import { hashBlob } from "./GitUtils.js";
async function bundleContents(source, batch) {
const { changes } = batch;
const shas = Array.from(
new Set(
changes.filter((change) => change.op !== "delete").map((change) => change.sha)
)
);
if (shas.length === 0) return batch;
const blobs = new Map(await accumulate(source.getBlobs(shas)));
return {
...batch,
changes: changes.map((change) => {
if (change.op === "delete") return change;
return {
...change,
contents: blobs.get(change.sha)
};
})
};
}
async function diff(source, remote) {
const localTree = await source.getTree();
const remoteTree = await remote.getTreeIfDifferent(localTree.sha);
if (!remoteTree)
return {
fromSha: localTree.sha,
changes: []
};
const batch = localTree.diff(remoteTree);
return bundleContents(remote, batch);
}
async function syncWith(source, remote) {
const batch = await diff(source, remote);
await source.applyChanges(batch);
return batch;
}
async function transaction(source) {
const from = await source.getTree();
return new SourceTransaction(source, from);
}
var SourceTransaction = class {
#source;
#from;
#into;
#blobs = /* @__PURE__ */ new Map();
#tasks = Array();
constructor(source, from) {
this.#source = source;
this.#from = from;
this.#into = from.clone();
}
add(path, contents) {
this.#tasks.push(async () => {
const sha = await hashBlob(contents);
this.#blobs.set(sha, contents);
this.#into.add(path, sha);
});
return this;
}
remove(path) {
this.#tasks.push(() => {
this.#into.remove(path);
});
return this;
}
rename(from, to) {
if (from !== to)
this.#tasks.push(() => {
this.#into.rename(from, to);
});
return this;
}
async compile() {
const todo = this.#tasks.splice(0);
for (const task of todo) await task();
const from = this.#from;
const into = await this.#into.compile();
const forwards = from.diff(into);
const fromSource = Array.from(
new Set(
forwards.changes.filter((change) => change.op === "add").map((change) => change.sha).filter((sha) => !this.#blobs.has(sha))
)
);
const blobs = new Map(
fromSource.length === 0 ? [] : await accumulate(this.#source.getBlobs(fromSource))
);
const bundleContents2 = (change) => {
if (change.op === "delete") return change;
const contents = this.#blobs.get(change.sha) ?? blobs.get(change.sha);
return { ...change, contents };
};
return {
from,
into,
changes: forwards.changes.map(bundleContents2)
};
}
};
export {
SourceTransaction,
bundleContents,
diff,
syncWith,
transaction
};