@opengis/fastify-table
Version:
core-plugins
116 lines (91 loc) • 5.16 kB
JavaScript
import {
config, getAccess, getTemplate, getMeta, setToken, applyHook, getToken, pgClients,
} from '../../../../utils.js';
import extraDataGet from '../../../plugins/extra/extraDataGet.js';
export default async function tableAPI(req, reply) {
const {
pg = pgClients.client, params, user = {}, query = {},
} = req;
const tokenData = await getToken({ token: params?.table, uid: user.uid, json: 1 }) || {};
const hookData = await applyHook('preTable', {
pg, table: params?.table, id: params?.id, ...tokenData || {}, user,
});
if (hookData?.message && hookData?.status) {
return { message: hookData?.message, status: hookData?.status };
}
const templateName = hookData?.table || tokenData.table || params.table;
const loadTable = await getTemplate('table', templateName);
if (!loadTable && !pg.pk?.[tokenData.table]) {
return { message: 'not found', status: 404 };
}
const { table = params.table, /* columns, */ form } = hookData || loadTable || tokenData;
const id = hookData?.id || tokenData.id || params.id;
if (tokenData && !id) return { message: {} };
if (!table && !id) {
return reply.status(400).send('not enough params');
}
const { actions = [], query: accessQuery } = await getAccess({
table, form, id, user,
}, pg) || {};
if (!tokenData && !config?.local && !config.security?.disableToken) {
return reply.status(400).send('invalid token');
}
if (!actions.includes('edit') && !config?.local && !tokenData) {
return reply.status(403).send('access restricted: actions');
}
const { pk, columns: dbColumns = [] } = await getMeta({ pg, table });
if (!pk) {
return reply.status(404).send(`table not found: ${table}`);
}
// const cols = columns.map((el) => el.name || el).join(',');
const formData = await getTemplate('form', form) || {};
const schema = formData?.schema || formData || {};
// skip DataTable from another table
const extraKeys = Object.keys(schema).filter((key) => schema[key]?.table && schema[key]?.parent_id && Object.hasOwn(schema[key], 'colModel'));
// skip non-existing columns
const columnList = dbColumns.map((el) => el.name || el).join(',');
const { fields = [] } = !loadTable?.table ? await pg.query(`select * from ${table} limit 0`) : {};
const cols = loadTable?.table
? Object.keys(schema || {}).filter((col) => columnList.includes(col) && !extraKeys.includes(col))?.map((col) => (col?.includes('geom') && schema?.[col]?.type === 'Geom' ? `st_asgeojson(${col})::json as "${col}"` : `"${col}"`))?.join(',')
: fields.map((el) => (el?.name?.includes('geom') && pg.pgType[el?.dataTypeID] === 'geometry' ? `st_asgeojson(${el.name})::json as "${el.name}"` : `"${el?.name}"`)).join(',');
const where = [`"${pk}" = $1`, loadTable?.query, accessQuery].filter(Boolean).filter((el) => (user?.user_type === 'superadmin' ? !el.includes('{{uid}}') : true));
const geom = dbColumns.find((el) => el.name === 'geom' && pg.pgType[el.dataTypeID] === 'geometry') ? ',st_asgeojson(geom)::json as geom' : '';
const q = `select "${pk}" as id, ${cols || '*'} ${geom} from ${table} t where ${where.join(' and ') || 'true'} limit 1`;
if (query?.sql === '1') {
const extraQ = extraKeys?.map((key) => {
const { colModel, table: extraTable, parent_id: parentId } = schema[key];
const colModel1 = Array.isArray(colModel) ? colModel : Object.values(colModel || {});
return colModel1.length ? `/*${key}*/ select ${parentId} as parent, ${colModel1.map((col) => col.name || col.key).join(',')} from ${extraTable} a where ${parentId}::text=$1` : null;
}).filter(el => el).join(';');
return `${q};${extraQ || ''}`.replace(/\$1/g, `'${id}'`);
}
const data = await pg.query(q.replace(/{{uid}}/, user?.uid), [id]).then(el => el.rows[0]);
if (!data) {
return reply.status(404).send(`object not found: ${id}`);
}
Object.keys(schema).filter(key => schema[key]?.type === 'DataTable').forEach(key => {
if (data[key] && !Array.isArray(data[key])) { data[key] = null; }
});
if (extraKeys?.length) {
await Promise.all(extraKeys?.map(async (key) => {
const { colModel, table: extraTable, parent_id: parentId } = schema[key];
const colModel1 = Array.isArray(colModel) ? colModel : Object.values(colModel || {});
const q1 = `select ${parentId} as parent, ${colModel1.map((col) => col.name || col.key).join(',')} from ${extraTable} a where ${parentId}=$1`;
// console.log(table, formName, q1);
const { rows: extraRows } = await pg.query(q1, [id]);
Object.assign(data, { [key]: extraRows });
}));
}
if (user?.uid && !config.security?.disableToken && actions.includes('edit')) {
data.token = tokenData?.table ? params.table : setToken({
ids: [JSON.stringify({ id, table, form })],
uid: user.uid,
array: 1,
})?.[0];
}
await extraDataGet({ rows: [data], table, form }, pg);
const res = await applyHook('afterTable', {
pg, table, payload: [data], user,
});
return res || data || {};
}