alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
251 lines (248 loc) • 7.86 kB
JavaScript
import {
useSetAtom
} from "../../chunks/chunk-WF77DMLN.js";
import {
atomFamily
} from "../../chunks/chunk-ZHH24SIG.js";
import {
atom
} from "../../chunks/chunk-OBOPLPUQ.js";
import {
pLimit
} from "../../chunks/chunk-QQTYTFWR.js";
import {
__commonJS,
__toESM
} from "../../chunks/chunk-U5RRZUYZ.js";
// node_modules/debounce-promise/dist/index.js
var require_dist = __commonJS({
"node_modules/debounce-promise/dist/index.js"(exports, module) {
"use strict";
module.exports = function debounce2(fn) {
var wait = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0;
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
var lastCallAt = void 0;
var deferred = void 0;
var timer = void 0;
var pendingArgs = [];
return function debounced() {
var currentWait = getWait(wait);
var currentTime = (/* @__PURE__ */ new Date()).getTime();
var isCold = !lastCallAt || currentTime - lastCallAt > currentWait;
lastCallAt = currentTime;
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (isCold && options.leading) {
return options.accumulate ? Promise.resolve(fn.call(this, [args])).then(function(result) {
return result[0];
}) : Promise.resolve(fn.call.apply(fn, [this].concat(args)));
}
if (deferred) {
clearTimeout(timer);
} else {
deferred = defer();
}
pendingArgs.push(args);
timer = setTimeout(flush.bind(this), currentWait);
if (options.accumulate) {
var argsIndex = pendingArgs.length - 1;
return deferred.promise.then(function(results) {
return results[argsIndex];
});
}
return deferred.promise;
};
function flush() {
var thisDeferred = deferred;
clearTimeout(timer);
Promise.resolve(options.accumulate ? fn.call(this, pendingArgs) : fn.apply(this, pendingArgs[pendingArgs.length - 1])).then(thisDeferred.resolve, thisDeferred.reject);
pendingArgs = [];
deferred = null;
}
};
function getWait(wait) {
return typeof wait === "function" ? wait() : wait;
}
function defer() {
var deferred = {};
deferred.promise = new Promise(function(resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
}
});
// src/dashboard/atoms/DbAtoms.ts
var import_debounce_promise = __toESM(require_dist(), 1);
import { Database } from "alinea/backend";
import { EntryResolver } from "alinea/backend/resolver/EntryResolver";
import { Entry } from "alinea/core";
import {
applySuffix,
entryFileName,
pathSuffix
} from "alinea/core/EntryFilenames";
import { Graph } from "alinea/core/Graph";
import { MutationType } from "alinea/core/Mutation";
import {
createEntryRow,
entryParentPaths,
publishEntryRow
} from "alinea/core/util/EntryRows";
import { useEffect } from "react";
import { createPersistentStore } from "../util/PersistentStore.js";
import { clientAtom, configAtom } from "./DashboardAtoms.js";
var persistentStoreAtom = atom(createPersistentStore);
var limit = pLimit(1);
var dbHashAtom = atom(async (get) => {
const db = await get(localDbAtom);
get(changedEntriesAtom);
const meta = await db.db.meta();
return meta.contentHash;
});
var localDbAtom = atom(async (get, set) => {
const config = get(configAtom);
const client = get(clientAtom);
const { store, clear, flush } = await get(persistentStoreAtom);
let db = new Database(config, store);
try {
await db.init();
} catch {
await clear();
db = new Database(config, store);
}
const resolver = new EntryResolver(db, config.schema);
const syncDb = async (force = false) => {
const changed = await db.syncWith(client, force);
if (changed.length > 0)
await flush();
return changed;
};
const debounceSync = (0, import_debounce_promise.default)(syncDb, 100);
const sync = (force) => limit(() => debounceSync(force).catch(() => []));
const applyMutations = async (mutations, commitHash) => {
return limit(async () => {
const update = await db.applyMutations(mutations, commitHash);
await flush();
return update;
});
};
await limit(syncDb);
return { db, applyMutations, resolve: resolver.resolve, sync };
});
async function suffixPaths(config, graph, mutations) {
const res = [];
for (const mutation of mutations) {
switch (mutation.type) {
case MutationType.Create: {
const { entry } = mutation;
const sameLocation = Entry.root.is(entry.root).and(
Entry.workspace.is(entry.workspace),
Entry.locale.is(entry.locale)
);
const sameParent = Entry.parent.is(entry.parent ?? null);
const isExact = Entry.path.is(entry.path);
const startsWith = Entry.path.like(entry.path + "-%");
const condition = sameLocation.and(sameParent, isExact.or(startsWith));
const conflictingPaths = await graph.preferPublished.find(
Entry().where(condition).select(Entry.path)
);
const suffix = pathSuffix(entry.path, conflictingPaths);
if (suffix) {
const updated = {
...entry,
data: { ...entry.data, path: applySuffix(entry.path, suffix) }
};
const suffixedEntry = await createEntryRow(
config,
publishEntryRow(config, updated)
);
const parentPaths = entryParentPaths(config, entry);
res.push({
...mutation,
file: entryFileName(
config,
publishEntryRow(config, updated),
parentPaths
),
entry: suffixedEntry
});
continue;
}
}
default:
res.push(mutation);
}
}
return res;
}
var mutateAtom = atom(
null,
async (get, set, ...mutations) => {
const client = get(clientAtom);
const config = get(configAtom);
const graph = await get(graphAtom);
const normalized = await limit(() => suffixPaths(config, graph, mutations));
const { commitHash } = await client.mutate(normalized);
const { applyMutations } = await get(localDbAtom);
if (normalized.length === 0)
return;
const changed = await applyMutations(normalized, commitHash);
set(changedEntriesAtom, changed);
}
);
var dbUpdateAtom = atom(
null,
async (get, set, force = false) => {
const { sync } = await get(localDbAtom);
const changed = await sync(force);
set(changedEntriesAtom, changed);
}
);
var graphAtom = atom(async (get) => {
const config = get(configAtom);
const { resolve } = await get(localDbAtom);
return new Graph(config, resolve);
});
var changedAtom = atom([]);
var changedEntriesAtom = atom(
(get) => get(changedAtom),
(get, set, i18nIds) => {
set(changedAtom, i18nIds);
for (const i18nId of i18nIds)
set(entryRevisionAtoms(i18nId));
}
);
var entryRevisionAtoms = atomFamily((i18nId) => {
const revision = atom(0);
return atom(
(get) => get(revision),
(get, set) => set(revision, (i) => i + 1)
);
});
function useMutate() {
return useSetAtom(mutateAtom);
}
function useDbUpdater(everySeconds = 30) {
const forceDbUpdate = useSetAtom(dbUpdateAtom);
useEffect(() => {
let interval = 0;
interval = setInterval(forceDbUpdate, everySeconds * 1e3);
return () => {
clearInterval(interval);
};
}, [everySeconds, forceDbUpdate]);
}
export {
changedEntriesAtom,
dbHashAtom,
dbUpdateAtom,
entryRevisionAtoms,
graphAtom,
mutateAtom,
persistentStoreAtom,
useDbUpdater,
useMutate
};