115 lines
4.3 KiB
JavaScript
115 lines
4.3 KiB
JavaScript
import {Kind, visit} from "graphql";
|
|
|
|
/**
|
|
* Apply sorters to the AST
|
|
* @param ast
|
|
* @param sorters
|
|
*/
|
|
export function applySorters(ast, sorters) {
|
|
sorters.forEach((sorter) => {
|
|
const [table, field] = sorter.field.split('.');
|
|
visit(ast, {
|
|
OperationDefinition: {
|
|
enter(node) {
|
|
node.selectionSet.selections.forEach((selection) => {
|
|
if (selection.name.value === table) {
|
|
let orderByArg = selection.arguments.find(arg => arg.name.value === 'order_by');
|
|
if (!orderByArg) {
|
|
orderByArg = {
|
|
kind: Kind.ARGUMENT,
|
|
name: {kind: Kind.NAME, value: 'order_by'},
|
|
value: {kind: Kind.OBJECT, fields: []}
|
|
};
|
|
selection.arguments.push(orderByArg);
|
|
}
|
|
|
|
const sorterField = {
|
|
kind: Kind.OBJECT_FIELD,
|
|
name: {kind: Kind.NAME, value: field},
|
|
value: {kind: Kind.ENUM, value: sorter.direction} // 'asc' for ascending order, 'desc' for descending order
|
|
};
|
|
|
|
orderByArg.value.fields.push(sorterField);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Apply filters to the AST
|
|
* @param ast
|
|
* @param filters
|
|
* @param filterFields
|
|
*/
|
|
export function applyFilters(ast, filters, filterFields) {
|
|
filters.forEach((filter) => {
|
|
const struct = filter.field.split('.');
|
|
visit(ast, {
|
|
OperationDefinition: {
|
|
enter(node) {
|
|
node.selectionSet.selections.forEach((selection) => {
|
|
if (selection.name.value === struct[0]) {
|
|
let whereArg = selection.arguments.find(arg => arg.name.value === 'where');
|
|
|
|
if (!whereArg) {
|
|
whereArg = {
|
|
kind: Kind.ARGUMENT,
|
|
name: {kind: Kind.NAME, value: 'where'},
|
|
value: {kind: Kind.OBJECT, fields: []}
|
|
};
|
|
selection.arguments.push(whereArg);
|
|
}
|
|
|
|
const filterField = {
|
|
kind: Kind.OBJECT_FIELD,
|
|
name: {kind: Kind.NAME, value: struct[1]},
|
|
value: {
|
|
kind: Kind.OBJECT,
|
|
fields: [{
|
|
kind: Kind.OBJECT_FIELD,
|
|
name: {kind: Kind.NAME, value: filter.operator},
|
|
value: {kind: Kind.STRING, value: filter.value}
|
|
}]
|
|
}
|
|
};
|
|
|
|
filterFields.push({kind: Kind.OBJECT, fields: [filterField]});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Wrap filters in an 'and' object
|
|
* @param ast
|
|
* @param filterFields
|
|
*/
|
|
export function wrapFiltersInAnd(ast, filterFields) {
|
|
visit(ast, {
|
|
OperationDefinition: {
|
|
enter(node) {
|
|
node.selectionSet.selections.forEach((selection) => {
|
|
let whereArg = selection.arguments.find(arg => arg.name.value === 'where');
|
|
if (filterFields.length > 1) {
|
|
const andFilter = {
|
|
kind: Kind.OBJECT_FIELD,
|
|
name: {kind: Kind.NAME, value: '_and'},
|
|
value: {kind: Kind.LIST, values: filterFields}
|
|
};
|
|
whereArg.value.fields.push(andFilter);
|
|
} else if (filterFields.length === 1) {
|
|
whereArg.value.fields.push(filterFields[0].fields[0]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|