alinea
Version:
Headless git-based CMS
226 lines (224 loc) • 6.1 kB
JavaScript
import "../../chunks/chunk-NZLE2WMY.js";
// src/core/db/Operation.ts
import { HttpError } from "../HttpError.js";
import { createId } from "../Id.js";
import { isImage } from "../media/IsImage.js";
import { Schema } from "../Schema.js";
import { Type } from "../Type.js";
import { createFileHash } from "../util/ContentHash.js";
import { workspaceMediaDir } from "../util/EntryFilenames.js";
import { basename, extname, join, normalize } from "../util/Paths.js";
import { slugify } from "../util/Slugs.js";
import { Workspace } from "../Workspace.js";
var Operation = class {
constructor(task) {
this.task = task;
}
};
function typeName(config, type) {
const typeNames = Schema.typeNames(config.schema);
const typeName2 = typeNames.get(type);
if (!typeName2)
throw new Error(`Type "${Type.label(type)}" not found in Schema`);
return typeName2;
}
var CreateOp = class extends Operation {
id;
constructor(op) {
super(async (db) => {
const { config } = db;
return [
{
op: "create",
id: this.id,
locale: op.locale ?? null,
parentId: op.parentId ?? null,
type: typeName(config, op.type),
data: op.set ?? {},
insertOrder: op.insertOrder,
status: op.status,
overwrite: op.overwrite,
root: op.root,
workspace: op.workspace
}
];
});
this.id = op.id ?? createId();
}
};
var DeleteOp = class extends Operation {
constructor(entryIds) {
super(() => {
return entryIds.map((id) => {
return {
op: "remove",
id
};
});
});
this.entryIds = entryIds;
}
};
var DiscardOp = class extends Operation {
constructor(query) {
super(() => {
return [
{
op: "remove",
...query
}
];
});
}
};
var UpdateOperation = class extends Operation {
constructor(query) {
super(() => {
const { status = "published", locale = null, id, set } = query;
return [
{
op: "update",
id,
locale,
status,
set
}
];
});
}
};
var MoveOperation = class extends Operation {
constructor(query) {
super(() => {
return [{ op: "move", ...query, after: query.after ?? null }];
});
}
};
var PublishOperation = class extends Operation {
constructor(query) {
super(() => {
return [{ op: "publish", ...query, locale: query.locale ?? null }];
});
}
};
var UnpublishOperation = class extends Operation {
constructor(query) {
super(() => {
return [{ op: "unpublish", ...query, locale: query.locale ?? null }];
});
}
};
var ArchiveOperation = class extends Operation {
constructor(query) {
super(() => {
return [{ op: "archive", ...query, locale: query.locale ?? null }];
});
}
};
var UploadOperation = class extends Operation {
id;
constructor(query) {
super(async (db) => {
const entryId = this.id;
const { file, createPreview } = query;
const { workspace: _workspace, root: _root, parentId: _parentId } = query;
const fileName = Array.isArray(file) ? file[0] : file.name;
const body = Array.isArray(file) ? file[1] : await file.arrayBuffer();
const contentType = file instanceof Blob ? file.type : "application/octet-stream";
const workspace = _workspace ?? Object.keys(db.config.workspaces)[0];
const root = _root ?? Workspace.defaultMediaRoot(db.config.workspaces[workspace]);
const extension = extname(fileName);
const path = slugify(basename(fileName, extension));
const directory = workspaceMediaDir(db.config, workspace);
const uploadLocation = join(directory, path + extension);
const info = await db.prepareUpload(uploadLocation);
const previewData = isImage(fileName) ? await createPreview?.(file instanceof Blob ? file : new Blob([body])) : void 0;
await fetch(info.url, {
method: info.method ?? "POST",
headers: { "Content-Type": contentType },
body
}).then((result) => {
if (!result.ok)
throw new HttpError(
result.status,
"Could not reach server for upload"
);
});
const title = basename(fileName, extension);
const hash = await createFileHash(new Uint8Array(body));
const { mediaDir } = Workspace.data(db.config.workspaces[workspace]);
const prefix = mediaDir && normalize(mediaDir);
const fileLocation = prefix && info.location.startsWith(prefix) ? info.location.slice(prefix.length) : info.location;
const uploadFile = {
op: "uploadFile",
url: info.previewUrl,
location: join(prefix, fileLocation)
};
const createEntry = {
op: "create",
id: entryId,
locale: null,
parentId: _parentId ?? null,
type: "MediaFile",
root,
workspace,
data: {
title,
location: fileLocation,
previewUrl: info.previewUrl,
extension,
size: body.byteLength,
hash,
...previewData
},
overwrite: query.replaceId !== void 0
};
return [uploadFile, createEntry];
});
this.id = query.replaceId ?? createId();
}
};
function update(query) {
return new UpdateOperation(query);
}
function create(query) {
return new CreateOp(query);
}
function remove(...entryIds) {
return new DeleteOp(entryIds);
}
function discard(query) {
return new DiscardOp(query);
}
function upload(query) {
return new UploadOperation(query);
}
function move(query) {
return new MoveOperation(query);
}
function publish(query) {
return new PublishOperation(query);
}
function archive(query) {
return new ArchiveOperation(query);
}
export {
ArchiveOperation,
CreateOp,
DeleteOp,
DiscardOp,
MoveOperation,
Operation,
PublishOperation,
UnpublishOperation,
UpdateOperation,
UploadOperation,
archive,
create,
discard,
move,
publish,
remove,
update,
upload
};