mirror of
https://github.com/directus/directus.git
synced 2026-01-25 23:48:58 -05:00
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
31
src/services/meta.ts
Normal 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
4
src/types/meta.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum Meta {
|
||||
TOTAL_COUNT = 'total_count',
|
||||
FILTER_COUNT = 'filter_count',
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user