alinea
Version:
Headless git-based CMS
99 lines (97 loc) • 2.7 kB
JavaScript
import {
pLimit
} from "../../chunks/chunk-C53YJRET.js";
import "../../chunks/chunk-NZLE2WMY.js";
// src/dashboard/boot/DashboardWorker.ts
import { getScope } from "alinea/core/Scope";
import { trigger } from "alinea/core/Trigger";
import { IndexEvent } from "alinea/core/db/IndexEvent";
import { LocalDB } from "alinea/core/db/LocalDB";
var MutateEvent = class _MutateEvent extends Event {
constructor(id, status, error) {
super(_MutateEvent.type);
this.id = id;
this.status = status;
this.error = error;
}
static type = "mutate";
};
var remote = pLimit(1);
var DashboardWorker = class extends EventTarget {
#source;
#localDB;
#localClient;
#nextLoad = trigger();
#defer;
#currentRevision;
constructor(source) {
super();
this.#source = source;
}
get db() {
return this.#localDB ?? this.#nextLoad.then((res) => res.db);
}
get #client() {
return this.#localClient ?? this.#nextLoad.then((res) => res.client);
}
async sync() {
const db = await this.db;
const client = await this.#client;
if (remote.pendingCount > 0) return db.sha;
const sync = remote(() => db.syncWith(client));
if (db.index.tree.isEmpty) await sync;
return db.sha;
}
queue(id, mutations) {
return remote(async () => {
const db = await this.db;
await db.mutate(mutations);
const intoSha = db.sha;
const client = await this.#client;
try {
const { sha } = await client.mutate(mutations);
if (sha !== intoSha) return db.syncWith(client);
return intoSha;
} catch (error) {
await db.syncWith(client);
throw error;
}
});
}
async resolve(raw) {
const db = await this.db;
const scope = getScope(db.config);
const query = scope.parse(raw);
return db.resolve(query);
}
async load(revision, config, client) {
if (this.#currentRevision === revision) {
await this.sync();
return;
}
this.#currentRevision = revision;
const db = new LocalDB(config, this.#source);
try {
if (this.#defer) this.#defer();
this.#nextLoad.resolve({ db, client });
this.#localDB = db;
this.#localClient = client;
const listen = (event) => {
if (event instanceof IndexEvent)
this.dispatchEvent(new IndexEvent(event.data));
};
db.index.addEventListener(IndexEvent.type, listen);
this.#defer = () => {
db.index.removeEventListener(IndexEvent.type, listen);
};
} catch (error) {
this.#nextLoad.reject(new Error("Failed to load database"));
} finally {
this.#nextLoad = trigger();
}
}
};
export {
DashboardWorker,
MutateEvent
};