@oberoncms/core
Version:
OberonCMS is a cloud deployable CMS written in typescript based on the Puck visual editor
280 lines (279 loc) • 7.85 kB
JavaScript
import { unstable_cache, revalidateTag, revalidatePath } from "next/cache";
import { streamResponse } from "@tohuhono/utils";
import { version } from "../package.json.js";
import { AddPageSchema, INITIAL_DATA, DeletePageSchema, PublishPageSchema, AddImageSchema, AddUserSchema, DeleteUserSchema, ChangeRoleSchema, ResponseError } from "../lib/dtd.js";
import { getTransforms, getComponentTransformVersions, applyTransforms } from "./transforms.js";
import { exportTailwindClasses } from "./export-tailwind-clases.js";
function initAdapter({
config,
versions,
pluginAdapter: adapter
}) {
const can = async (action, permission = "read") => {
if (adapter.hasPermission({ action, permission })) {
return true;
}
const user = await adapter.getCurrentUser();
return adapter.hasPermission({ user, action, permission });
};
const will = async (action, permission) => {
if (await can(action, permission)) {
return;
}
throw new ResponseError("You do not have permission to perform this action");
};
const whoWill = async (action, permission) => {
const user = await adapter.getCurrentUser();
if (user && adapter.hasPermission({ user, action, permission })) {
return user;
}
throw new ResponseError("You do not have permission to perform this action");
};
const getAllPagesCached = unstable_cache(
async () => {
const sortPages = (a, b) => {
if (a.key < b.key) {
return -1;
}
if (a.key > b.key) {
return 1;
}
return 0;
};
const result = await adapter.getAllPages();
const data = result.sort(sortPages);
return data;
},
void 0,
{ tags: ["oberon-pages"] }
);
const getAllPathsCached = unstable_cache(
async () => {
const result = await adapter.getAllPages();
const data = result.map((row) => ({
path: row["key"].split("/").slice(1)
}));
return data;
},
void 0,
{ tags: ["oberon-pages"] }
);
const getPageDataCached = async (key) => {
const dataString = await adapter.getPageData(key);
return dataString;
};
const getAllUsersCached = unstable_cache(
async () => {
const allUsers = await adapter.getAllUsers();
return allUsers || [];
},
void 0,
{
tags: ["oberon-users"]
}
);
const getAllImagesCached = unstable_cache(
async () => {
const allImages = await adapter.getAllImages();
return allImages || [];
},
void 0,
{
tags: ["oberon-images"]
}
);
const updatePageData = async ({
key,
data,
updatedBy
}) => {
await adapter.updatePageData({
key,
data,
updatedAt: /* @__PURE__ */ new Date(),
updatedBy
});
revalidatePath(key);
revalidateTag("oberon-pages");
};
const getConfigCached = unstable_cache(
async () => {
const site = await adapter.getSite();
const { components, transforms } = getTransforms(site == null ? void 0 : site.components, config);
const siteConfig = {
version,
plugins: versions,
components,
pendingMigrations: transforms && Object.keys(transforms)
};
if (!site) {
await adapter.updateSite({
version: config.version,
components: getComponentTransformVersions(config),
updatedAt: /* @__PURE__ */ new Date(),
updatedBy: "system"
});
}
return siteConfig;
},
void 0,
{
tags: ["oberon-config"]
}
);
const migrate = streamResponse(async function* (user) {
const summary = {
type: "summary",
error: [],
success: [],
total: 0
};
const site = await adapter.getSite();
const { transforms } = getTransforms(site == null ? void 0 : site.components, config);
if (!transforms) {
return summary;
}
const pages = await getAllPagesCached();
const results = applyTransforms({
transforms,
pages,
getPageData: getPageDataCached,
updatePageData
});
for await (const result of results) {
summary[result.status].push(result.key);
yield result;
}
await adapter.updateSite({
version: config.version,
components: getComponentTransformVersions(config),
updatedAt: /* @__PURE__ */ new Date(),
updatedBy: user.email
});
revalidateTag("oberon-config");
yield { ...summary, total: pages.length };
});
return {
prebuild: async () => {
await adapter.prebuild();
await exportTailwindClasses(adapter);
},
/*
* Auth
*/
can,
signIn: adapter.signIn,
signOut: adapter.signOut,
/*
* Site actions
*/
getConfig: async () => {
await will("site", "read");
return await getConfigCached();
},
migrateData: async () => {
const user = await whoWill("site", "write");
return migrate(user);
},
/*
* Page actions
*/
getAllPaths: async function() {
await will("pages", "read");
return getAllPathsCached();
},
getAllPages: async function() {
await will("pages", "read");
return getAllPagesCached();
},
getPageData: async function(key) {
await will("pages", "read");
return getPageDataCached(key);
},
// TODO return value
addPage: async function(data) {
const user = await whoWill("pages", "write");
const { key } = AddPageSchema.parse(data);
await adapter.addPage({
key,
data: INITIAL_DATA,
updatedAt: /* @__PURE__ */ new Date(),
updatedBy: user.email
});
revalidatePath(key);
revalidateTag("oberon-pages");
},
// TODO return value
deletePage: async function(data) {
await will("pages", "write");
const { key } = DeletePageSchema.parse(data);
await adapter.deletePage(key);
revalidatePath(key);
revalidateTag("oberon-pages");
},
publishPageData: async function(data) {
const user = await whoWill("pages", "write");
const { key, data: pageData } = PublishPageSchema.parse(data);
await updatePageData({
key,
data: pageData,
updatedBy: user.email
});
return { message: `Successfully published ${key}` };
},
/*
* Image actions
*/
getAllImages: async function() {
await will("images", "read");
return getAllImagesCached();
},
addImage: async function(data) {
await will("images", "write");
const image = AddImageSchema.parse(data);
await adapter.addImage(image);
revalidateTag("oberon-images");
return adapter.getAllImages();
},
// TODO uploadthing
deleteImage: async function(data) {
await will("images", "write");
revalidateTag("oberon-images");
return adapter.deleteImage(data);
},
/*
* User actions
*/
getAllUsers: async function() {
await will("users", "read");
return getAllUsersCached();
},
addUser: async function(data) {
await will("users", "write");
const { email, role } = AddUserSchema.parse(data);
const { id } = await adapter.addUser({
email,
role
});
revalidateTag("oberon-users");
return { id, email, role };
},
deleteUser: async function(data) {
await will("users", "write");
const { id } = DeleteUserSchema.parse(data);
await adapter.deleteUser(id);
revalidateTag("oberon-users");
return { id };
},
changeRole: async function(data) {
await will("users", "write");
const { role, id } = ChangeRoleSchema.parse(data);
await adapter.changeRole({ role, id });
revalidateTag("oberon-users");
return { role, id };
}
};
}
export {
initAdapter
};