@npio/internals
Version:
A free visual website editor, powered with your own SolidJS components.
169 lines (148 loc) • 4.43 kB
text/typescript
import { NitroProject } from "@prisma/client";
import { redirect } from "@solidjs/router";
import { useContext } from "solid-js";
import { getRequestEvent } from "solid-js/web";
import { PageVisit } from "../../../types";
import { ConfigContext } from "../../context/page";
import { normalizeState } from "../../normalization";
import { getClientConfig, getEventProject } from "../../request";
import { baseFilename } from "../../string";
import { getPublishedRevision } from "../revision";
import { useDatabase } from "./../prisma";
import { getSettings, notFoundPage } from "./../settings";
export const blueprintPaths: Record<string, string> = ((
globalThis as any
).npBlueprintPaths ??= {});
const passiveBlueprints: Record<string, boolean> = ((
globalThis as any
).npPassiveBlueprints ??= {});
let firstLoad = true;
const getPageState = async function ({
urlPath,
project,
}: {
urlPath: string;
project: NitroProject;
}) {
let pageRevision = await getPublishedRevision({
urlPath,
projectId: project.id,
});
if (!pageRevision) {
const notFoundPage_ = await notFoundPage({
projectId: project?.id,
});
if (notFoundPage_.value) {
pageRevision = await getPublishedRevision({
projectId: project?.id,
pageId: notFoundPage_.value,
});
}
}
if (!pageRevision) {
return;
}
const settings = await getSettings({
projectId: project?.id,
pageId: pageRevision.pageId,
});
settings.blueprintDefaults.value = {};
const prisma = useDatabase();
const fonts = await prisma.nitroFont.findMany({
where: {
projectId: project.id,
},
omit: {
createdAt: true,
updatedAt: true,
},
include: {
faces: {
omit: {
createdAt: true,
updatedAt: true,
},
},
},
});
return normalizeState({
pageRevision,
fonts,
presets: [],
settings,
passiveBlueprints,
});
};
export const getPageVisit = async (args: {
urlPath: string;
}): Promise<PageVisit | undefined> => {
const configCtx = useContext(ConfigContext)!;
// Removing trailing slash from urls *PT2*
// Trailing slashes are handled in two places: middleware & getPageVisit
// Here we handle client-side navigation (navigating from one page to the next)
if (args.urlPath !== "/" && args.urlPath.slice(-1) === "/") {
throw redirect(args.urlPath.slice(0, -1), {
status: 301,
});
}
const project = getEventProject();
const nitropageConfig = getClientConfig();
if (!project || !nitropageConfig) {
return;
}
const updateBlueprintFiles = firstLoad || !import.meta.env.PROD;
if (updateBlueprintFiles) {
try {
for (const [filePath, loader] of Object.entries(
nitropageConfig.blueprints(),
)) {
const module = await loader();
const id = module.id || baseFilename(filePath).toLowerCase();
blueprintPaths[id] = filePath;
if (module.passive) {
passiveBlueprints[id] = true;
}
}
firstLoad = false;
} catch (err) {
console.error(err);
}
}
const state = await getPageState({ urlPath: args.urlPath, project });
if (!state) {
return;
}
const isSSR = !!configCtx;
const event = getRequestEvent()!;
event.locals.npElements = {};
const dynamicBlueprintIds: Record<string, boolean> = {};
const blueprintIds: Record<string, boolean> = {};
const layoutIds: Record<string, boolean> = {};
for (const element of Object.values(state.elements)) {
if (element.blueprintId && blueprintPaths[element.blueprintId]) {
blueprintIds[element.blueprintId] = true;
if (element.dynamic) {
dynamicBlueprintIds[element.blueprintId] = true;
}
}
if (element.layoutId) {
layoutIds[element.layoutId] = true;
event.locals.npElements[element.id] = element;
continue;
}
if (import.meta.env.PROD && isSSR) {
event.locals.npElements[element.id] = { ...element };
if (!element.dynamic) {
// Data for non-dynamic elements doesn't have to be available for client hydration
// During ssr we access the data via event.locals.npElements
delete (element as any).data;
}
}
}
return {
state,
dynamicBlueprintIds: Object.keys(dynamicBlueprintIds),
blueprintIds: Object.keys(blueprintIds),
layoutIds: Object.keys(layoutIds),
};
};