diff --git a/README.md b/README.md index ed08297..a70af1c 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,16 @@ [![Platform](https://img.shields.io/badge/platform-Node--RED-red)](https://nodered.org) ![Release](https://img.shields.io/npm/v/node-red-contrib-graphql.svg) ![NPM](https://img.shields.io/npm/dm/node-red-contrib-graphql.svg) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/6cbeb40ab5604b3ab99e6badc9469e8a)](https://www.codacy.com/gh/rgstephens/node-red-contrib-graphql?utm_source=github.com&utm_medium=referral&utm_content=rgstephens/node-red-contrib-graphql&utm_campaign=Badge_Grade) A NodeRed node to execute GraphQL Queries. -## Install - -Run command on Node-RED installation directory. - -``` -npm install node-red-contrib-graphql -``` - ## Change Log | Vers | Changes | | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2.0.1 | Update dependencies (`axios` & `mustache`), fix node-red scorecard issues | +| 2.1.0 | Bearer Token Authentication | +| 2.0.1 | Update dependencies (`axios` & `mustache`), fix node-red scorecard issues | | 2.0.0 | GraphQL response is now on `payload.graphql` instead of replacing `payload`. This is a breaking change. Addresses #32 | | 1.4.1 | Bump `follow-redirects` to 1.14.8 | | 1.4.0 | improve debug, bump `follow-redirects` | @@ -30,15 +24,15 @@ npm install node-red-contrib-graphql ## GraphQL Nodes -Provides a `GraphQL` node to support queries and a supporting Configuration node, called `graphql-server` to point to a GraphQL server. +Provides a `GraphQL` node to support queries and a configuration node called `graphql-server`. ### `graphql-server` Configuration Node Fields -| Name | Use | -| ------------- | ------------------- | -| Name | Node Name | -| Endpoint | URL to the endpoint | -| Authorization | Header | +| Name | Use | +| -------- | ------------------- | +| Name | Node Name | +| Endpoint | URL to the endpoint | +| Token | Bearer Token | ### `graphql` Function Node Fields @@ -48,46 +42,52 @@ Provides a `GraphQL` node to support queries and a supporting Configuration node | Endpoint | Configuration Node Name | | Query | Query or Mutation template | | Syntax | Mustache / plain | +| Token | Bearer Token | | Show Debug | Enable debug | -## Installing and using the Example Flow +## Countries API Example -This example flow uses the `node-red-contrib-graphql` node to query the Deutsche Bahn GraphQL service and get a station address and details on the next departure. +This example flow uses the `node-red-contrib-graphql` node to query the [Countries API](https://github.com/trevorblades/countries) built by GitHub user [Trevor Blades](https://github.com/trevorblades). -The example flow is in the file `countries.json`. Import this file from the clipboard under the NodeRed menu `Import > Clipboard`. You'll drag the example flow onto NodeRed. +The example flow is in the file `examples/countries.json`. Import this file from the clipboard under the NodeRed menu `Import > Clipboard`. You'll drag the example flow onto NodeRed. -![Example Flow](flow.png) +![Example Flow](images/flow.png) + +### Edit graphql node + +The GraphQL endpoint for is `https://countries.trevorblades.com/`. You can try it out [here](https://countries.trevorblades.com/). Here's the `graphql-node`: + +![Edit GraphQL Node](images/editGraphQL.png) + +### GraphQL Output This is the result sent to the debug window. -![Example Flow Output](flowOutput.png) +![Example Flow Output](images/flowOutput.png) -### Countries API +## Authentication Example -Here is the example using the [Countries API](https://github.com/trevorblades/countries) built by GitHub user [Trevor Blades](https://github.com/trevorblades), who used [Countries List](https://annexare.github.io/Countries/) as a source of data. +A bearer token can be provided for authentication. This is an example using the GitHub GraphQL API which is documented [here](https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#communicating-with-graphql). -The GraphQL endpoint for this API is `https://countries.trevorblades.com/`. You can try it out [here](https://countries.trevorblades.com/). +![Github Flow](images/githubFlow.png) -```json -# Get information on Germany and it's states -{ - country(code: "DE") { - name - native - capital - currency - phone - states { - code - name - } - } -} -``` +### Config Node Token + +If you have an token with a long life, you can provide the token in the `graphql-server` configuration node. For GitHub, user your GitHub PAT. + +![Github Config](images/githubGraphqlConfig.png) + +You can also provide the token in the `graphql` node. This is useful if a prior node performs the authentication and returns the token to be used for a limited session. + +![GitHub GraphQL](images/githubGraphql.png) + +## Custom Headers + +You can provide custom headers to the GraphQL node by attaching a `customHeaders` key to the `msg` and passing that to the GraphQL node. Here's an example that sets the `content-type` and a bearer token. -![Edit GraphQL Node](editGraphQL.png) +![Custom Headers](images/customHeaders.png) -## Template flavors and uses +## Templates and Variable Use There are two template flavors: diff --git a/editGraphQL.png b/editGraphQL.png deleted file mode 100644 index 2f8ca23..0000000 Binary files a/editGraphQL.png and /dev/null differ diff --git a/editGraphQLserver.png b/editGraphQLserver.png deleted file mode 100644 index b95c4df..0000000 Binary files a/editGraphQLserver.png and /dev/null differ diff --git a/examples/countriesFlow.json b/examples/countriesFlow.json index 8c12c7f..519d989 100644 --- a/examples/countriesFlow.json +++ b/examples/countriesFlow.json @@ -1 +1,110 @@ -[{"id":"a12eeec2ef7081f3","type":"graphql","z":"e596e2e15cffe546","name":"Get Country","graphql":"5ec8b7409ad68ba9","format":"json","syntax":"mustache","template":"{\n country(code: \"DE\") {\n name\n native\n capital\n currency\n phone\n states {\n code\n name\n }\n }\n}","showDebug":false,"x":290,"y":80,"wires":[["b1909e0fe42ed002","b4a00ddbf587d5db"],["b4a00ddbf587d5db"]]},{"id":"8ce305107f24099c","type":"inject","z":"e596e2e15cffe546","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":80,"wires":[["a12eeec2ef7081f3"]]},{"id":"b4a00ddbf587d5db","type":"debug","z":"e596e2e15cffe546","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":100,"wires":[]},{"id":"b1909e0fe42ed002","type":"template","z":"e596e2e15cffe546","name":"Country Details","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Country Name - {{payload.graphql.country.name}} / {{payload.country.native}}\nCapital: {{payload.graphql.country.capital}}\nCurrency: {{payload.graphql.country.currency}}\nStates:\n {{payload.graphql.country.states.0.name}}\n {{payload.graphql.country.states.1.name}}\n {{payload.graphql.country.states.2.name}}\n {{payload.graphql.country.states.3.name}}\n","output":"str","x":520,"y":60,"wires":[["080fbc2ad4668f85"]]},{"id":"080fbc2ad4668f85","type":"debug","z":"e596e2e15cffe546","name":"","active":true,"tosidebar":true,"console":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":60,"wires":[]},{"id":"5ec8b7409ad68ba9","type":"graphql-server","name":"Countries","endpoint":"https://countries.trevorblades.com"}] \ No newline at end of file +[ + { + "id": "a12eeec2ef7081f3", + "type": "graphql", + "z": "e596e2e15cffe546", + "name": "Get Country", + "graphql": "5ec8b7409ad68ba9", + "format": "json", + "syntax": "mustache", + "template": "{\n country(code: \"DE\") {\n name\n native\n capital\n currency\n phone\n states {\n code\n name\n }\n }\n}", + "showDebug": false, + "x": 290, + "y": 80, + "wires": [ + [ + "b1909e0fe42ed002", + "b4a00ddbf587d5db" + ], + [ + "b4a00ddbf587d5db" + ] + ] + }, + { + "id": "8ce305107f24099c", + "type": "inject", + "z": "e596e2e15cffe546", + "name": "", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 100, + "y": 80, + "wires": [ + [ + "a12eeec2ef7081f3" + ] + ] + }, + { + "id": "b4a00ddbf587d5db", + "type": "debug", + "z": "e596e2e15cffe546", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 490, + "y": 100, + "wires": [] + }, + { + "id": "b1909e0fe42ed002", + "type": "template", + "z": "e596e2e15cffe546", + "name": "Country Details", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "Country Name - {{payload.graphql.country.name}} / {{payload.graphql.country.native}}\nCapital: {{payload.graphql.country.capital}}\nCurrency: {{payload.graphql.country.currency}}\nStates:\n {{payload.graphql.country.states.0.name}}\n {{payload.graphql.country.states.1.name}}\n {{payload.graphql.country.states.2.name}}\n {{payload.graphql.country.states.3.name}}\n", + "output": "str", + "x": 520, + "y": 60, + "wires": [ + [ + "080fbc2ad4668f85" + ] + ] + }, + { + "id": "080fbc2ad4668f85", + "type": "debug", + "z": "e596e2e15cffe546", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "complete": "false", + "statusVal": "", + "statusType": "auto", + "x": 730, + "y": 60, + "wires": [] + }, + { + "id": "5ec8b7409ad68ba9", + "type": "graphql-server", + "name": "Countries", + "endpoint": "https://countries.trevorblades.com" + } +] \ No newline at end of file diff --git a/examples/deutscheBahnFlow.json b/examples/deutscheBahnFlow.json deleted file mode 100644 index fac7d59..0000000 --- a/examples/deutscheBahnFlow.json +++ /dev/null @@ -1,95 +0,0 @@ -[ - { - "id": "b236dd3d.25db5", - "type": "inject", - "z": "d1e47d94.4423f", - "name": "60 mins", - "topic": "", - "payload": "", - "payloadType": "date", - "repeat": "3600", - "crontab": "", - "once": true, - "x": 104.5, - "y": 92, - "wires": [ - [ - "81611922.cc5f68" - ] - ] - }, - { - "id": "149ee59b.df226a", - "type": "debug", - "z": "d1e47d94.4423f", - "name": "", - "active": true, - "console": "false", - "complete": "false", - "x": 810.5, - "y": 89, - "wires": [] - }, - { - "id": "3aa84960.a2c3f6", - "type": "graphql", - "z": "d1e47d94.4423f", - "name": "Station Details", - "graphql": "fbde2665.e26a18", - "format": "handlebars", - "syntax": "mustache", - "template": "{\n stationWithStationNumber(stationNumber: {{payload}}) {\n name\n mailingAddress {\n street\n city\n zipcode\n }\n federalState\n location {\n latitude\n longitude\n }\n szentrale {\n name\n email\n number\n phoneNumber\n }\n hasParking\n timetable {\n nextDepatures {\n type\n trainNumber\n platform\n time\n stops\n }\n }\n hasWiFi\n hasParking\n }\n}", - "x": 458, - "y": 91, - "wires": [ - [ - "2fd3f3ce.9e20dc" - ], - [] - ] - }, - { - "id": "2fd3f3ce.9e20dc", - "type": "template", - "z": "d1e47d94.4423f", - "name": "Station Details", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "Station Details - {{payload.stationWithStationNumber.name}}\n {{payload.stationWithStationNumber.mailingAddress.street}}\n {{payload.stationWithStationNumber.mailingAddress.city}}\n {{payload.stationWithStationNumber.federalState}}\nCentral Station:\n {{payload.stationWithStationNumber.szentrale.name}}\nNext Depature:\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.type}} {{payload.stationWithStationNumber.timetable.nextDepatures.0.trainNumber}}\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.time}}\nStops:\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.stops.0}}\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.stops.1}}\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.stops.2}}\n {{payload.stationWithStationNumber.timetable.nextDepatures.0.stops.3}}", - "x": 641, - "y": 155, - "wires": [ - [ - "149ee59b.df226a" - ] - ] - }, - { - "id": "81611922.cc5f68", - "type": "template", - "z": "d1e47d94.4423f", - "name": "Berlin Ostbahnhof", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "530", - "x": 280, - "y": 158, - "wires": [ - [ - "3aa84960.a2c3f6" - ] - ] - }, - { - "id": "fbde2665.e26a18", - "type": "graphql-server", - "z": "", - "endpoint": "https://developer.deutschebahn.com/free1bahnql/graphql", - "token": "", - "name": "Deutsche Bahn" - } -] \ No newline at end of file diff --git a/examples/githubLogin.json b/examples/githubLogin.json new file mode 100644 index 0000000..51563b7 --- /dev/null +++ b/examples/githubLogin.json @@ -0,0 +1,95 @@ +[ + { + "id": "cc97ba59b7f7b1c6", + "type": "inject", + "z": "ecee231023f6944e", + "name": "", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": false, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 160, + "y": 140, + "wires": [ + [ + "5ce1d5e8c233c062" + ] + ] + }, + { + "id": "5ce1d5e8c233c062", + "type": "graphql", + "z": "ecee231023f6944e", + "name": "Get Login id", + "graphql": "4a27e34566452125", + "format": "handlebars", + "template": "{\n viewer {\n login\n }\n}", + "syntax": "mustache", + "token": "", + "showDebug": false, + "credentials": {}, + "x": 350, + "y": 140, + "wires": [ + [ + "fe44bcf58ee82812" + ], + [ + "35a20afebf41f631" + ] + ] + }, + { + "id": "fe44bcf58ee82812", + "type": "debug", + "z": "ecee231023f6944e", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload.graphql.viewer.login", + "targetType": "msg", + "statusVal": "", + "statusType": "auto", + "x": 660, + "y": 120, + "wires": [] + }, + { + "id": "35a20afebf41f631", + "type": "debug", + "z": "ecee231023f6944e", + "name": "", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 570, + "y": 160, + "wires": [] + }, + { + "id": "4a27e34566452125", + "type": "graphql-server", + "name": "GitHub", + "endpoint": "https://api.github.com/graphql", + "token": "" + } +] \ No newline at end of file diff --git a/flowOutput.png b/flowOutput.png deleted file mode 100644 index 029e815..0000000 Binary files a/flowOutput.png and /dev/null differ diff --git a/graphql.html b/graphql.html index 0b3f1bc..274b021 100644 --- a/graphql.html +++ b/graphql.html @@ -8,8 +8,8 @@