Merge pull request #19 from directus/meta

Add meta query param
This commit is contained in:
Rijk van Zanten
2020-06-19 19:01:30 -04:00
committed by GitHub
6 changed files with 74 additions and 3 deletions

View File

@@ -5,6 +5,7 @@
import { RequestHandler } from 'express';
import { Query, Sort, Filter, FilterOperator } from '../types/query';
import { Meta } from '../types/meta';
const sanitizeQuery: RequestHandler = (req, res, next) => {
if (!req.query) return;
@@ -39,6 +40,10 @@ const sanitizeQuery: RequestHandler = (req, res, next) => {
query.single = sanitizeSingle(req.query.single);
}
if (req.query.meta) {
query.meta = sanitizeMeta(req.query.meta);
}
res.locals.query = query;
return next();
};
@@ -95,3 +100,17 @@ function sanitizePage(rawPage: any) {
function sanitizeSingle(rawSingle: any) {
return true;
}
function sanitizeMeta(rawMeta: any) {
if (rawMeta === '*') {
return Object.values(Meta);
}
if (rawMeta.includes(',')) {
return rawMeta.split(',');
}
if (Array.isArray(rawMeta)) {
return rawMeta;
}
}

View File

@@ -17,8 +17,11 @@ const validateQuery: RequestHandler = asyncHandler(async (req, res, next) => {
const query: Query = res.locals.query;
await validateParams(req.params.collection, query);
await validateFields(req.params.collection, query);
await Promise.all([
validateParams(req.params.collection, query),
validateFields(req.params.collection, query),
validateMeta(query),
]);
return next();
});
@@ -55,4 +58,10 @@ async function validateFields(collection: string, query: Query) {
});
}
async function validateMeta(query: Query) {
if (!query.meta) return;
return query.meta.every((metaField) => []);
}
export default validateQuery;

View File

@@ -4,6 +4,7 @@ import { createItem, readItems, readItem, updateItem, deleteItem } from '../serv
import sanitizeQuery from '../middleware/sanitize-query';
import collectionExists from '../middleware/collection-exists';
import validateQuery from '../middleware/validate-query';
import * as MetaService from '../services/meta';
const router = express.Router();
@@ -22,9 +23,13 @@ router.get(
sanitizeQuery,
validateQuery,
asyncHandler(async (req, res) => {
const records = await readItems(req.params.collection, res.locals.query);
const [records, meta] = await Promise.all([
readItems(req.params.collection, res.locals.query),
MetaService.getMetaForQuery(req.params.collection, res.locals.query),
]);
return res.json({
meta: meta,
data: records,
});
})

31
src/services/meta.ts Normal file
View File

@@ -0,0 +1,31 @@
import { Query } from '../types/query';
import database from '../database';
export const getMetaForQuery = async (collection: string, query: Query) => {
if (!query.meta) return;
const results = await Promise.all(
query.meta.map((metaVal) => {
if (metaVal === 'total_count') return totalCount(collection);
if (metaVal === 'filter_count') return filterCount(collection, query);
})
);
return results.reduce((metaObject: Record<string, any>, value, index) => {
return {
...metaObject,
[query.meta[index]]: value,
};
}, {});
};
export const totalCount = async (collection: string) => {
const records = await database(collection).count('*');
return records[0].count;
};
export const filterCount = async (collection: string, query: Query) => {
/** @TODO use actual query builder logic from items service to get count */
const records = await database(collection).count('*');
return records[0].count;
};

4
src/types/meta.ts Normal file
View File

@@ -0,0 +1,4 @@
export enum Meta {
TOTAL_COUNT = 'total_count',
FILTER_COUNT = 'filter_count',
}

View File

@@ -1,3 +1,5 @@
import { Meta } from './meta';
export type Query = {
fields?: string[];
sort?: Sort[];
@@ -6,6 +8,7 @@ export type Query = {
offset?: number;
page?: number;
single?: boolean;
meta?: Meta[];
};
export type Sort = {