From 8cd6dca1af73437f621b5b0618c2078ae9de587b Mon Sep 17 00:00:00 2001 From: Cavan Klinsky Date: Wed, 9 Dec 2020 20:39:49 -0500 Subject: [PATCH 1/3] adding gql node generator --- package.json | 232 ++++++++++++++++++++++++++++---------------- src/graphql2rest.js | 18 +++- 2 files changed, 164 insertions(+), 86 deletions(-) diff --git a/package.json b/package.json index 62d2ffe..b095afe 100644 --- a/package.json +++ b/package.json @@ -1,86 +1,150 @@ { - "name": "graphql2rest", - "version": "0.6.4", - "author": "Roy Mor ", - "contributors": [ - "Ray Luxembourg", - "Yotam Roth" - ], - "license": "MIT", - "description": "GraphQL to REST converter: automatically generate a RESTful API from your existing GraphQL API", - "keywords": [ - "graphql", - "rest", - "api", - "graphql2rest", - "restful", - "graphql-to-rest" - ], - "repository": { - "type": "git", - "url": "https://github.com/sisense/graphql2rest.git" - }, - "main": "./src/index.js", - "private": false, - "scripts": { - "lint": "eslint . --ext .js", - "test": "./node_modules/mocha/bin/_mocha --recursive './test/**/*.test.js'", - "test:coverage": "nyc npm run test" - }, - "dependencies": { - "del": "^5.1.0", - "dot-object": "^2.1.2", - "express": "~4.16.0", - "graphql": "^14.5.8", - "graphql-tag": "^2.10.1", - "http-status-codes": "^1.3.0", - "jmespath": "^0.15.0", - "lodash-pickdeep": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "lodash.omit": "^4.5.0", - "mingo": "^2.2.10", - "object-path": "^0.11.4", - "url-join": "^4.0.0", - "winston": "^3.1.0" - }, - "devDependencies": { - "@babel/cli": "^7.8.4", - "@babel/core": "^7.8.4", - "@babel/plugin-proposal-class-properties": "^7.8.3", - "@babel/plugin-proposal-decorators": "^7.8.3", - "@babel/plugin-proposal-do-expressions": "^7.8.3", - "@babel/plugin-proposal-export-default-from": "^7.8.3", - "@babel/plugin-proposal-export-namespace-from": "^7.8.3", - "@babel/plugin-proposal-function-bind": "^7.8.3", - "@babel/plugin-proposal-function-sent": "^7.8.3", - "@babel/plugin-proposal-json-strings": "^7.8.3", - "@babel/plugin-proposal-logical-assignment-operators": "^7.8.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-numeric-separator": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.8.3", - "@babel/plugin-proposal-pipeline-operator": "^7.8.3", - "@babel/plugin-proposal-throw-expressions": "^7.8.3", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.8.3", - "@babel/polyfill": "^7.8.3", - "@babel/preset-env": "^7.8.4", - "@babel/register": "^7.8.3", - "babel-eslint": "^10.0.1", - "babel-loader": "^8.0.5", - "chai": "^3.5.0", - "chai-fs": "^2.0.0", - "eslint": "6.8.0", - "eslint-config-airbnb-base": "^13.1.0", - "eslint-nibble": "^5.1.0", - "eslint-plugin-import": "^2.16.0", - "eslint-plugin-node": "^8.0.1", - "eslint-plugin-promise": "^4.0.1", - "eslint-plugin-simple-import-sort": "^3.0.0", - "eslint-plugin-unicorn": "^7.1.0", - "mocha": "7.1.0", - "nyc": "^15.0.0", - "run-middleware": "^0.9.10", - "webpack": "^4.41.5" - } + "_from": "github:sisense/graphql2rest", + "_id": "graphql2rest@0.6.4", + "_inBundle": false, + "_integrity": "", + "_location": "/graphql2rest", + "_phantomChildren": { + "accepts": "1.3.7", + "array-flatten": "1.1.1", + "content-type": "1.0.4", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "inherits": "2.0.3", + "iterall": "1.3.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "ms": "2.0.0", + "on-finished": "2.3.0", + "parseurl": "1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.6", + "range-parser": "1.2.1", + "safe-buffer": "5.1.2", + "safer-buffer": "2.1.2", + "type-is": "1.6.18", + "unpipe": "1.0.0", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "_requested": { + "type": "git", + "raw": "graphql2rest@github:sisense/graphql2rest", + "name": "graphql2rest", + "escapedName": "graphql2rest", + "rawSpec": "github:sisense/graphql2rest", + "saveSpec": "github:sisense/graphql2rest", + "fetchSpec": null, + "gitCommittish": null + }, + "_requiredBy": [ + "/" + ], + "_resolved": "github:sisense/graphql2rest#8251c41add2cb5d6f122b41b0f7e1fbbc61800b2", + "_spec": "graphql2rest@github:sisense/graphql2rest", + "_where": "/Users/2c4school/Development/onebody/sofa_king", + "author": { + "name": "Roy Mor", + "email": "roy.mor@sisense.com" + }, + "bugs": { + "url": "https://github.com/sisense/graphql2rest/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Ray Luxembourg" + }, + { + "name": "Yotam Roth" + } + ], + "dependencies": { + "del": "^5.1.0", + "dot-object": "^2.1.2", + "express": "~4.16.0", + "gql-generator-node": "^2.1.15", + "graphql": "^14.5.8", + "graphql-tag": "^2.10.1", + "http-status-codes": "^1.3.0", + "jmespath": "^0.15.0", + "lodash-pickdeep": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "lodash.omit": "^4.5.0", + "mingo": "^2.2.10", + "object-path": "^0.11.4", + "url-join": "^4.0.0", + "winston": "^3.1.0" + }, + "deprecated": false, + "description": "GraphQL to REST converter: automatically generate a RESTful API from your existing GraphQL API", + "devDependencies": { + "@babel/cli": "^7.8.4", + "@babel/core": "^7.8.4", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-proposal-do-expressions": "^7.8.3", + "@babel/plugin-proposal-export-default-from": "^7.8.3", + "@babel/plugin-proposal-export-namespace-from": "^7.8.3", + "@babel/plugin-proposal-function-bind": "^7.8.3", + "@babel/plugin-proposal-function-sent": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-logical-assignment-operators": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.8.3", + "@babel/plugin-proposal-pipeline-operator": "^7.8.3", + "@babel/plugin-proposal-throw-expressions": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.8.3", + "@babel/polyfill": "^7.8.3", + "@babel/preset-env": "^7.8.4", + "@babel/register": "^7.8.3", + "babel-eslint": "^10.0.1", + "babel-loader": "^8.0.5", + "chai": "^3.5.0", + "chai-fs": "^2.0.0", + "eslint": "6.8.0", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-nibble": "^5.1.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-node": "^8.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-simple-import-sort": "^3.0.0", + "eslint-plugin-unicorn": "^7.1.0", + "mocha": "7.1.0", + "nyc": "^15.0.0", + "run-middleware": "^0.9.10", + "webpack": "^4.41.5" + }, + "homepage": "https://github.com/sisense/graphql2rest#readme", + "keywords": [ + "graphql", + "rest", + "api", + "graphql2rest", + "restful", + "graphql-to-rest" + ], + "license": "MIT", + "main": "./src/index.js", + "name": "graphql2rest", + "private": false, + "repository": { + "type": "git", + "url": "git+https://github.com/sisense/graphql2rest.git" + }, + "scripts": { + "lint": "eslint . --ext .js", + "test": "./node_modules/mocha/bin/_mocha --recursive './test/**/*.test.js'", + "test:coverage": "nyc npm run test" + }, + "version": "0.6.4" } diff --git a/src/graphql2rest.js b/src/graphql2rest.js index d62883b..c6e8037 100644 --- a/src/graphql2rest.js +++ b/src/graphql2rest.js @@ -6,6 +6,7 @@ const omit = require('lodash.omit'); const httpStatuses = require('http-status-codes'); const objectPath = require('object-path'); const dot = require('dot-object'); +const gqlGeneratorNode = require("gql-generator-node"); const mingo = require('mingo'); const jmespath = require('jmespath'); @@ -83,7 +84,7 @@ const init = ( config = { ...configFileObj, - ...options + ...options, }; // options override configFileObj defaults, should always come last // populate global custom functions object @@ -114,6 +115,7 @@ const init = ( const legend = manifest.endpoints; errorMap = manifest.errors; config.queryStrings = queryStrings; + config.schema = schemaObj middlewares = middlewaresModule; errHandler = errorHandling(errorMap, config); @@ -331,9 +333,21 @@ const executeOperation = async ({ req, res, queryString, allParams, statusCode, debug(`Executing "${queryString.substring(0, 100).replace(/(\r\n|\n|\r)/gm, '')}..." with parameters:`); debug(pretty(allParams)); + const fieldList = {} + allParams.fields ? allParams.fields.split(",").forEach(x => fieldList[x] = !hiddenFields || hiddenFields.indexOf(x) === -1 ) : {} + + const query = gqlGeneratorNode.generateQuery({ + field: config.schema + .getQueryType() + .getFields()[operationName], + skeleton: fieldList + }) + + + Object.keys(allParams).forEach(ap => allParams[ap] === "true" ? allParams[ap] = true : allParams[ap] === "false" ? allParams[ap] = false : ap) try { response = await funcs.executeFn({ - query: gql(queryString), + query: gql(query), variables: allParams, context: { headers: req.headers, From 91eac013e15933ef58b970025066e002ece7beec Mon Sep 17 00:00:00 2001 From: Cavan Klinsky Date: Sat, 12 Dec 2020 11:54:11 -0500 Subject: [PATCH 2/3] allowing for loading of nested field --- src/graphql2rest.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/graphql2rest.js b/src/graphql2rest.js index c6e8037..14c52e7 100644 --- a/src/graphql2rest.js +++ b/src/graphql2rest.js @@ -326,6 +326,23 @@ const addRestEndpoint = ({ action, router }) => { } }; + +const setPath = (object, path, value) => { + path + .split('.') + .reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, object) + } + + +const generateFieldListObject = (fieldList, fieldParam, hiddenFields) => { + const value = !hiddenFields || hiddenFields.indexOf(fieldParam) === -1; + if (fieldParam.indexOf('.') > -1) { + setPath(fieldList, fieldParam, value) + } else { + fieldList[fieldParam] = value + } +}; + /* Operation invoker, called by Express callback function created by addRestEndpoint() */ const executeOperation = async ({ req, res, queryString, allParams, statusCode, hiddenFields, operationName }) => { let response; @@ -334,7 +351,7 @@ const executeOperation = async ({ req, res, queryString, allParams, statusCode, debug(pretty(allParams)); const fieldList = {} - allParams.fields ? allParams.fields.split(",").forEach(x => fieldList[x] = !hiddenFields || hiddenFields.indexOf(x) === -1 ) : {} + allParams.fields ? allParams.fields.split(",").forEach(x => generateFieldListObject(fieldList, x.trim(), hiddenFields)) : {} const query = gqlGeneratorNode.generateQuery({ field: config.schema From ee55a42042a0380f7b4347ceab317e1a5c9d17fa Mon Sep 17 00:00:00 2001 From: Cavan Klinsky Date: Fri, 17 Sep 2021 16:56:16 -0400 Subject: [PATCH 3/3] Create pull_request_template.md --- pull_request_template.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 pull_request_template.md diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..993534b --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,27 @@ +## Change description + +> Description here (or just add a link to Clubhouse) + +## Type of change +- [ ] Bug fix (fixes an issue) +- [ ] New feature (adds functionality) + +## Checklists + +### Development + +- [ ] Lint rules pass locally +- [ ] Application changes have been tested thoroughly +- [ ] Self-QA video added (if applicable) +- [ ] Automated tests covering modified code pass + +### Security + +- [ ] Security impact of change has been considered +- [ ] Code follows company security practices and guidelines + +### Code review + +- [ ] Pull request has a descriptive title and context useful to a reviewer. Screenshots or screencasts are attached as necessary +- [ ] Changes have been reviewed by at least one other contributor +- [ ] Pull request linked to task tracker where applicable