alinea
Version:
Headless git-based CMS
107 lines (105 loc) • 3.5 kB
JavaScript
import "../../chunks/chunk-NZLE2WMY.js";
// src/cli/generate/DevDB.ts
import * as fsp from "node:fs/promises";
import { Config } from "alinea/core/Config";
import { checkCommit } from "alinea/core/db/CommitRequest";
import { LocalDB } from "alinea/core/db/LocalDB";
import { createId } from "alinea/core/Id";
import { getWorkspace } from "alinea/core/Internal";
import { CachedFSSource } from "alinea/core/source/FSSource";
import { assert } from "alinea/core/util/Assert";
import { keys, values } from "alinea/core/util/Objects";
import {
basename,
contains,
dirname,
extname,
join
} from "alinea/core/util/Paths";
import { slugify } from "alinea/core/util/Slugs";
var DevDB = class extends LocalDB {
source;
#options;
constructor(options) {
const source = new CachedFSSource(
join(options.rootDir, Config.contentDir(options.config))
);
super(options.config, source);
this.#options = options;
this.source = source;
}
async sync() {
await this.source.refresh();
return super.sync();
}
async fix() {
await this.index.fix(this.source);
}
async watchFiles() {
const { rootDir, config } = this.#options;
const singleWorkspace = Config.multipleWorkspaces(config) ? void 0 : keys(config.workspaces)[0];
const tree = await this.source.getTree();
const res = { files: [], dirs: [] };
for (const [path, node] of tree) {
const segments = path.split("/");
const workspace = singleWorkspace ?? segments.shift();
const hasWorkspace = config.workspaces[workspace];
if (!hasWorkspace) continue;
const contentDir = getWorkspace(hasWorkspace).source;
const fullPath = join(rootDir, contentDir, segments.join("/"));
if (node.type === "tree") res.dirs.push(fullPath);
else res.files.push(fullPath);
}
return res;
}
isInMediaLocation(file) {
const { config, rootDir } = this.#options;
const mediaDirs = values(config.workspaces).map((workspace) => getWorkspace(workspace).mediaDir).filter(Boolean);
return mediaDirs.some((dir) => contains(join(rootDir, dir), file));
}
async write(request) {
if (this.sha === request.intoSha) return { sha: this.sha };
if (this.sha !== request.fromSha) {
const tree = await this.source.getTree();
checkCommit(tree, request);
}
const { rootDir } = this.#options;
for (const change of request.changes) {
switch (change.op) {
// Uploaded files will be put in the right folder by the server
// during upload
case "removeFile": {
const location = join(rootDir, change.location);
assert(
this.isInMediaLocation(location),
`Invalid media location: ${location}`
);
await fsp.rm(location, { force: true });
}
}
}
return super.write(request);
}
async prepareUpload(file) {
const { dashboardUrl } = this.#options;
assert(dashboardUrl, "Dashboard URL is required for upload");
const entryId = createId();
const dir = dirname(file);
const extension = extname(file).toLowerCase();
const name = basename(file, extension);
const fileName = `${slugify(name)}.${entryId}${extension}`;
const fileLocation = join(dir, fileName);
return {
entryId,
location: fileLocation,
previewUrl: "",
url: new URL(
`?/upload&file=${encodeURIComponent(fileLocation)}`,
dashboardUrl
).href
};
}
};
export {
DevDB
};