From 6f185372b348aae1b1093c960e904ac41d49fc96 Mon Sep 17 00:00:00 2001 From: Bhanu Agrawal Date: Fri, 14 Oct 2022 17:31:18 +0530 Subject: [PATCH] Added graphql to fql converter --- .gitignore | 1 + graphqlToFQLConverter.js | 113 +++++++++++++++++++++++++++++++++++++++ package-lock.json | 31 +++++++++++ package.json | 23 ++++++++ 4 files changed, 168 insertions(+) create mode 100644 .gitignore create mode 100644 graphqlToFQLConverter.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/graphqlToFQLConverter.js b/graphqlToFQLConverter.js new file mode 100644 index 0000000..47c7f88 --- /dev/null +++ b/graphqlToFQLConverter.js @@ -0,0 +1,113 @@ +const { parse } = require('graphql/language/parser'); + +const capitalizeFirstLetter = (string) => { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +const composeOperator = (stringArray) => { + let result = stringArray[1]; + for (let index = 2; index < stringArray.length; index++) { + result += capitalizeFirstLetter(stringArray[index]); + } + return result; +} + +const getCollectionSortCriteria = (arg) => { + const [key, direction] = arg.value.value.split('_'); + return `order(${direction.toLowerCase()}(.${key}))`; +} + +const buildCriteriaString = (fields) => { + let criteriaString = ''; + for (let index = 0; index < fields.length; index++) { + const splittedString = fields[index].name.value.split("_"); + const key = splittedString[0]; + const operator = composeOperator(splittedString); + const value = fields[index].value.value; + + criteriaString += `.${key}.${operator}("${value}")`; + criteriaString += index < fields.length - 1 ? ' && ' : ''; + } + return criteriaString; +} + +const getCollectionFilterCriteria = (arg) => { + const { fields } = arg.value; + const criteriaString = buildCriteriaString(fields); + return `firstWhere(${criteriaString})`; +} + +const getCollectionLevelCriteria = (args) => { + let sortCriteria = null; + let filterCriteria = null; + for (const arg of args) { + const keyword = arg.name.value; + if (keyword === 'orderBy') { + sortCriteria = getCollectionSortCriteria(arg); + } + else if (keyword === 'where') { + filterCriteria = getCollectionFilterCriteria(arg); + } + } + return { sortCriteria, filterCriteria }; +} + +const buildArrayExpression = (name, args) => { + const { fields } = args[0].value; + const criteriaString = buildCriteriaString(fields); + return `${name}.filter(${criteriaString}).at(0)`; +} + +const getLastExpression = (input, result) => { + if (!input) return result; + result += '.'; + const selections = input.selections[0]; + const name = selections?.name?.value; + const args = selections?.arguments; + if (!args || args.length == 0) { + result += name; + } + else { + result += buildArrayExpression(name, args); + } + return getLastExpression(selections.selectionSet, result); +} + +// TRP_TreatmentPlans.all.order(asc(.name)).firstWhere(.name.startsWith("Jamie")) +//.treatments.filter(.title.startsWith("Union")).at(0).selectedItems + +const query = ` +query MyQuery { + TRP_TreatmentPlans(orderBy: name_ASC, where: {name_starts_with: "Jamie"}) { + treatments(where: {title_starts_with: "Union"}) { + selectedItems { + quantity { + items + } + } + } + } + } +`; + +const convertGraphQLToFQL = (query) => { + let fqlString = ''; + const parsedQuery = parse(query); + const selections = parsedQuery.definitions[0].selectionSet.selections[0]; + const collectionName = selections.name.value; + const args = selections.arguments; + + fqlString += `${collectionName}.all`; + const { sortCriteria, filterCriteria } = getCollectionLevelCriteria(args); + + fqlString += sortCriteria ? `.${sortCriteria}` : ''; + fqlString += filterCriteria ? `.${filterCriteria}` : ''; + + const input = selections.selectionSet; + const lastExpression = getLastExpression(input, ''); + fqlString += lastExpression; + + return fqlString; +}; + +console.log(convertGraphQLToFQL(query)); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..704a4eb --- /dev/null +++ b/package-lock.json @@ -0,0 +1,31 @@ +{ + "name": "rules-engine", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "rules-engine", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "graphql": "^16.6.0" + } + }, + "node_modules/graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + } + }, + "dependencies": { + "graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..435a72e --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "rules-engine", + "version": "1.0.0", + "description": "", + "main": "composer.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Dechea/rules-engine.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Dechea/rules-engine/issues" + }, + "homepage": "https://github.com/Dechea/rules-engine#readme", + "dependencies": { + "graphql": "^16.6.0" + } +}