@websolutespa/payload-plugin-bowl
Version:
Bowl PayloadCms plugin of the BOM Repository
171 lines (170 loc) • 8.12 kB
JavaScript
import { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';
import { decorateCategory_, decorateComponents_, decorateHref_, decorateNav_, decorateSchema_ } from '../decorators';
import { findByIDHandler } from '../utils/findByIDHandler';
import { findHandler } from '../utils/findHandler';
import { getCollectionItems } from './collection.service';
import { collectPageRedirects } from './redirect.service';
import { isMixerRequest } from './utils';
/**
* Rest api page collection get handler.
*/ export const pageIndexGet = (slug)=>({
path: '/',
method: 'get',
handler: async (req)=>{
try {
const { query } = req;
// console.log('pageIndexGet.query', ...Object.entries(query || {}));
if (!query) {
return findHandler(req);
}
const { locale, market, pagination } = query;
if (typeof market === 'string' && typeof locale === 'string') {
// const context = await setMixerContext(req, market, locale);
// console.log('pageIndexGet.context', context.market, context.locale, context.routes.length, context.categories.length);
if (pagination === 'true') {
return findHandler(req);
} else {
const items = await getCollectionItems(req, slug);
return ResponseSuccess(items);
}
} else if (pagination === 'false') {
const items = await getCollectionItems(req, slug);
return ResponseSuccess(items);
}
return findHandler(req);
} catch (error) {
console.error(`PageService.pageIndexGet.${slug}.error`, error);
return ResponseError(error);
}
}
});
/**
* Rest api page collection detail get handler.
*/ export const pageDetailGet = (slug)=>({
path: '/:id',
method: 'get',
handler: async (req)=>{
try {
const { query } = req;
// console.log('pageDetailGet.query', ...Object.entries(query || {}));
if (!query) {
return findByIDHandler(req);
}
const { market, locale } = query;
// console.log('pageDetailGet', 'market', market, 'locale', locale);
if (!(typeof market === 'string' && typeof locale === 'string')) {
return findByIDHandler(req);
}
req.query.depth = req.query.depth || '3';
// const context = await setMixerContext(req, market, locale);
// console.log('pageDetailGet.context', context.market, context.locale, context.routes.length, context.categories.length);
return findByIDHandler(req);
} catch (error) {
console.error(`PageService.pageDetailGet.${slug}.error`, error);
return ResponseError(error);
}
}
});
/**
* eg. PAYLOAD_PAGE_FIND = 'components'
*/ const afterPageOperationFind = process.env.PAYLOAD_FILTER_FIND ? process.env.PAYLOAD_FILTER_FIND.split(',').map((x)=>x.trim()) : [];
/**
* Modify record for Mixer when queried by market and locale.
*/ export const afterPageOperationHook = (collectionConfig)=>async ({ args, collection, req, operation, result })=>{
if (afterPageOperationFind.length > 0 && isMixerRequest(req) && operation === 'find' && req.pathname !== '/store' && req.query.optimize !== 'false') {
// console.log('withPage.afterPageOperationHook', operation, collection.slug, req.pathname);
result.docs = result.docs.map((x)=>Object.fromEntries(Object.entries(x).filter(([k, v])=>!afterPageOperationFind.includes(k))));
// console.log('withPage.afterPageOperationHook.done');
}
return result;
};
/**
* Decorate record for Mixer when queried by market and locale.
*/ export const afterPageReadHook = (collectionConfig)=>async ({ doc, req, context, findMany })=>{
const { market, locale, routes, categories } = context;
// console.log('afterPageReadHook', doc.title, query, market, locale);
if (!market || !locale || !routes || !categories) {
return doc;
}
const withSchema = await decorateSchema_(doc, collectionConfig.slug);
const withComponents = await decorateComponents_(withSchema, collectionConfig.slug, context);
const withCategory = await decorateCategory_(withComponents, collectionConfig.slug, context);
const withHref = await decorateHref_(withCategory, collectionConfig.slug, context);
const withNav = await decorateNav_(withHref, collectionConfig.slug, context);
return withNav;
/*
const withRichText = await decorateRichText_(withNav, collectionConfig.fields, context as Required<MixerContext>, req.payload.config);
return withRichText;
*/ };
/**
* Trigger revalidation in the Next.js Mixer app for a given page document.
*/ async function triggerPageRevalidation(schema, pageId) {
if (!schema || !pageId) return;
// todo: dedicated envVar for mixerUrl
const mixerUrl = process.env.PAYLOAD_PUBLIC_PREVIEW_URL;
const mixerSecret = process.env.MIXER_SECRET;
if (!mixerUrl || !mixerSecret) {
console.warn(`[revalidation] Skipping revalidation for ${schema}:${pageId}: MIXER_SECRET or PAYLOAD_PUBLIC_PREVIEW_URL is missing.`);
return;
}
try {
// console.log(`[revalidation] Triggering revalidation for ${schema}:${pageId}`);
const response = await fetch(`${mixerUrl}/api/__revalidate`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${mixerSecret}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
schema,
page: String(pageId)
})
});
if (!response.ok) {
const text = await response.text().catch(()=>'');
console.warn(`[revalidation] Failed to revalidate ${schema}:${pageId}`, response.status, text);
} else {
// console.log(`[revalidation] Successfully revalidated ${schema}:${pageId}`);
}
} catch (error) {
console.error(`[revalidation] Error triggering revalidation for ${schema}:${pageId}`, error);
}
}
/**
* Create a record of the pages collection related to the created document.
*/ export const afterPageChangeHook = async ({ doc, req, previousDoc, operation, collection })=>{
if (operation === 'update') {
const { query = {} } = req;
const { draft } = query;
// console.log('afterPageChange', operation, draft, doc.isDefault, previousDoc.slug, doc.slug);
if (!draft && doc.isDefault !== true && previousDoc.slug && doc.slug) {
const redirects = await collectPageRedirects(req, previousDoc, doc);
// console.log('redirects', redirects);
}
}
if (doc._status === 'published') {
triggerPageRevalidation(collection?.slug, doc.id);
}
return doc;
};
/**
* Delete records of the pages collection related to the deleted document.
*/ export const afterPageDeleteHook = async ({ req, id, doc })=>{
const { query = {} } = req;
const { draft } = query;
if (!draft && doc.isDefault !== true && doc.slug) {
console.log('RedirectService.deletePage !!!');
// !!! todo find and redirect to parentCategory connected to a page
}
}; /*
export const beforeValidateHook: CollectionBeforeValidateHook = async ({
data, // incoming data to update or create with
req, // full express request
operation, // name of the operation ie. 'create', 'update'
originalDoc, // original document
}) => {
console.log(data, originalDoc, req.query);
return data; // Return data to either create or update a document with
};
*/
//# sourceMappingURL=page.service.js.map