- Progress check

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-02-08 11:15:32 -05:00
parent 85d1fd3c39
commit 0541d0ef1e

View File

@@ -1,5 +1,7 @@
import {Kind, visit} from "graphql";
/* eslint-disable no-loop-func */
/**
* Apply sorters to the AST
* @param ast
@@ -7,31 +9,53 @@ import {Kind, visit} from "graphql";
*/
export function applySorters(ast, sorters) {
sorters.forEach((sorter) => {
const [table, field] = sorter.field.split('.');
const fieldPath = 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);
// Loop through each sorter to apply it
// noinspection DuplicatedCode
let currentSelection = node; // Start with the root operation
// Navigate down the field path to the correct location
for (let i = 0; i < fieldPath.length - 1; i++) {
let found = false;
visit(currentSelection, {
Field: {
enter(node) {
if (node.name.value === fieldPath[i]) {
currentSelection = node; // Move down to the next level
found = true;
}
}
}
});
if (!found) break; // Stop if we can't find the next field in the path
}
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
// Apply the sorter at the correct level
if (currentSelection) {
const targetFieldName = fieldPath[fieldPath.length - 1];
let orderByArg = currentSelection.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: [] },
};
orderByArg.value.fields.push(sorterField);
currentSelection.arguments.push(orderByArg);
}
});
const sorterField = {
kind: Kind.OBJECT_FIELD,
name: { kind: Kind.NAME, value: targetFieldName },
value: { kind: Kind.ENUM, value: sorter.direction }, // Adjust if your schema uses a different type for sorting directions
};
// Add the new sorter condition
orderByArg.value.fields.push(sorterField);
}
}
}
});
@@ -42,49 +66,90 @@ export function applySorters(ast, sorters) {
* 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');
export function applyFilters(ast, filters) {
return visit(ast, {
OperationDefinition: {
enter(node) {
// Loop through each filter to apply it
filters.forEach(filter => {
const fieldPath = filter.field.split('.');
let currentSelection = node; // Start with the root operation
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}
}]
// Navigate down the field path to the correct location
for (let i = 0; i < fieldPath.length - 1; i++) {
let found = false;
visit(currentSelection, {
Field: {
enter(node) {
if (node.name.value === fieldPath[i]) {
currentSelection = node; // Move down to the next level
found = true;
}
}
};
}
});
if (!found) break; // Stop if we can't find the next field in the path
}
filterFields.push({kind: Kind.OBJECT, fields: [filterField]});
// Apply the filter at the correct level
if (currentSelection) {
const targetFieldName = fieldPath[fieldPath.length - 1];
let whereArg = currentSelection.arguments.find(arg => arg.name.value === 'where');
if (!whereArg) {
whereArg = {
kind: Kind.ARGUMENT,
name: { kind: Kind.NAME, value: 'where' },
value: { kind: Kind.OBJECT, fields: [] },
};
currentSelection.arguments.push(whereArg);
}
});
}
const filterValue = {
kind: getGraphQLKind(filter.value),
value: filter.value,
};
const filterField = {
kind: Kind.OBJECT_FIELD,
name: { kind: Kind.NAME, value: targetFieldName },
value: {
kind: Kind.OBJECT,
fields: [{
kind: Kind.OBJECT_FIELD,
name: { kind: Kind.NAME, value: filter.operator },
value: filterValue,
}],
},
};
// Add the new filter condition
whereArg.value.fields.push(filterField);
}
});
}
});
}
});
}
/**
* Get the GraphQL kind for a value
* @param value
* @returns {Kind|Kind.INT}
*/
function getGraphQLKind(value) {
if (typeof value === 'number') {
return value % 1 === 0 ? Kind.INT : Kind.FLOAT;
} else if (typeof value === 'boolean') {
return Kind.BOOLEAN;
} else if (typeof value === 'string') {
return Kind.STRING;
}
// Extend with more types as needed
}
/**
* Wrap filters in an 'and' object
* @param ast
@@ -112,3 +177,4 @@ export function wrapFiltersInAnd(ast, filterFields) {
});
}
/* eslint-enable no-loop-func */