@websolutespa/payload-plugin-bowl
Version:
Bowl PayloadCms plugin of the BOM Repository
336 lines (335 loc) • 12.4 kB
JavaScript
import { isArray, isObject } from '@websolutespa/bom-core';
import { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';
import qs from 'qs';
import { options } from '../../options';
import { InMemoryCache } from './cache.service';
import { parseDepth } from './collection.service';
import { getRoutes } from './route.service';
import { setMixerContext } from './utils';
const USE_CACHE = true;
const CACHE_ = new InMemoryCache();
function getStoreRequest_(req, market = 'all', locale = 'all') {
const { query = {} } = req;
const { where: w, market: m, locale: l, ...rest } = query;
const subQuery = {
market,
locale
};
req.query = {
...rest,
...subQuery
};
req.locale = locale;
return req;
}
async function getStore_(req) {
const { user } = req;
// console.log('getStore_.user', user);
if (!user) {
throw {
status: 403,
message: 'Unauthorized'
};
}
const roles = user.roles || [];
const tenants = Array.isArray(user.tenants) ? user.tenants.map((x)=>isObject(x) ? x.id : x) : [];
const keys = [
...roles,
...tenants
];
keys.sort();
// console.log('getStore_.roles', roles);
const strategy = req.query?.strategy === 'runtime' ? 'runtime' : 'static';
const market = 'all';
const locale = 'all';
const key = `store-${market}-${locale}-${strategy}-${keys.join('-')}`;
if (USE_CACHE && CACHE_.has(key) && req.query?.nocache != null && req.query?.t != null) {
// console.log('StoreService return from cache');
return CACHE_.get(key);
}
console.log('StoreService.getStore_', key);
// console.log('StoreService skipping cache');
const store = {};
const subRequest = getStoreRequest_(req, market, locale);
const context = await setMixerContext(subRequest, market, locale);
for (const slug of options.collections){
try {
const collection = req.payload.collections[slug];
// console.log('getStore.collection', collection.config.slug);
if (!collection) {
throw `collection '${slug}' not found`;
}
const disallowedCollection = options.actions.includes(slug) || options.users.includes(slug);
if (!disallowedCollection) {
const bowlCollection = options.bowlCollections.find((x)=>x.slug === slug);
// console.log('getStore_.bowlCollection', bowlCollection.slug, bowlCollection.type);
const type = bowlCollection?.type;
// console.log('getStore.type', type, 'strategy', strategy);
switch(type){
case 'withStatic':
{
if (strategy === 'runtime') {
store[slug] = [];
} else {
// we fetch static collection through custom endpoints
// fetching through local api would return empty array
const items = await fetchStaticCollection_(subRequest, slug);
// console.log('getStore_.withStatic', slug, items.length);
store[slug] = items;
}
}
break;
case 'withPage':
{
if (strategy === 'runtime') {
store[slug] = [];
} else {
// we fetch pages via local api
const items = await findCollection(subRequest, slug);
// console.log('getStore_.withPage', slug, items.length);
store[slug] = items;
/*
// we fetch pages via local api filtered by _status == published
const options: Omit<FindOptions, 'req'> = {
where: {
_status: {
equals: 'published',
},
},
};
const items = await findCollection<IEntity>(subRequest, slug, options);
// console.log('getStore_.withPage', slug, items.length);
store[slug] = items;
*/ }
}
break;
default:
{
if (strategy === 'runtime' && ![
'category',
'market',
'template',
'menu',
'label'
].includes(slug) || [
'media',
'template',
'email_config'
].includes(slug)) {
store[slug] = [];
} else {
// we fetch others collection via local api
const options = slug === 'category' ? {
sort: 'order'
} : undefined;
const items = await findCollection(subRequest, slug, options);
// console.log('getStore_.withCollection', slug, items.length);
store[slug] = items;
}
}
}
}
} catch (error) {
// 403 is expected, it means the collection is private
if (error.status !== 403) {
throw error;
}
console.log('StoreService', `no access granted for collection '${slug}'`);
store[slug] = [];
}
}
let app = {
id: 'app',
brand: {
name: 'Mixer',
social: []
}
};
try {
app = await findGlobal(subRequest, 'app');
} catch (error) {
console.log('IApp not found', error);
}
store.app = [
{
...app,
id: app.id || 'app'
}
];
try {
// we fetch locale through custom endpoint
const locale = await fetchGlobal_(subRequest, 'locale', {
richText: false
});
// we fetch locale through custom endpoint api/locale
// const localeCollection = await fetchCollection_(subRequest, 'locale', { richText: false });
// console.log('localeCollection', localeCollection);
store.locale = locale.items;
} catch (error) {
// 403 is expected, it means the collection is private
if (error.status !== 403) {
throw error;
}
console.log('StoreService', 'no access granted for collection \'locale\'');
store.locale = [];
}
// we handle routes separately
const routes = await getRoutes(subRequest);
store.route = routes;
CACHE_.set(key, store);
return store;
}
export async function findCollection(req, slug, findOptions) {
/*
const requestOptions = { lng: (req as any).lng, locale: req.locale, language: (req as any).language, languages: (req as any).languages };
console.log('requestOptions', requestOptions, options);
*/ // console.log('findCollection', slug);
const { query = {}, payload, user } = req;
const { draft } = query;
const depth = parseDepth(query.depth, 3);
// type FindOptions = ArgumentTypes<typeof payload.find>[0];
const findOptions_ = {
...findOptions,
collection: slug,
draft: draft === 'true',
locale: req.locale || 'all',
fallbackLocale: undefined,
// fallbackLocale: options.defaultLocale,
depth,
limit: 10000,
pagination: false,
req: req,
user: user,
overrideAccess: false
};
// console.log('findCollection', slug, findOptions_);
try {
const response = await payload.find(findOptions_);
// console.log('findCollection.success', slug);
const items = isArray(response) ? response : isArray(response.docs) ? response.docs : [];
/*
const firstItem = items[0];
if (firstItem) {
console.log('findCollection', slug, 'firstItem', firstItem);
}
*/ return items;
} catch (error) {
// 403 is expected, it means the collection is private
if (error.status !== 403) {
throw error;
}
console.log('StoreService.findCollection', `no access granted for collection '${slug}'`);
return [];
}
}
export async function findGlobal(req, slug, findOptions) {
// console.log('findGlobal', global);
const { query = {}, payload, user } = req;
const { draft } = query;
const depth = parseDepth(query.depth, 3);
const response = await payload.findGlobal({
slug,
draft: draft === 'true',
locale: req.locale || 'all',
fallbackLocale: undefined,
// fallbackLocale: options.defaultLocale,
depth,
req: req,
user: user,
...findOptions,
overrideAccess: false
});
return response;
}
export function getSearchUrl(req, overrideQuery) {
const { query = {} } = req;
const params = Object.assign({
locale: 'all',
depth: 1,
limit: 10000
}, query, overrideQuery);
const search = qs.stringify(params);
const url = search ? `?${search}` : '';
return url;
}
/*
async function fetchEndpoint_<T>(req: PayloadRequest, endpoint: string, query?: {}): Promise<T> {
try {
const apiUrl = getApiUrl(req);
const searchUrl = getSearchUrl(req, query);
const url = `${apiUrl}${endpoint}${searchUrl}`;
// console.log('fetchEndpoint_.url', url, req.headers.authorization);
const httpGetResponse = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
...(req.headers.authorization ? {
'Authorization': req.headers.authorization,
} : {}),
...(req.headers.cookie ? {
'Cookie': req.headers.cookie,
} : {}),
},
});
// console.log('fetchEndpoint_', url, req.headers.authorization, httpGetResponse.ok, httpGetResponse.status, httpGetResponse.statusText, httpGetResponse.type);
if (!httpGetResponse.ok) {
// console.log('fetchEndpoint_', url, endpoint, httpGetResponse.status, httpGetResponse.statusText);
throw httpGetResponse;
}
const json = await httpGetResponse.json();
return json;
} catch (error) {
console.log('StoreService.fetchEndpoint_.error', endpoint, error.statusText);
throw (error);
}
}
*/ async function fetchStaticCollection_(req, slug, query) {
try {
const response = await req.payload.find({
...req,
pagination: false,
collection: slug
});
return response.docs;
} catch (error) {
// 403 is expected, it means the collection is private
if (error.status !== 403) {
throw error;
}
console.log('StoreService.fetchStaticCollection_', `no access granted for collection '${slug}'`);
return [];
}
}
async function fetchGlobal_(req, slug, query) {
try {
const response = await req.payload.findGlobal({
...req,
slug
});
// console.log('fetchGlobal_', response);
return response;
} catch (error) {
// 403 is expected, it means the collection is private
if (error.status !== 403) {
throw error;
}
console.log('StoreService.fetchGlobal_', `no access granted for collection '${slug}'`);
return {
items: []
};
}
}
export const storeGet = {
path: '/store',
method: 'get',
handler: async (req)=>{
try {
const store = await getStore_(req);
return ResponseSuccess(store);
} catch (error) {
console.error('StoreService.storeGet.error', error);
return ResponseError(error);
}
}
};
//# sourceMappingURL=store.service.js.map