├── .npmignore
├── .gitattributes
├── examples
├── README.md
├── pr
│ └── 196
│ │ ├── client
│ │ ├── src
│ │ │ ├── App.re
│ │ │ ├── Index.re
│ │ │ ├── index.html
│ │ │ ├── Client.re
│ │ │ ├── Wallets.re
│ │ │ └── Settings.re
│ │ ├── .gitignore
│ │ ├── build
│ │ │ └── index.html
│ │ ├── bsconfig.json
│ │ ├── webpack.config.js
│ │ ├── package.json
│ │ ├── README.md
│ │ └── graphql_schema.json
│ │ └── server
│ │ ├── package.json
│ │ └── index.js
├── swapi
│ ├── .gitignore
│ ├── src
│ │ ├── index.re
│ │ ├── Page.re
│ │ ├── ShowLivePersons.re
│ │ ├── PersonById.re
│ │ ├── PersonByIdDelete.re
│ │ ├── SubscribeToPersons.re
│ │ ├── GetPersonById.re
│ │ ├── AddPerson.re
│ │ ├── GetPerson.re
│ │ ├── Persons.re
│ │ ├── Client.re
│ │ ├── DeletePerson.re
│ │ ├── DeletePersonButton.re
│ │ └── PersonSubscribeToMore.re
│ ├── index.html
│ ├── webpack.config.js
│ ├── README.md
│ ├── bsconfig.json
│ └── package.json
└── realtime-chat-application
│ ├── src
│ ├── Theme.re
│ ├── index.re
│ ├── Handler.re
│ ├── Messages.re
│ ├── App.re
│ ├── Header.re
│ ├── ChatBubble.re
│ ├── index.html
│ ├── NewMessageNotification.re
│ ├── ReasonApolloClient.re
│ ├── AddMessage.re
│ └── MessagesContainer.re
│ ├── public
│ ├── favicon.ico
│ ├── notification.mp3
│ ├── notification.ogg
│ ├── manifest.json
│ └── index.html
│ ├── webpack.config.js
│ ├── bsconfig.json
│ ├── .gitignore
│ ├── package.json
│ ├── README.md
│ └── graphql_schema.json
├── .travis.yml
├── src
├── ApolloProvider.re
├── ApolloUtilities.re
├── ReasonApolloUtils.re
├── ApolloConsumer.re
├── graphql-types
│ ├── ReasonApolloSubscription.rei
│ ├── ReasonApolloSubscription.re
│ ├── ReasonApolloMutation.rei
│ ├── ReasonApolloQuery.rei
│ ├── ReasonApolloMutation.re
│ └── ReasonApolloQuery.re
├── ReasonApollo.re
├── ApolloInMemoryCache.re
├── ReasonApolloTypes.re
├── ApolloLinks.re
└── ApolloClient.re
├── .github
├── PULL_REQUEST_TEMPLATE.md
└── ISSUE_TEMPLATE.md
├── .gitignore
├── bsconfig.json
├── LICENSE
├── package.json
├── CONTRIBUTING.md
└── README.md
/.npmignore:
--------------------------------------------------------------------------------
1 | examples
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.re linguist-language=Reason
2 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | This folder contains working examples of usage of the library.
--------------------------------------------------------------------------------
/examples/pr/196/client/src/App.re:
--------------------------------------------------------------------------------
1 | [@react.component]
2 | let make = () =>
;
3 |
--------------------------------------------------------------------------------
/examples/pr/196/client/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .merlin
3 | .bsb.lock
4 | npm-debug.log
5 | /lib/bs/
6 | /node_modules/
7 |
--------------------------------------------------------------------------------
/examples/swapi/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .merlin
3 | .bsb.lock
4 | npm-debug.log
5 | /lib/bs/
6 | /node_modules/
7 | build
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/Theme.re:
--------------------------------------------------------------------------------
1 | open Css;
2 |
3 | let primaryColor = purple;
4 | let secondaryColor = tomato;
5 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apollographql/reason-apollo/HEAD/examples/realtime-chat-application/public/favicon.ico
--------------------------------------------------------------------------------
/examples/realtime-chat-application/public/notification.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apollographql/reason-apollo/HEAD/examples/realtime-chat-application/public/notification.mp3
--------------------------------------------------------------------------------
/examples/realtime-chat-application/public/notification.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apollographql/reason-apollo/HEAD/examples/realtime-chat-application/public/notification.ogg
--------------------------------------------------------------------------------
/examples/pr/196/client/src/Index.re:
--------------------------------------------------------------------------------
1 | ReactDOMRe.renderToElementWithId(
2 |
3 |
4 | ,
5 | "index1",
6 | );
7 |
--------------------------------------------------------------------------------
/examples/swapi/src/index.re:
--------------------------------------------------------------------------------
1 | ReactDOMRe.renderToElementWithId(
2 |
3 |
4 |
5 | , "index");
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "8"
5 | cache:
6 | yarn: true
7 | directories:
8 | - node_modules
9 | install: npm install
10 | script:
11 | - npm run build
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/index.re:
--------------------------------------------------------------------------------
1 | ReactDOMRe.renderToElementWithId(
2 |
3 |
4 |
5 | , "root");
6 |
--------------------------------------------------------------------------------
/src/ApolloProvider.re:
--------------------------------------------------------------------------------
1 | open ApolloClient;
2 |
3 | [@bs.module "react-apollo"] [@react.component]
4 | external make:
5 | (~client: generatedApolloClient, ~children: React.element) => React.element =
6 | "ApolloProvider";
7 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/Handler.re:
--------------------------------------------------------------------------------
1 | let onChange = evt => (
2 | evt
3 | |> ReactEventRe.Form.target
4 | |> ReactDOMRe.domElementToObj
5 | )##value;
6 |
--------------------------------------------------------------------------------
/examples/swapi/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Reason Example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/ApolloUtilities.re:
--------------------------------------------------------------------------------
1 | type operationDefinitionNode = {
2 | kind: string,
3 | operation: string,
4 | };
5 |
6 | [@bs.module "apollo-utilities"]
7 | external getMainDefinition:
8 | ReasonApolloTypes.documentNodeT => operationDefinitionNode =
9 | "getMainDefinition";
10 |
--------------------------------------------------------------------------------
/examples/pr/196/client/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ReasonReact Examples
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/pr/196/client/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ReasonReact Examples
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/swapi/src/Page.re:
--------------------------------------------------------------------------------
1 | [@react.component]
2 | let make = () =>
3 |
4 |
{React.string("Star Wars")}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
;
13 |
--------------------------------------------------------------------------------
/examples/pr/196/client/src/Client.re:
--------------------------------------------------------------------------------
1 | /* Create an InMemoryCache */
2 | let inMemoryCache = ApolloInMemoryCache.createInMemoryCache();
3 |
4 | /* Create an HTTP Link */
5 | let httpLink = ApolloLinks.createHttpLink(~uri="http://localhost:4000", ());
6 |
7 | let instance =
8 | ReasonApollo.createApolloClient(~link=httpLink, ~cache=inMemoryCache, ());
9 |
--------------------------------------------------------------------------------
/examples/swapi/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const isProd = process.env.NODE_ENV === "production";
3 |
4 | module.exports = {
5 | entry: './src/index.bs.js',
6 | mode: isProd ? "production" : "development",
7 | output: {
8 | path: path.join(__dirname, "build"),
9 | filename: 'bundle.js',
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const isProd = process.env.NODE_ENV === "production";
3 |
4 | module.exports = {
5 | entry: './src/index.bs.js',
6 | mode: isProd ? "production" : "development",
7 | output: {
8 | path: path.join(__dirname, "build"),
9 | filename: 'bundle.js',
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/examples/pr/196/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "start": "nodemon index.js"
8 | },
9 | "devDependencies": {
10 | "nodemon": "^1.19.1"
11 | },
12 | "dependencies": {
13 | "apollo-server": "^2.6.1",
14 | "graphql": "^14.3.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ReasonApolloUtils.re:
--------------------------------------------------------------------------------
1 | let getNonEmptyObj = jsObj =>
2 | switch (jsObj |> Js.Nullable.toOption) {
3 | | None => None
4 | | Some(data) =>
5 | switch (Js.Json.decodeObject(data)) {
6 | | None => None
7 | | Some(data) =>
8 | switch (Array.length(Js.Dict.keys(data))) {
9 | | 0 => None
10 | | _ => Some(Js.Json.object_(data))
11 | }
12 | }
13 | };
--------------------------------------------------------------------------------
/examples/swapi/README.md:
--------------------------------------------------------------------------------
1 | # Reason-Apollo Swapi
2 |
3 | This project illustrates the usage of reason-apollo to query the [SWAPI](http://swapi.apis.guru/) and serves as an example on how to use the project.
4 |
5 | ## Getting started
6 |
7 | ```
8 | npm install
9 | npm start
10 | # in another tab
11 | npm run webpack
12 | ```
13 |
14 | Then modify whichever file in `src` and refresh the page to see the changes.
15 |
--------------------------------------------------------------------------------
/src/ApolloConsumer.re:
--------------------------------------------------------------------------------
1 | open ApolloClient;
2 |
3 | module JsConsumer = {
4 | [@bs.module "react-apollo"] [@react.component]
5 | external make:
6 | (~children: generatedApolloClient => React.element) => React.element =
7 | "ApolloConsumer";
8 | };
9 |
10 | [@react.component]
11 | let make = (~children: generatedApolloClient => React.element) =>
12 | {client => children(client)} ;
13 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/Messages.re:
--------------------------------------------------------------------------------
1 | let component = ReasonReact.statelessComponent("Messages");
2 |
3 | let make = (
4 | ~messages,
5 | ~onLoad,
6 | _children
7 | ) => {
8 | ...component,
9 | didMount: _self => {
10 | onLoad()
11 | },
12 | render: _self =>
13 | {
14 | messages
15 | |> Js.Array.map(message => )
16 | |> ReasonReact.array
17 | }
18 |
19 | };
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Pull Request Labels**
4 |
5 |
8 |
9 | - [ ] feature
10 | - [ ] blocking
11 | - [ ] docs
12 |
13 |
17 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/App.re:
--------------------------------------------------------------------------------
1 | module Styles = {
2 | open Css;
3 |
4 | let container = style([
5 | marginBottom(px(100))
6 | ]);
7 | };
8 |
9 | let component = ReasonReact.statelessComponent("App");
10 |
11 | let make = _children => {
12 | ...component,
13 | render: _self =>
14 | ,
20 | };
21 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/Header.re:
--------------------------------------------------------------------------------
1 | module Styles = {
2 | open Css;
3 |
4 | let header = style([
5 | backgroundColor(Theme.primaryColor),
6 | color(white),
7 | fontSize(rem(2.0)),
8 | padding(px(20))
9 | ]);
10 | };
11 |
12 | let component = ReasonReact.statelessComponent("Header");
13 |
14 | let make = _children => {
15 | ...component,
16 | render: _self => ("Chat Application" |> ReasonReact.string)
,
17 | };
18 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/bsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reason-scripts",
3 | "sources": ["src", "lib"],
4 | "bs-dependencies": ["reason-react", "@glennsl/bs-jest", "bs-css", "reason-apollo"],
5 | "reason": {
6 | "react-jsx": 2
7 | },
8 | "bsc-flags": ["-bs-super-errors"],
9 | "refmt": 3,
10 | "package-specs": {
11 | "module": "commonjs",
12 | "in-source": true
13 | },
14 | "ppx-flags": [
15 | "graphql_ppx/ppx"
16 | ],
17 | "suffix": ".bs.js"
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 | package-lock.json
7 |
8 |
9 | # Dependency directories
10 | node_modules/
11 |
12 | # Optional npm cache directory
13 | .npm
14 |
15 | # Optional eslint cache
16 | .eslintcache
17 |
18 | # Yarn Integrity file
19 | .yarn-integrity
20 |
21 | .merlin
22 |
23 | lib
24 | *.bs.js
25 |
26 | **/*.swp
27 | **/.graphql_ppx_cache
28 |
29 | .bsb.lock
30 | schema.graphql
31 | .DS_Store
32 |
33 | # Editor
34 | **/.idea
35 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # bucklescript
13 | /lib
14 | /types
15 | .merlin
16 | *.bs.js
17 |
18 | # misc
19 | .DS_Store
20 | .env.local
21 | .env.development.local
22 | .env.test.local
23 | .env.production.local
24 |
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 | **/*.swp
29 |
--------------------------------------------------------------------------------
/examples/swapi/src/ShowLivePersons.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | [@react.component]
4 | let make = (~persons, ~getLiveData) => {
5 | React.useEffect0(() => {
6 | getLiveData();
7 | /* Nothing to clean */
8 | None;
9 | });
10 | persons
11 | |> Array.mapi((index, person) =>
12 | string_of_int}>
13 | {person##name |> ste}
14 |
15 |
{"ID: " ++ person##id |> ste}
16 |
17 | )
18 | |> React.array;
19 | };
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Issue Labels**
4 |
5 |
8 |
9 | - [ ] has-reproduction
10 | - [ ] feature
11 | - [ ] docs
12 | - [ ] blocking
13 | - [ ] good first issue
14 |
15 |
19 |
--------------------------------------------------------------------------------
/examples/pr/196/client/bsconfig.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "react-hooks-template",
4 | "reason": {
5 | "react-jsx": 3
6 | },
7 | "sources": {
8 | "dir" : "src",
9 | "subdirs" : true
10 | },
11 | "package-specs": [{
12 | "module": "commonjs",
13 | "in-source": true
14 | }],
15 | "suffix": ".bs.js",
16 | "namespace": true,
17 | "bs-dependencies": [
18 | "reason-react",
19 | "reason-apollo"
20 | ],
21 | "ppx-flags": [
22 | "graphql_ppx/ppx"
23 | ],
24 | "refmt": 3
25 | }
26 |
--------------------------------------------------------------------------------
/bsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reason-apollo",
3 | "sources": [
4 | {
5 | "dir": "src",
6 | "public": "all",
7 | "subdirs": ["graphql-types"]
8 | },
9 | {
10 | "dir": "examples",
11 | "type": "dev"
12 | }
13 | ],
14 | "bs-dependencies": ["reason-react"],
15 | "bsc-flags": ["-bs-super-errors"],
16 | "reason": {
17 | "react-jsx": 3
18 | },
19 | "refmt": 3,
20 | "package-specs": [
21 | {
22 | "module": "es6",
23 | "in-source": true
24 | }
25 | ],
26 | "suffix": ".bs.js"
27 | }
28 |
--------------------------------------------------------------------------------
/examples/swapi/src/PersonById.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | [@react.component]
4 | let make = () => {
5 | let (id, setId) = React.useState(() => "");
6 |
7 |
22 |
;
23 | };
24 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/ChatBubble.re:
--------------------------------------------------------------------------------
1 | module Styles = {
2 | open Css;
3 | let container = userMsg => style([
4 | margin(px(5)),
5 | padding(px(5)),
6 | backgroundColor(Theme.secondaryColor),
7 | color(white),
8 | borderRadius(px(3)),
9 | width(px(300))
10 | ]);
11 | };
12 |
13 | let component = ReasonReact.statelessComponent("Message");
14 |
15 | let make = (~message, _children) => {
16 | ...component,
17 | render: _ =>
18 |
19 | (message##author##name ++ " : " ++ message##text |> ReasonReact.string)
20 |
,
21 | };
22 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Chat App
8 |
9 |
15 |
16 |
17 |
18 | You need to enable JavaScript to run this app.
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Chat App
8 |
9 |
15 |
16 |
17 |
18 | You need to enable JavaScript to run this app.
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/swapi/src/PersonByIdDelete.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | let onIdInputChange = (setId, e) => setId(ReactEvent.Form.target(e)##value);
4 |
5 | [@react.component]
6 | let make = () => {
7 | let (id, setId) = React.useState(() => "");
8 | ;
23 | };
24 |
--------------------------------------------------------------------------------
/examples/pr/196/client/src/Wallets.re:
--------------------------------------------------------------------------------
1 | module GetWallets = [%graphql
2 | {|
3 | query getWallets {
4 | wallets {
5 | id
6 | name
7 | }
8 | }
9 | |}
10 | ];
11 |
12 | module GetWalletsQuery = ReasonApollo.CreateQuery(GetWallets);
13 |
14 | [@react.component]
15 | let make = () => {
16 |
17 | ...{({result}) =>
18 | switch (result) {
19 | | Loading => {ReasonReact.string("Loading")}
20 | | Error(error) => {ReasonReact.string(error##message)}
21 | | Data(response) =>
22 | Js.log2("Wallets", response);
23 | {ReasonReact.string("Success")}
;
24 | }
25 | }
26 | ;
27 | };
28 |
--------------------------------------------------------------------------------
/examples/pr/196/client/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const outputDir = path.join(__dirname, 'build/');
4 |
5 | const isProd = process.env.NODE_ENV === 'production';
6 |
7 | module.exports = {
8 | entry: './src/Index.bs.js',
9 | mode: isProd ? 'production' : 'development',
10 | output: {
11 | path: outputDir,
12 | filename: 'Index.js'
13 | },
14 | plugins: [
15 | new HtmlWebpackPlugin({
16 | template: 'src/index.html',
17 | inject: false
18 | })
19 | ],
20 | devServer: {
21 | compress: true,
22 | contentBase: outputDir,
23 | port: process.env.PORT || 8000,
24 | historyApiFallback: true
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/examples/swapi/bsconfig.json:
--------------------------------------------------------------------------------
1 | /* This is the BuckleScript configuration file. Note that this is a comment;
2 | BuckleScript comes with a JSON parser that supports comments and trailing
3 | comma. If this screws with your editor highlighting, please tell us by filing
4 | an issue! */
5 | {
6 | "name": "react-template",
7 | "reason": { "react-jsx": 3 },
8 | "sources": ["src"],
9 | "package-specs": [
10 | {
11 | "module": "commonjs",
12 | "in-source": true
13 | }
14 | ],
15 | "suffix": ".bs.js",
16 | "namespace": true,
17 | "bs-dependencies": ["reason-react", "reason-apollo"],
18 | "bsc-flags": [
19 | "-bs-super-errors"
20 | ],
21 | "refmt": 3,
22 | "ppx-flags": ["@baransu/graphql_ppx_re/ppx6"]
23 | }
24 |
--------------------------------------------------------------------------------
/examples/pr/196/client/src/Settings.re:
--------------------------------------------------------------------------------
1 | module GetSettings = [%graphql
2 | {|
3 | query getSettings {
4 | settings {
5 | id
6 | version
7 | wallets {
8 | id
9 | name
10 | }
11 | }
12 | }
13 | |}
14 | ];
15 |
16 | module GetSettingsQuery = ReasonApollo.CreateQuery(GetSettings);
17 |
18 | [@react.component]
19 | let make = () => {
20 |
21 | ...{({result}) =>
22 | switch (result) {
23 | | Loading => {ReasonReact.string("Loading")}
24 | | Error(error) => {ReasonReact.string(error##message)}
25 | | Data(response) =>
26 | Js.log(response);
27 | {ReasonReact.string("Success")}
;
28 | }
29 | }
30 | ;
31 | };
32 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reason-workshop-chat-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "bs-css": "^7.2.0",
7 | "react": "^16.5.2",
8 | "react-dom": "^16.5.2",
9 | "reason-apollo": "../../",
10 | "reason-scripts": "0.9.0"
11 | },
12 | "scripts": {
13 | "start": "bsb -make-world -w",
14 | "webpack": "webpack-dev-server",
15 | "get-schema": "yarn send-introspection-query https://boiling-bastion-96890.herokuapp.com/graphql"
16 | },
17 | "devDependencies": {
18 | "@glennsl/bs-jest": "^0.4.4",
19 | "bs-platform": "^4.0.6",
20 | "graphql_ppx": "^0.2.7",
21 | "reason-react": "^0.5.3",
22 | "webpack": "^4.20.2",
23 | "webpack-cli": "^3.1.2",
24 | "webpack-dev-server": "^3.1.9"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/swapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reason-apollo-test",
3 | "version": "0.1.0",
4 | "scripts": {
5 | "build": "bsb -make-world",
6 | "start": "bsb -make-world -w",
7 | "clean": "bsb -clean-world",
8 | "webpack": "webpack-dev-server",
9 | "format": "refmt",
10 | "get-schema": "yarn send-introspection-query https://api.graph.cool/simple/v1/cjdgba1jw4ggk0185ig4bhpsn"
11 | },
12 | "keywords": [
13 | "BuckleScript"
14 | ],
15 | "author": "",
16 | "license": "MIT",
17 | "dependencies": {
18 | "apollo-utilities": "^1.0.16",
19 | "react": "^16.8.6",
20 | "react-dom": "^16.8.6",
21 | "reason-apollo": "../../",
22 | "reason-react": "^0.7.0"
23 | },
24 | "devDependencies": {
25 | "@baransu/graphql_ppx_re": "^0.7.1",
26 | "bs-platform": "^7.2.2",
27 | "webpack": "^4.6.0",
28 | "webpack-cli": "^3.1.2",
29 | "webpack-dev-server": "^3.1.3"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/pr/196/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-react-app",
3 | "version": "0.1.0",
4 | "scripts": {
5 | "build": "bsb -make-world",
6 | "start": "bsb -make-world -w",
7 | "clean": "bsb -clean-world",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "webpack": "webpack -w",
10 | "webpack:production": "NODE_ENV=production webpack",
11 | "server": "webpack-dev-server"
12 | },
13 | "keywords": [
14 | "BuckleScript"
15 | ],
16 | "author": "",
17 | "license": "MIT",
18 | "dependencies": {
19 | "react": "^16.8.1",
20 | "react-dom": "^16.8.1",
21 | "reason-apollo": "^0.16.1",
22 | "reason-react": ">=0.7.0"
23 | },
24 | "devDependencies": {
25 | "bs-platform": "^7.0.1",
26 | "graphql_ppx": "^0.2.8",
27 | "html-webpack-plugin": "^3.2.0",
28 | "webpack": "^4.0.1",
29 | "webpack-cli": "^3.1.1",
30 | "webpack-dev-server": "^3.1.8"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/NewMessageNotification.re:
--------------------------------------------------------------------------------
1 | module NewNotification = [%graphql {|
2 | subscription messageAdded {
3 | messageAdded {
4 | id
5 | text
6 | author {
7 | id
8 | name
9 | }
10 | }
11 | }
12 | |}];
13 |
14 | module NewNotificationSub = ReasonApollo.CreateSubscription(NewNotification);
15 |
16 |
17 | let component = ReasonReact.statelessComponent("NewMessageNotification");
18 |
19 | let make = _children => {
20 | ...component,
21 | render: _self =>
22 |
23 | ...{
24 | ({result}) => {
25 | switch result {
26 | | Loading =>
27 | | Error(_error) =>
28 | | Data(_response) =>
29 |
30 |
31 |
32 |
33 | }
34 | }
35 | }
36 |
37 | };
38 |
--------------------------------------------------------------------------------
/examples/swapi/src/SubscribeToPersons.re:
--------------------------------------------------------------------------------
1 | module Persons = [%graphql
2 | {|
3 |
4 | subscription {
5 | person: Person {
6 | node {
7 | name
8 | }
9 | }
10 | }
11 | |}
12 | ];
13 |
14 | module PersonsSubscription = ReasonApollo.CreateSubscription(Persons);
15 |
16 | [@react.component]
17 | let make = () => {
18 |
19 |
{"Person Subscription" |> React.string}
20 |
21 | ...{({result}) =>
22 | switch (result) {
23 | | Error(_e) =>
24 | Js.log(_e);
25 | "Something went wrong" |> React.string;
26 | | Loading => "Loading" |> React.string
27 | | Data(response) =>
28 | switch (response##person) {
29 | | Some(person) =>
30 | switch (person##node) {
31 | | Some(node) => node##name |> React.string
32 | | None => "No node found" |> React.string
33 | }
34 | | None => "Persons not found" |> React.string
35 | }
36 | }
37 | }
38 |
39 |
;
40 | };
41 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/ReasonApolloClient.re:
--------------------------------------------------------------------------------
1 | /* Create an InMemoryCache */
2 | let inMemoryCache = ApolloInMemoryCache.createInMemoryCache();
3 |
4 | /* Create an HTTP Link */
5 | let httpLink =
6 | ApolloLinks.createHttpLink(
7 | ~uri="https://boiling-bastion-96890.herokuapp.com/graphql",
8 | (),
9 | );
10 |
11 | /* WebSocket client */
12 | let webSocketLink =
13 | ApolloLinks.webSocketLink(
14 | ~uri="wss://boiling-bastion-96890.herokuapp.com/graphql",
15 | ~reconnect=true,
16 | (),
17 | );
18 |
19 | /* based on test, execute left or right */
20 | let webSocketHttpLink =
21 | ApolloLinks.split(
22 | operation => {
23 | let operationDefinition =
24 | ApolloUtilities.getMainDefinition(operation##query);
25 | operationDefinition##kind == "OperationDefinition"
26 | &&
27 | operationDefinition##operation == "subscription";
28 | },
29 | webSocketLink,
30 | httpLink,
31 | );
32 |
33 | let instance =
34 | ReasonApollo.createApolloClient(
35 | ~link=webSocketHttpLink,
36 | ~cache=inMemoryCache,
37 | (),
38 | );
39 |
--------------------------------------------------------------------------------
/examples/swapi/src/GetPersonById.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | /* alias Person as person because compiler doesn't like uppercase key names */
4 | module GetPerson = [%graphql
5 | {|
6 | query getPerson ($id:ID!){
7 | person:
8 | Person(id:$id) {
9 | id
10 | age
11 | name
12 | }
13 | }
14 | |}
15 | ];
16 |
17 | module GetPersonQuery = ReasonApollo.CreateQuery(GetPerson);
18 |
19 | [@react.component]
20 | let make = (~id) => {
21 | let getPersonQuery = GetPerson.make(~id, ());
22 |
23 | ...{({result}) =>
24 |
25 | {switch (result) {
26 | | Error(e) =>
27 | Js.log(e);
28 | "Something Went Wrong" |> ste;
29 | | Loading => "Loading" |> ste
30 | | Data(response) =>
31 | switch (response##person) {
32 | | None => "No Person Data" |> ste
33 | | Some(person) =>
{person##name |> ste}
34 | }
35 | }}
36 |
37 | }
38 | ;
39 | };
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Meteor Development Group, Inc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/swapi/src/AddPerson.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | module AddPerson = [%graphql
4 | {|
5 |
6 | mutation addPerson($age: Int!, $name: String!) {
7 | createPerson(age: $age, name: $name) {
8 | name
9 | }
10 | }
11 | |}
12 | ];
13 |
14 | module AddPersonMutation = ReasonApollo.CreateMutation(AddPerson);
15 |
16 | [@react.component]
17 | let make = () => {
18 | let addPersonMutation = AddPerson.make(~name="Bob", ~age=24, ());
19 |
20 | ...{(mutation, {result}) =>
21 |
22 |
24 | mutation(
25 | ~variables=addPersonMutation##variables,
26 | ~refetchQueries=[|"getAllPersons"|],
27 | (),
28 | )
29 | |> ignore
30 | }>
31 | {"Add a person" |> ste}
32 |
33 |
34 | {switch (result) {
35 | | NotCalled => "" |> ste
36 | | Data(_) => "Person has been added" |> ste
37 | | Error(_) => "ERROR" |> ste
38 | | Loading => "Loading" |> ste
39 | }}
40 |
41 |
42 | }
43 | ;
44 | };
45 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/README.md:
--------------------------------------------------------------------------------
1 | ## Reason DOJO
2 |
3 | ### Real time chat application with Reason and GraphQL
4 |
5 | This example shows Reason Apollo usage with Queries, Mutations and Subscriptions
6 |
7 | ### Config
8 |
9 | - Your GraphQL endpoint: https://boiling-bastion-96890.herokuapp.com/graphql
10 | - The documentation of the GraphQL endpoint (Note! We didn't wrote any documentation, just a normal GraphQL API):
11 | https://graphqlbin.com/v2/WLPqS6 (We recommend using Chrome)
12 | - Paper, pen, redbull,...
13 |
14 |
15 | ### SETUP
16 |
17 | #### GraphQL Playground
18 | Open the GraphQL playground in your browser https://graphqlbin.com/v2/WLPqS6 (Safari doesn't work)
19 | Add a user, grab it's id, put the id into AddMessage.re to make mutations.
20 | (Don't assume endpoint has existing valid user id hardcoded in src)
21 | `
22 | mutation {
23 | addUser(name:"MyUser") {
24 | id
25 | name
26 | }
27 | }
28 | `
29 |
30 | #### Run the app
31 | `yarn`
32 | `yarn start`
33 | `yarn webpack`
34 |
35 | (note: the send text field seems to be unused and hard coded to send "HI")
36 |
37 | #### Setup GraphQL PPX
38 | Run the introspection query, so the ppx can typecheck based on the graphql_schema :
39 | https://github.com/apollographql/reason-apollo#send-introspection-query
40 |
41 |
42 |
--------------------------------------------------------------------------------
/examples/swapi/src/GetPerson.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | /* alias Person as person because compiler doesn't like uppercase key names */
4 | module GetPerson = [%graphql
5 | {|
6 | query getPerson ($id:ID!){
7 | person:
8 | Person(id:$id) {
9 | id
10 | age
11 | name
12 | }
13 | }
14 | |}
15 | ];
16 |
17 | module GetPersonQuery = ReasonApollo.CreateQuery(GetPerson);
18 |
19 | [@react.component]
20 | let make = () => {
21 | /* pick a valid id from list returned from GetPersons query here
22 | "https://api.graph.cool/simple/v1/cjdgba1jw4ggk0185ig4bhpsn" and pass it to ~id variable
23 | */
24 | let getPersonQuery = GetPerson.make(~id="cjdgbi6d136a90157kpqef72m", ());
25 |
26 | ...{({result}) =>
27 |
28 |
{"Get Person: " |> ste}
29 | {switch (result) {
30 | | Error(e) =>
31 | Js.log(e);
32 | "Something Went Wrong" |> ste;
33 | | Loading => "Loading" |> ste
34 | | Data(response) =>
35 | switch (response##person) {
36 | | None => "No Person Data" |> ste
37 | | Some(person) =>
{person##name |> ste}
38 | }
39 | }}
40 |
41 | }
42 | ;
43 | };
44 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloSubscription.rei:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | module Make:
4 | (Config: ReasonApolloTypes.Config) =>
5 | {
6 | [@bs.module "graphql-tag"] external gql: ReasonApolloTypes.gql = "default";
7 |
8 | let graphQLSubscriptionAST: queryString;
9 |
10 | type response = subscriptionResponse(Config.t);
11 |
12 | type renderPropObj = {
13 | result: response,
14 | data: option(Config.t),
15 | error: option(apolloError),
16 | loading: bool,
17 | };
18 |
19 | type renderPropObjJS = {
20 | loading: bool,
21 | data: Js.Nullable.t(Js.Json.t),
22 | error: Js.Nullable.t(apolloError),
23 | };
24 |
25 | let apolloDataToVariant: renderPropObjJS => response;
26 |
27 | let convertJsInputToReason: renderPropObjJS => renderPropObj;
28 |
29 | module JsSubscription: {
30 | [@bs.module "react-apollo"] [@react.component]
31 | external make:
32 | (
33 | ~subscription: ReasonApolloTypes.queryString,
34 | ~variables: option(Js.Json.t),
35 | ~children: renderPropObjJS => ReasonReact.reactElement
36 | ) =>
37 | ReasonReact.reactElement =
38 | "Subscription";
39 | };
40 |
41 | [@react.component]
42 | let make:
43 | (~variables: Js.Json.t=?, ~children: renderPropObj => React.element) =>
44 | React.element;
45 | };
46 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/AddMessage.re:
--------------------------------------------------------------------------------
1 | module Styles = {
2 | open Css;
3 | let container = style([
4 |
5 | ]);
6 |
7 | let input = style([
8 | width(px(300)),
9 | height(px(22)),
10 | marginLeft(px(32)),
11 | ]);
12 |
13 | let submitBtn = style([
14 | height(px(28)),
15 | ]);
16 | };
17 |
18 | module AddMessage = [%graphql {|
19 | mutation addMessage {
20 | addMessage(userId: "e4315d20-fa78-11e8-877a-8f1cf822dad6", text: "HI") {
21 | id
22 | }
23 | }
24 | |}];
25 |
26 | module AddMessageMutation = ReasonApollo.CreateMutation(AddMessage);
27 |
28 | type state = {
29 | text: string
30 | };
31 |
32 | type action =
33 | | Change(string);
34 |
35 | let component = ReasonReact.reducerComponent("AddMessage");
36 |
37 | let make = _children => {
38 | ...component,
39 | initialState: () => { text: "" },
40 | reducer: (action, _state) => switch action {
41 | | Change(str) => ReasonReact.Update({text: str})
42 | },
43 | render: ({state: {text}, send}) =>
44 |
45 | ...{
46 | (mutation, _result) => {
47 |
48 | send(Change(Handler.onChange(e)))}
52 | />
53 | mutation() |> ignore}
56 | >
57 | ("SEND" |> ReasonReact.string)
58 |
59 |
60 | }
61 | }
62 | ,
63 | };
64 |
--------------------------------------------------------------------------------
/examples/pr/196/server/index.js:
--------------------------------------------------------------------------------
1 | const { ApolloServer, gql } = require('apollo-server');
2 |
3 | // This is a (sample) collection of books we'll be able to query
4 | // the GraphQL server for. A more complete example might fetch
5 | // from an existing data source like a REST API or database.
6 |
7 | const wallets = [{
8 | id: "1",
9 | name: "What"
10 | }, {
11 | id: "2",
12 | name: "Ever"
13 | }]
14 |
15 | const settings = {
16 | id: "1",
17 | version: "v1",
18 | wallets: wallets
19 | }
20 |
21 | // Type definitions define the "shape" of your data and specify
22 | // which ways the data can be fetched from the GraphQL server.
23 | const typeDefs = gql`
24 | type Wallet {
25 | id: ID!
26 | name: String!
27 | }
28 |
29 | type Settings {
30 | id: ID!
31 | version: String!
32 | wallets: [Wallet!]!
33 | }
34 |
35 | type Query {
36 | wallets: [Wallet!]!
37 | settings: Settings!
38 | }
39 | `;
40 |
41 | // Resolvers define the technique for fetching the types in the
42 | // schema. We'll retrieve books from the "books" array above.
43 | const resolvers = {
44 | Query: {
45 | wallets: () => wallets,
46 | settings: () => settings
47 | },
48 | };
49 |
50 | // In the most basic sense, the ApolloServer can be started
51 | // by passing type definitions (typeDefs) and the resolvers
52 | // responsible for fetching the data for those types.
53 | const server = new ApolloServer({ typeDefs, resolvers });
54 |
55 | // This `listen` method launches a web-server. Existing apps
56 | // can utilize middleware options, which we'll discuss later.
57 | server.listen().then(({ url }) => {
58 | console.log(`🚀 Server ready at ${url}`);
59 | });
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reason-apollo",
3 | "version": "0.20.0",
4 | "license": "MIT",
5 | "sideEffects": "false",
6 | "description": "Using Apollo client 2 with Reason",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/apollographql/reason-apollo"
10 | },
11 | "peerDependencies": {},
12 | "keywords": [
13 | "Reason",
14 | "Apollo",
15 | "React",
16 | "GraphQL"
17 | ],
18 | "author": "Grégoire Van der Auwermeulen ",
19 | "devDependencies": {
20 | "@baransu/graphql_ppx_re": "^0.7.1",
21 | "bs-platform": "^7.2.2",
22 | "husky": "^1.2.0",
23 | "lint-staged": "^8.1.0",
24 | "reason-react": "^0.7.0"
25 | },
26 | "dependencies": {
27 | "apollo-cache-inmemory": "^1.6.0",
28 | "apollo-client": "^2.6.3",
29 | "apollo-link": "^1.2.12",
30 | "apollo-link-context": "^1.0.18",
31 | "apollo-link-error": "^1.1.11",
32 | "apollo-link-http": "^1.5.15",
33 | "apollo-link-ws": "^1.0.18",
34 | "apollo-upload-client": "9.1.0",
35 | "apollo-utilities": "^1.3.2",
36 | "graphql": "^14.0.2",
37 | "graphql-tag": "^2.10.0",
38 | "react-apollo": "^2.5.8",
39 | "subscriptions-transport-ws": "^0.9.16"
40 | },
41 | "lint-staged": {
42 | "*.re": [
43 | "bsrefmt --in-place",
44 | "git add"
45 | ]
46 | },
47 | "husky": {
48 | "hooks": {
49 | "pre-commit": "lint-staged"
50 | }
51 | },
52 | "scripts": {
53 | "build": "bsb -make-world",
54 | "start": "bsb -make-world -w",
55 | "clean": "bsb -clean-world",
56 | "lint-staged": "lint-staged",
57 | "test": "echo \"Error: no test specified\" && exit 1"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/examples/swapi/src/Persons.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | module GetAllPersons = [%graphql
4 | {|
5 | query getAllPersons {
6 | allPersons {
7 | id
8 | age
9 | name
10 | }
11 | }
12 | |}
13 | ];
14 |
15 | module GetAllPersonsQuery = ReasonApollo.CreateQuery(GetAllPersons);
16 |
17 | [@react.component]
18 | let make = () =>
19 |
20 | ...{({result, fetchMore}) =>
21 |
22 |
{"Persons: " |> ste}
23 | {switch (result) {
24 | | Error(e) =>
25 | Js.log(e);
26 | "Something Went Wrong" |> ste;
27 | | Loading => "Loading" |> ste
28 | | Data(response) =>
29 |
30 | {response##allPersons
31 | |> Array.mapi((index, person) =>
32 |
string_of_int}>
33 | {person##name |> ste}
34 |
35 |
{"ID: " ++ person##id |> ste}
36 |
37 | )
38 | |> React.array}
39 |
41 | fetchMore(
42 | ~updateQuery=
43 | (prev, _next) =>
44 | /* Update Apollo Store with [@bs.raw {||}] for now, since the type comming in is a generic Js.Json.t for now*/
45 | prev,
46 | (),
47 | )
48 | |> ignore
49 | }>
50 | {"fetchMore" |> ste}
51 |
52 |
53 | }}
54 |
55 | }
56 | ;
57 |
--------------------------------------------------------------------------------
/src/ReasonApollo.re:
--------------------------------------------------------------------------------
1 | open ApolloClient;
2 |
3 | /*
4 | * Expose a createApolloClient function that has to be passed to the ApolloProvider
5 | */
6 | let createApolloClient =
7 | (
8 | ~link,
9 | ~cache,
10 | ~ssrMode=?,
11 | ~ssrForceFetchDelay=?,
12 | ~connectToDevTools=?,
13 | ~queryDeduplication=?,
14 | (),
15 | ) =>
16 | createApolloClientJS({
17 | link,
18 | cache,
19 | ssrMode,
20 | ssrForceFetchDelay,
21 | connectToDevTools,
22 | queryDeduplication,
23 | });
24 | // let createApolloClient =
25 | // (
26 | // ~link,
27 | // ~cache,
28 | // ~ssrMode=?,
29 | // ~ssrForceFetchDelay=?,
30 | // ~connectToDevTools=?,
31 | // ~queryDeduplication=?,
32 | // (),
33 | // ) => {
34 | // createApolloClientJS(
35 | // apolloClientObjectParam(
36 | // ~link,
37 | // ~cache,
38 | // ~ssrMode?,
39 | // ~ssrForceFetchDelay?,
40 | // ~connectToDevTools?,
41 | // ~queryDeduplication?,
42 | // ),
43 | // );
44 | // };
45 |
46 | /*
47 | * Expose a module to perform "query" operations for the given client
48 | */
49 | module CreateQuery = (Config: ReasonApolloTypes.Config) =>
50 | ReasonApolloQuery.Make(Config);
51 |
52 | /*
53 | * Expose a module to perform "mutation" operations for the given client
54 | */
55 | module CreateMutation = (Config: ReasonApolloTypes.Config) =>
56 | ReasonApolloMutation.Make(Config);
57 | /*
58 | * Expose a module to perform "subscription" operations for the given client
59 | */
60 | module CreateSubscription = (Config: ReasonApolloTypes.Config) =>
61 | ReasonApolloSubscription.Make(Config);
62 |
63 | module Provider = ApolloProvider;
64 |
65 | module Consumer = ApolloConsumer;
66 |
--------------------------------------------------------------------------------
/examples/swapi/src/Client.re:
--------------------------------------------------------------------------------
1 | /* open ApolloLinks; */
2 | open ApolloInMemoryCache;
3 |
4 | /* Create an InMemoryCache */
5 | let inMemoryCache = createInMemoryCache();
6 |
7 | /*
8 | OR with dataIdFromObject:
9 |
10 | type dataObject = {
11 | .
12 | "__typename": string,
13 | "id": string
14 | };
15 |
16 | createInMemoryCache(~dataIdFromObject=(obj: dataObject) => obj##id, ());
17 | */
18 |
19 | /* Create a Link that puts an Authorization header in context */
20 | let headerContextLink =
21 | ApolloLinks.createContextLink(() =>
22 | {
23 | "headers": {
24 | "authorization": "Bearer $123",
25 | },
26 | }
27 | );
28 |
29 | /* Create an HTTP Link */
30 | let httpLink =
31 | ApolloLinks.createHttpLink(
32 | ~uri="https://api.graph.cool/simple/v1/cjdgba1jw4ggk0185ig4bhpsn",
33 | (),
34 | );
35 | let webSocketLinkT: ReasonApolloTypes.webSocketLinkT = {
36 | uri: "wss://subscriptions.graph.cool/v1/cjdgba1jw4ggk0185ig4bhpsn",
37 | options: {
38 | reconnect: true,
39 | connectionParams: None,
40 | },
41 | };
42 | /* WebSocket client */
43 | let webSocketLink = ApolloLinks.webSocketLink(webSocketLinkT);
44 |
45 | /* based on test, execute left or right */
46 | let webSocketHttpLink =
47 | ApolloLinks.split(
48 | operation => {
49 | let operationDefinition =
50 | ApolloUtilities.getMainDefinition(operation.query);
51 | Js.log(operationDefinition);
52 | operationDefinition.kind == "OperationDefinition"
53 | && operationDefinition.operation == "subscription";
54 | },
55 | webSocketLink,
56 | httpLink,
57 | );
58 |
59 | let instance =
60 | ReasonApollo.createApolloClient(
61 | ~link=ApolloLinks.from([|headerContextLink, webSocketHttpLink|]),
62 | ~cache=inMemoryCache,
63 | (),
64 | );
65 |
--------------------------------------------------------------------------------
/src/ApolloInMemoryCache.re:
--------------------------------------------------------------------------------
1 | open ReasonApolloTypes;
2 |
3 | /**
4 | * Used on the client to rehydrate the cache using the initial data passed from the server
5 | * - e.g. window.__APOLLO_STATE__
6 | */
7 | type restoreData;
8 |
9 | /**
10 | * Define the data to pass to the restore method that'll be used used to rehydrate client.
11 | * If you don't want to pass any data, simply return `Js_null_undefined.undefined`.
12 | */
13 | type inMemoryCacheRestoreData = Js.Nullable.t(restoreData);
14 |
15 | /**
16 | * CreateInMemoryCache
17 | * https://github.com/apollographql/apollo-client/tree/master/packages/apollo-cache-inmemory
18 | */
19 | /* Bind the InMemoryCache class */
20 | [@bs.module "apollo-cache-inmemory"]
21 | [@bs.new]
22 | external apolloInMemoryCache : 'a => apolloCache = "InMemoryCache";
23 |
24 | /* Bind the restore method */
25 | [@bs.send.pipe : 't]
26 | external restore : inMemoryCacheRestoreData => apolloCache = "restore";
27 |
28 | /* Fragment matcher */
29 | type fragmentMatcher;
30 |
31 | [@bs.module "apollo-cache-inmemory"] [@bs.new]
32 | external introspectionFragmentMatcher : Js.t({..}) => fragmentMatcher =
33 | "IntrospectionFragmentMatcher";
34 |
35 | let createIntrospectionFragmentMatcher = (~data) =>
36 | introspectionFragmentMatcher({"introspectionQueryResultData": data});
37 |
38 | /* Instantiate a new cache object */
39 | [@bs.obj] external
40 | makeApolloInMemoryCacheParams :
41 | (
42 | ~dataIdFromObject: (Js.t({..}) => string)=?,
43 | ~fragmentMatcher: fragmentMatcher=?
44 | ) => _ = "";
45 |
46 | let createInMemoryCache = (~dataIdFromObject=?, ~fragmentMatcher=?, ()) => {
47 | /* Apollo Client, looks for key in Object. Doesn't check if value is null */
48 | apolloInMemoryCache(
49 | makeApolloInMemoryCacheParams(~dataIdFromObject?, ~fragmentMatcher?)
50 | );
51 | };
52 |
--------------------------------------------------------------------------------
/examples/swapi/src/DeletePerson.re:
--------------------------------------------------------------------------------
1 | let ste = React.string;
2 |
3 | module DeletePerson = [%graphql
4 | {|
5 | mutation deletePerson($id: ID!) {
6 | deletePerson(id: $id) {
7 | id
8 | }
9 | }
10 | |}
11 | ];
12 |
13 | module DeletePersonMutation = ReasonApollo.CreateMutation(DeletePerson);
14 |
15 | [@react.component]
16 | let make = () => {
17 | /* pick a valid id from list returned from GetPersons query here
18 | "https://api.graph.cool/simple/v1/cjdgba1jw4ggk0185ig4bhpsn" and pass it to ~id variable
19 | */
20 | let deletePersonMutation =
21 | DeletePerson.make(~id="cjhhv0i51k5lf0160xszwdaps", ());
22 |
23 | ...{(mutation, {result}) =>
24 |
25 |
{"Delete a Person By Id" |> ste}
26 |
27 | {"Pick and Id from above and put it in DeletePerson.re" |> ste}
28 |
29 |
{
31 | mutation(
32 | ~variables=deletePersonMutation##variables,
33 | ~refetchQueries=[|"getAllPersons"|],
34 | (),
35 | )
36 | |> ignore;
37 | Js.log("SEND");
38 | }}>
39 | {"Delete a person" |> ste}
40 |
41 |
42 | {switch (result) {
43 | | NotCalled =>
44 | Js.log("Not called");
45 | "" |> ste;
46 | | Data(d) =>
47 | Js.log2("data", d);
48 | "Person has been deleted" |> ste;
49 | | Error(e) =>
50 | Js.log2("error", e);
51 | "ERROR" |> ste;
52 | | Loading =>
53 | Js.log("Loading");
54 | "Loading" |> ste;
55 | }}
56 |
57 |
58 | }
59 | ;
60 | };
61 |
--------------------------------------------------------------------------------
/examples/swapi/src/DeletePersonButton.re:
--------------------------------------------------------------------------------
1 | let ste = ReasonReact.string;
2 |
3 | module DeletePerson = [%graphql
4 | {|
5 | mutation deletePerson($id: ID!) {
6 | deletePerson(id: $id) {
7 | id
8 | }
9 | }
10 | |}
11 | ];
12 |
13 | module DeletePersonMutation = ReasonApollo.CreateMutation(DeletePerson);
14 |
15 | [@react.component]
16 | let make = (~id) => {
17 | let deletePersonMutation = DeletePerson.make(~id, ());
18 |
19 | ...(
20 | (mutation, {result}) =>
21 |
22 |
25 | mutation(
26 | ~variables=deletePersonMutation##variables,
27 | ~refetchQueries=[|"getAllPersons"|],
28 | (),
29 | )
30 | |> ignore
31 | )>
32 | ("Delete ID" |> ste)
33 |
34 |
35 | (
36 | switch (result) {
37 | | NotCalled =>
38 | Js.log("Not called");
39 | "" |> ste;
40 | | Data(d) =>
41 | Js.log2("data", d);
42 | let person = d##deletePerson;
43 | Js.log2("deleted person", person);
44 | "Person with this ID has been deleted" |> ste;
45 | | Error(e) =>
46 | Js.log2("error", e);
47 | "ERROR" |> ste;
48 | | Loading =>
49 | Js.log("Loading");
50 | "Loading" |> ste;
51 | }
52 | )
53 |
54 |
55 | )
56 | ;
57 | };
58 |
--------------------------------------------------------------------------------
/examples/pr/196/client/README.md:
--------------------------------------------------------------------------------
1 | # my-react-app
2 |
3 | ## Run Project
4 |
5 | ```sh
6 | npm install
7 | npm start
8 | # in another tab
9 | npm run webpack
10 | ```
11 |
12 | After you see the webpack compilation succeed (the `npm run webpack` step), open up `build/index.html` (**no server needed!**). Then modify whichever `.re` file in `src` and refresh the page to see the changes.
13 |
14 | **For more elaborate ReasonReact examples**, please see https://github.com/reasonml-community/reason-react-example
15 |
16 | ## Run Project with Server
17 |
18 | To run with the webpack development server run `npm run server` and view in the browser at http://localhost:8000. Running in this environment provides hot reloading and support for routing; just edit and save the file and the browser will automatically refresh.
19 |
20 | Note that any hot reload on a route will fall back to the root (`/`), so `ReasonReact.Router.dangerouslyGetInitialUrl` will likely be needed alongside the `ReasonReact.Router.watchUrl` logic to handle routing correctly on hot reload refreshes or simply opening the app at a URL that is not the root.
21 |
22 | To use a port other than 8000 set the `PORT` environment variable (`PORT=8080 npm run server`).
23 |
24 | ## Build for Production
25 |
26 | ```sh
27 | npm run clean
28 | npm run build
29 | npm run webpack:production
30 | ```
31 |
32 | This will replace the development artifact `build/Index.js` for an optimized version as well as copy `src/index.html` into `build/`. You can then deploy the contents of the `build` directory (`index.html` and `Index.js`).
33 |
34 | If you make use of routing (via `ReasonReact.Router` or similar logic) ensure that server-side routing handles your routes or that 404's are directed back to `index.html` (which is how the dev server is set up).
35 |
36 | **To enable dead code elimination**, change `bsconfig.json`'s `package-specs` `module` from `"commonjs"` to `"es6"`. Then re-run the above 2 commands. This will allow Webpack to remove unused code.
37 |
--------------------------------------------------------------------------------
/examples/swapi/src/PersonSubscribeToMore.re:
--------------------------------------------------------------------------------
1 | [@bs.module "graphql-tag"] external gql: ReasonApolloTypes.gql = "default";
2 |
3 | let ste = React.string;
4 |
5 | module GetAllPersons = [%graphql
6 | {|
7 | query getAllPersons {
8 | allPersons {
9 | id
10 | age
11 | name
12 | }
13 | }
14 | |}
15 | ];
16 |
17 | module GetAllPersonsQuery = ReasonApollo.CreateQuery(GetAllPersons);
18 |
19 | module NewPerson = [%graphql
20 | {|
21 |
22 | subscription {
23 | person: Person {
24 | node {
25 | name
26 | }
27 | }
28 | }
29 | |}
30 | ];
31 |
32 | let newPerson = NewPerson.make();
33 | let newPersonAST = gql(. newPerson##query);
34 |
35 | [@react.component]
36 | let make = () => {
37 |
38 | ...{({result, subscribeToMore}) =>
39 |
40 |
{"Persons: " |> ste}
41 | {switch (result) {
42 | | Error(_e) => "Something Went Wrong" |> ste
43 | | Loading => "Loading" |> ste
44 | | Data(response) =>
45 | {
48 | let _unsub =
49 | subscribeToMore(
50 | ~document=newPersonAST,
51 | ~updateQuery=[%bs.raw
52 | {|
53 | function(prev, next) {
54 | if(!next.subscriptionData.data || !next.subscriptionData.data.person)
55 | return prev;
56 | return Object.assign({}, prev, {
57 | messages: prev.allPersons.concat(next.subscriptionData.data.person)
58 | });
59 | }
60 | |}
61 | ],
62 | (),
63 | );
64 | ();
65 | }}
66 | />
67 | }}
68 |
69 | }
70 | ;
71 | };
72 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloSubscription.re:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | module Make = (Config: ReasonApolloTypes.Config) => {
4 | [@bs.module "graphql-tag"] external gql: ReasonApolloTypes.gql = "default";
5 |
6 | let graphQLSubscriptionAST = gql(. Config.query);
7 |
8 | type response = subscriptionResponse(Config.t);
9 |
10 | type renderPropObj = {
11 | result: response,
12 | data: option(Config.t),
13 | error: option(apolloError),
14 | loading: bool,
15 | };
16 |
17 | type renderPropObjJS = {
18 | loading: bool,
19 | data: Js.Nullable.t(Js.Json.t),
20 | error: Js.Nullable.t(apolloError),
21 | };
22 |
23 | let apolloDataToVariant = apolloData =>
24 | switch (
25 | apolloData.loading,
26 | apolloData.data |> ReasonApolloUtils.getNonEmptyObj,
27 | apolloData.error |> Js.Nullable.toOption,
28 | ) {
29 | | (true, _, _) => Loading
30 | | (false, Some(response), _) => Data(Config.parse(response))
31 | | (false, _, Some(error)) => Error(error)
32 | | (false, None, None) =>
33 | Error({
34 | message: "No data",
35 | graphQLErrors: Js.Nullable.null,
36 | networkError: Js.Nullable.null,
37 | })
38 | };
39 |
40 | let convertJsInputToReason = apolloData => {
41 | result: apolloData |> apolloDataToVariant,
42 | data:
43 | switch (apolloData.data |> ReasonApolloUtils.getNonEmptyObj) {
44 | | None => None
45 | | Some(data) =>
46 | switch (Config.parse(data)) {
47 | | parsedData => Some(parsedData)
48 | | exception _ => None
49 | }
50 | },
51 | error:
52 | switch (apolloData.error |> Js.Nullable.toOption) {
53 | | Some(error) => Some(error)
54 | | None => None
55 | },
56 | loading: apolloData.loading,
57 | };
58 |
59 | module JsSubscription = {
60 | [@bs.module "react-apollo"] [@react.component]
61 | external make:
62 | (
63 | ~subscription: ReasonApolloTypes.queryString,
64 | ~variables: option(Js.Json.t),
65 | ~children: renderPropObjJS => ReasonReact.reactElement
66 | ) =>
67 | ReasonReact.reactElement =
68 | "Subscription";
69 | };
70 |
71 | [@react.component]
72 | let make = (~variables=?, ~children) =>
73 |
74 | {apolloData => apolloData |> convertJsInputToReason |> children}
75 | ;
76 | };
77 |
--------------------------------------------------------------------------------
/examples/realtime-chat-application/src/MessagesContainer.re:
--------------------------------------------------------------------------------
1 | [@bs.module "graphql-tag"] external gql: ReasonApolloTypes.gql = "default";
2 |
3 | module Styles = {
4 | open Css;
5 | let container = style([
6 | margin(px(20)),
7 | padding(px(5)),
8 | boxShadow(~x=px(2), ~y=px(2), grey)
9 | ]);
10 | };
11 |
12 | module GetAllMessages = [%graphql {|
13 | {
14 | messages {
15 | id
16 | text
17 | author {
18 | id
19 | name
20 | }
21 | }
22 | }
23 | |}];
24 |
25 | module GetAllMessagesQuery = ReasonApollo.CreateQuery(GetAllMessages);
26 |
27 |
28 | module MessageAdded = [%graphql {|
29 | subscription messageAdded {
30 | messageAdded {
31 | id
32 | text
33 | author {
34 | id
35 | name
36 | }
37 | }
38 | }
39 | |}];
40 |
41 | let messageAdded = MessageAdded.make();
42 | let messageAddedASTQuery = gql(. messageAdded##query);
43 |
44 | let component = ReasonReact.statelessComponent("Messages");
45 |
46 | let make = _children => {
47 | ...component,
48 | render: _self =>
49 |
50 | ...{
51 | ({result, subscribeToMore}) => switch result {
52 | | Loading => {"Loading" |> ReasonReact.string}
53 | | Error(_e) => {"Error" |> ReasonReact.string}
54 | | Data(response) =>
55 | {
58 | let _unsub = subscribeToMore(
59 | ~document=messageAddedASTQuery,
60 | ~updateQuery={(prev, next) => {
61 | let addNewMessageJS = [%bs.raw {|
62 | function(prev, next) {
63 | if(!next.subscriptionData.data || !next.subscriptionData.data.messageAdded)
64 | return prev;
65 | return Object.assign({}, prev, {
66 | messages: prev.messages.concat(next.subscriptionData.data.messageAdded)
67 | });
68 | }
69 | |}];
70 | addNewMessageJS(prev, next);
71 | }},
72 | ()
73 | )
74 | }
75 | }
76 | messages=(response##messages)
77 | />
78 | }
79 | }
80 |
81 |
82 | };
--------------------------------------------------------------------------------
/src/ReasonApolloTypes.re:
--------------------------------------------------------------------------------
1 | /**
2 | * An abstract type to describe a query string object.
3 | */
4 | type queryString;
5 |
6 | /**
7 | * The signature of the `graphql-tag/gql` function that transforms a GraphQL
8 | * query string to the standard GraphQL AST.
9 | * https://github.com/apollographql/graphql-tag
10 | */
11 | type gql = (. string) => queryString;
12 |
13 | /**
14 | * An abstract type to describe an Apollo Link object.
15 | */
16 | type apolloLink;
17 |
18 | /**
19 | * An abstract type to describe an Apollo Cache object.
20 | */
21 | type apolloCache;
22 |
23 | type networkError = {statusCode: int};
24 |
25 | type apolloErrorExtensions = {code: Js.Nullable.t(string)};
26 |
27 | type graphqlError = {
28 | message: string,
29 | name: Js.Nullable.t(string),
30 | extensions: Js.Nullable.t(apolloErrorExtensions),
31 | locations: Js.Nullable.t(array(string)),
32 | path: Js.Nullable.t(array(string)),
33 | nodes: Js.Nullable.t(array(string)),
34 | };
35 |
36 | type executionResult = {
37 | errors: Js.Nullable.t(Js.Array.t(graphqlError)),
38 | data: Js.Nullable.t(Js.Json.t),
39 | };
40 |
41 | /* TODO define all types */
42 | type operation = {query: queryString};
43 |
44 | /* TODO define subscription */
45 | type subscription;
46 |
47 | type errorResponse = {
48 | graphQLErrors: Js.Nullable.t(Js.Array.t(graphqlError)),
49 | networkError: Js.Nullable.t(networkError),
50 | response: Js.Nullable.t(executionResult),
51 | operation,
52 | forward: operation => subscription,
53 | };
54 |
55 | module type Config = {
56 | let query: string;
57 | type t;
58 | let parse: Js.Json.t => t;
59 | };
60 |
61 | type apolloError = {
62 | message: string,
63 | graphQLErrors: Js.Nullable.t(array(graphqlError)),
64 | networkError: Js.Nullable.t(string),
65 | };
66 |
67 | type apolloOptions = {
68 | query: queryString,
69 | variables: Js.Json.t,
70 | };
71 |
72 | type queryResponse('a) =
73 | | Loading
74 | | Error(apolloError)
75 | | Data('a);
76 |
77 | type mutationResponse('a) =
78 | | Loading
79 | | Error(apolloError)
80 | | Data('a)
81 | | NotCalled;
82 |
83 | type subscriptionResponse('a) =
84 | | Loading
85 | | Error(apolloError)
86 | | Data('a);
87 |
88 | type executionResponse('a) =
89 | | Errors(array(graphqlError))
90 | | EmptyResponse
91 | | Data('a);
92 | /*
93 | apollo link ws
94 | */
95 |
96 | type webSocketLinkOptionsT = {
97 | reconnect: bool,
98 | connectionParams: option(Js.Json.t),
99 | };
100 |
101 | type webSocketLinkT = {
102 | uri: string,
103 | options: webSocketLinkOptionsT,
104 | };
105 |
106 | type documentNodeT;
107 |
108 | type splitTest = {query: documentNodeT};
109 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloMutation.rei:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | type renderPropObjJS = {
4 | loading: bool,
5 | called: bool,
6 | data: Js.Nullable.t(Js.Json.t),
7 | error: Js.Nullable.t(apolloError),
8 | networkStatus: Js.Nullable.t(int),
9 | variables: Js.Null_undefined.t(Js.Json.t),
10 | };
11 |
12 | module Make:
13 | (Config: Config) =>
14 | {
15 | external cast:
16 | string =>
17 | {
18 | .
19 | "data": Js.Json.t,
20 | "loading": bool,
21 | } =
22 | "%identity";
23 |
24 | [@bs.module "graphql-tag"] external gql: gql = "default";
25 |
26 | let graphqlMutationAST: queryString;
27 | type response = mutationResponse(Config.t);
28 | type renderPropObj = {
29 | result: response,
30 | data: option(Config.t),
31 | loading: bool,
32 | error: option(apolloError),
33 | networkStatus: option(int),
34 | };
35 | type apolloMutation =
36 | (
37 | ~variables: Js.Json.t=?,
38 | ~refetchQueries: array(string)=?,
39 | ~optimisticResponse: Config.t=?,
40 | unit
41 | ) =>
42 | Js.Promise.t(executionResponse(Config.t));
43 |
44 | type jsMutationParams = {
45 | variables: option(Js.Json.t),
46 | refetchQueries: option(array(string)),
47 | optimisticResponse: option(Config.t),
48 | };
49 |
50 | let convertExecutionResultToReason:
51 | executionResult => executionResponse(Config.t);
52 |
53 | let apolloMutationFactory:
54 | (
55 | ~jsMutation: jsMutationParams => Js.Promise.t(executionResult),
56 | ~variables: Js.Json.t=?,
57 | ~refetchQueries: array(string)=?,
58 | ~optimisticResponse: Config.t=?,
59 | unit
60 | ) =>
61 | Js.Promise.t(executionResponse(Config.t));
62 |
63 | let apolloDataToReason: renderPropObjJS => response;
64 |
65 | let convertJsInputToReason: renderPropObjJS => renderPropObj;
66 |
67 | module JsMutation: {
68 | [@bs.module "react-apollo"] [@react.component]
69 | external make:
70 | (
71 | ~mutation: queryString,
72 | ~variables: Js.Json.t=?,
73 | ~onCompleted: unit => unit=?,
74 | ~onError: apolloError => unit=?,
75 | ~children: (
76 | jsMutationParams => Js.Promise.t(executionResult),
77 | renderPropObjJS
78 | ) =>
79 | React.element
80 | ) =>
81 | React.element =
82 | "Mutation";
83 | };
84 |
85 | [@react.component]
86 | let make:
87 | (
88 | ~variables: Js.Json.t=?,
89 | ~onError: apolloError => unit=?,
90 | ~onCompleted: unit => unit=?,
91 | ~children: (apolloMutation, renderPropObj) => React.element
92 | ) =>
93 | React.element;
94 | };
95 |
--------------------------------------------------------------------------------
/src/ApolloLinks.re:
--------------------------------------------------------------------------------
1 | open ReasonApolloTypes;
2 |
3 | /* Bind the method `from`, used to compose links together */
4 | [@bs.module "apollo-link"]
5 | external from: array(apolloLink) => apolloLink = "from";
6 |
7 | /* Bind the method split. Based on a test send left or right */
8 | [@bs.module "apollo-link"]
9 | external split: (splitTest => bool, apolloLink, apolloLink) => apolloLink =
10 | "split";
11 |
12 | /* Bind the HttpLink class */
13 | [@bs.module "apollo-link-http"] [@bs.new]
14 | external createHttpLink: ApolloClient.linkOptions => apolloLink = "HttpLink";
15 |
16 | /* Bind the setContext method */
17 | [@bs.module "apollo-link-context"]
18 | external apolloLinkSetContext: (unit => Js.t({..})) => apolloLink =
19 | "setContext";
20 |
21 | /* Bind the onError method */
22 | [@bs.module "apollo-link-error"]
23 | external apolloLinkOnError: (errorResponse => unit) => apolloLink = "onError";
24 |
25 | /* bind apollo-link-ws */
26 | [@bs.module "apollo-link-ws"] [@bs.new]
27 | external webSocketLink: webSocketLinkT => apolloLink = "WebSocketLink";
28 |
29 | /* Bind createUploadLink function from apollo upload link */
30 | [@bs.module "apollo-upload-client"]
31 | external createUploadLink: ApolloClient.uploadLinkOptions => apolloLink =
32 | "createUploadLink";
33 |
34 | // let webSocketLink = (~uri, ~reconnect=?, ~connectionParams=?, ()) => {
35 | // uri,
36 | // options: {
37 | // reconnect,
38 | // connectionParams,
39 | // },
40 | // };
41 |
42 | /**
43 | * CreateHttpLink
44 | * https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-http
45 | */
46 | let createHttpLink =
47 | (
48 | ~uri,
49 | ~includeExtensions=?,
50 | ~fetch=?,
51 | ~headers=?,
52 | ~credentials=?,
53 | ~fetchOptions=?,
54 | (),
55 | ) => {
56 | createHttpLink({
57 | uri,
58 | includeExtensions: Js.Nullable.fromOption(includeExtensions),
59 | fetch: Js.Nullable.fromOption(fetch),
60 | headers: Js.Nullable.fromOption(headers),
61 | credentials: Js.Nullable.fromOption(credentials),
62 | fetchOptions: Js.Nullable.fromOption(fetchOptions),
63 | });
64 | };
65 |
66 | /**
67 | * CreateUploadLink
68 | * https://github.com/jaydenseric/apollo-upload-client#function-createuploadlink
69 | */
70 | let createUploadLink =
71 | (
72 | ~uri=?,
73 | ~fetch=?,
74 | ~fetchOptions=?,
75 | ~credentials=?,
76 | ~headers=?,
77 | ~includeExtensions=?,
78 | (),
79 | ) =>
80 | createUploadLink(
81 | Js.Nullable.{
82 | uri: fromOption(uri),
83 | fetch: fromOption(fetch),
84 | fetchOptions: fromOption(fetchOptions),
85 | credentials: fromOption(credentials),
86 | headers: fromOption(headers),
87 | includeExtensions: fromOption(includeExtensions),
88 | },
89 | );
90 |
91 | /**
92 | * CreateContextLink
93 | * https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-context
94 | */
95 | let createContextLink = contextHandler => {
96 | /* Instanciate a new context link object */
97 | apolloLinkSetContext(
98 | contextHandler,
99 | );
100 | };
101 |
102 | /**
103 | * CreateErrorLink
104 | * https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-error
105 | */
106 | let createErrorLink = errorHandler => {
107 | /* Instanciate a new error link object */
108 | apolloLinkOnError(errorHandler);
109 | };
110 |
--------------------------------------------------------------------------------
/src/ApolloClient.re:
--------------------------------------------------------------------------------
1 | open ReasonApolloTypes;
2 |
3 | type queryObj = {
4 | query: ReasonApolloTypes.queryString,
5 | variables: Js.Json.t,
6 | };
7 |
8 | type mutationObj = {
9 | mutation: ReasonApolloTypes.queryString,
10 | variables: Js.Json.t,
11 | };
12 |
13 | type generatedApolloClient = {
14 | query:
15 | [@bs.meth] (queryObj => Js.Promise.t(ReasonApolloQuery.renderPropObjJS)),
16 | mutate:
17 | [@bs.meth] (
18 | mutationObj => Js.Promise.t(ReasonApolloMutation.renderPropObjJS)
19 | ),
20 | resetStore: [@bs.meth] (unit => Js.Promise.t(unit)),
21 | };
22 |
23 | type fetch;
24 |
25 | type linkOptions = {
26 | uri: string,
27 | includeExtensions: Js.Nullable.t(bool),
28 | fetch: Js.Nullable.t(fetch),
29 | headers: Js.Nullable.t(Js.Json.t),
30 | credentials: Js.Nullable.t(string),
31 | fetchOptions: Js.Nullable.t(Js.Json.t),
32 | };
33 |
34 | type uploadLinkOptions = {
35 | uri: Js.Nullable.t(string),
36 | fetch: Js.Nullable.t(fetch),
37 | fetchOptions: Js.Nullable.t(Js.t({.})),
38 | credentials: Js.Nullable.t(string),
39 | headers: Js.Nullable.t(Js.Json.t),
40 | includeExtensions: Js.Nullable.t(bool),
41 | };
42 |
43 | type apolloClientObjectParam = {
44 | link: apolloLink,
45 | cache: apolloCache,
46 | ssrMode: option(bool),
47 | ssrForceFetchDelay: option(int),
48 | connectToDevTools: option(bool),
49 | queryDeduplication: option(bool),
50 | };
51 | [@bs.module "apollo-client"] [@bs.new]
52 | external createApolloClientJS: apolloClientObjectParam => generatedApolloClient =
53 | "ApolloClient";
54 |
55 | [@bs.module "graphql-tag"] external gql: ReasonApolloTypes.gql = "default";
56 |
57 | // [@bs.obj]
58 | // external apolloClientObjectParam:
59 | // (
60 | // ~link: apolloLink,
61 | // ~cache: apolloCache,
62 | // ~ssrMode: bool=?,
63 | // ~ssrForceFetchDelay: int=?,
64 | // ~connectToDevTools: bool=?,
65 | // ~queryDeduplication: bool=?
66 | // ) =>
67 | // _ =
68 | // "";
69 | // type apolloClientObjectParam = {
70 | // link: apolloLink,
71 | // cache: apolloCache,
72 | // ssrMode: option(bool),
73 | // ssrForceFetchDelay: option(int),
74 | // connectToDevTools: option(bool),
75 | // queryDeduplication: option(bool),
76 | // };
77 | module ReadQuery = (Config: ReasonApolloTypes.Config) => {
78 | type readQueryOptions = {
79 | query: ReasonApolloTypes.queryString,
80 | variables: Js.Nullable.t(Js.Json.t),
81 | };
82 | type response = option(Config.t);
83 | [@bs.send]
84 | external readQuery:
85 | (generatedApolloClient, readQueryOptions) => Js.Nullable.t(Js.Json.t) =
86 | "readQuery";
87 |
88 | let graphqlQueryAST = gql(. Config.query);
89 | let apolloDataToRecord: Js.Nullable.t(Js.Json.t) => response =
90 | apolloData =>
91 | Js.Nullable.toOption(apolloData)->(Belt.Option.map(Config.parse));
92 |
93 | let make = (~client, ~variables: option(Js.Json.t)=?, ()) =>
94 | readQuery(
95 | client,
96 | {query: graphqlQueryAST, variables: Js.Nullable.fromOption(variables)},
97 | )
98 | ->apolloDataToRecord;
99 | };
100 |
101 | module WriteQuery = (Config: ReasonApolloTypes.Config) => {
102 | type writeQueryOptions = {
103 | query: ReasonApolloTypes.queryString,
104 | variables: Js.Nullable.t(Js.Json.t),
105 | data: Config.t,
106 | };
107 | [@bs.send]
108 | external writeQuery: (generatedApolloClient, writeQueryOptions) => unit =
109 | "writeQuery";
110 |
111 | let graphqlQueryAST = gql(. Config.query);
112 |
113 | let make = (~client, ~variables: option(Js.Json.t)=?, ~data: Config.t, ()) =>
114 | writeQuery(
115 | client,
116 | {
117 | query: graphqlQueryAST,
118 | variables: Js.Nullable.fromOption(variables),
119 | data,
120 | },
121 | );
122 | };
123 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloQuery.rei:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | type updateQueryOptions = {
4 | fetchMoreResult: option(Js.Json.t),
5 | variables: option(Js.Json.t),
6 | };
7 |
8 | type onErrorT;
9 | type updateQueryT = (Js.Json.t, updateQueryOptions) => Js.Json.t;
10 | type updateSubscriptionOptions = {
11 | subscriptionData: option(Js.Json.t),
12 | variables: option(Js.Json.t),
13 | };
14 | type updateQuerySubscriptionT =
15 | (Js.Json.t, updateSubscriptionOptions) => Js.Json.t;
16 |
17 | type subscribeToMoreOptions = {
18 | document: queryString,
19 | variables: option(Js.Json.t),
20 | updateQuery: option(updateQuerySubscriptionT),
21 | onError: option(onErrorT),
22 | };
23 |
24 | /* We don't accept a new query for now */
25 |
26 | type fetchMoreOptions = {
27 | variables: option(Js.Json.t),
28 | updateQuery: updateQueryT,
29 | };
30 |
31 | type renderPropObjJS = {
32 | loading: bool,
33 | data: Js.Nullable.t(Js.Json.t),
34 | error: Js.Nullable.t(apolloError),
35 | refetch: Js.Nullable.t(Js.Json.t) => Js.Promise.t(renderPropObjJS),
36 | networkStatus: Js.Nullable.t(int),
37 | variables: Js.Nullable.t(Js.Json.t),
38 | fetchMore: fetchMoreOptions => Js.Promise.t(unit),
39 | subscribeToMore: subscribeToMoreOptions => unit,
40 | };
41 |
42 | module Make:
43 | (Config: Config) =>
44 | {
45 | [@bs.module "graphql-tag"] external gql: gql = "default";
46 |
47 | type response = queryResponse(Config.t);
48 |
49 | type renderPropObj = {
50 | result: response,
51 | data: option(Config.t),
52 | error: option(apolloError),
53 | loading: bool,
54 | refetch: option(Js.Json.t) => Js.Promise.t(response),
55 | fetchMore:
56 | (~variables: option(Js.Json.t), ~updateQuery: updateQueryT, unit) =>
57 | Js.Promise.t(unit),
58 | networkStatus: option(int),
59 | subscribeToMore:
60 | (
61 | ~document: queryString,
62 | ~variables: Js.Json.t=?,
63 | ~updateQuery: updateQuerySubscriptionT=?,
64 | ~onError: onErrorT=?,
65 | unit
66 | ) =>
67 | unit,
68 | };
69 |
70 | let graphqlQueryAST: queryString;
71 | let apolloDataToVariant: renderPropObjJS => response;
72 |
73 | let convertJsInputToReason: renderPropObjJS => renderPropObj;
74 |
75 | module JsQuery: {
76 | [@bs.module "react-apollo"] [@react.component]
77 | external make:
78 | (
79 | ~query: queryString,
80 | ~variables: Js.Json.t=?,
81 | ~pollInterval: int=?,
82 | ~notifyOnNetworkStatusChange: bool=?,
83 | ~fetchPolicy: string=?,
84 | ~errorPolicy: string=?,
85 | ~ssr: bool=?,
86 | ~displayName: string=?,
87 | ~skip: bool=?,
88 | ~onCompleted: Js.Nullable.t(Js.Json.t) => unit=?,
89 | ~onError: apolloError => unit=?,
90 | ~partialRefetch: bool=?,
91 | ~delay: bool=?,
92 | ~context: Js.Json.t=?,
93 | ~children: renderPropObjJS => React.element
94 | ) =>
95 | React.element =
96 | "Query";
97 | };
98 |
99 | [@react.component]
100 | let make:
101 | (
102 | ~variables: Js.Json.t=?,
103 | ~pollInterval: int=?,
104 | ~notifyOnNetworkStatusChange: bool=?,
105 | ~fetchPolicy: string=?,
106 | ~errorPolicy: string=?,
107 | ~ssr: bool=?,
108 | ~displayName: string=?,
109 | ~skip: bool=?,
110 | ~onCompleted: Js.Nullable.t(Js.Json.t) => unit=?,
111 | ~onError: apolloError => unit=?,
112 | ~partialRefetch: bool=?,
113 | ~delay: bool=?,
114 | ~context: Js.Json.t=?,
115 | ~children: renderPropObj => React.element
116 | ) =>
117 | React.element;
118 | };
119 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloMutation.re:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | type renderPropObjJS = {
4 | loading: bool,
5 | called: bool,
6 | data: Js.Nullable.t(Js.Json.t),
7 | error: Js.Nullable.t(apolloError),
8 | networkStatus: Js.Nullable.t(int),
9 | variables: Js.Null_undefined.t(Js.Json.t),
10 | };
11 |
12 | module Make = (Config: Config) => {
13 | external cast:
14 | string =>
15 | {
16 | .
17 | "data": Js.Json.t,
18 | "loading": bool,
19 | } =
20 | "%identity";
21 |
22 | [@bs.module "graphql-tag"] external gql: gql = "default";
23 |
24 | let graphqlMutationAST = gql(. Config.query);
25 | type response = mutationResponse(Config.t);
26 | type renderPropObj = {
27 | result: response,
28 | data: option(Config.t),
29 | loading: bool,
30 | error: option(apolloError),
31 | networkStatus: option(int),
32 | };
33 | type apolloMutation =
34 | (
35 | ~variables: Js.Json.t=?,
36 | ~refetchQueries: array(string)=?,
37 | ~optimisticResponse: Config.t=?,
38 | unit
39 | ) =>
40 | Js.Promise.t(executionResponse(Config.t));
41 |
42 | type jsMutationParams = {
43 | variables: option(Js.Json.t),
44 | refetchQueries: option(array(string)),
45 | optimisticResponse: option(Config.t),
46 | };
47 |
48 | let convertExecutionResultToReason = (executionResult: executionResult) =>
49 | switch (
50 | executionResult.data |> ReasonApolloUtils.getNonEmptyObj,
51 | executionResult.errors |> Js.Nullable.toOption,
52 | ) {
53 | | (Some(data), _) => Data(Config.parse(data))
54 | | (_, Some(errors)) => Errors(errors)
55 | | (None, None) => EmptyResponse
56 | };
57 |
58 | let apolloMutationFactory =
59 | (
60 | ~jsMutation,
61 | ~variables=?,
62 | ~refetchQueries=?,
63 | ~optimisticResponse=?,
64 | (),
65 | ) =>
66 | jsMutation({variables, refetchQueries, optimisticResponse})
67 | // jsMutation(
68 | // jsMutationParams(
69 | // ~variables?,
70 | // ~refetchQueries?,
71 | // ~optimisticResponse?,
72 | // (),
73 | // ),
74 | // )
75 | |> Js.Promise.(
76 | then_(response => resolve(convertExecutionResultToReason(response)))
77 | );
78 |
79 | let apolloDataToReason: renderPropObjJS => response =
80 | apolloData =>
81 | switch (
82 | apolloData.loading,
83 | apolloData.data |> ReasonApolloUtils.getNonEmptyObj,
84 | apolloData.error |> Js.Nullable.toOption,
85 | ) {
86 | | (true, _, _) => Loading
87 | | (false, Some(data), _) => Data(Config.parse(data))
88 | | (false, _, Some(error)) => Error(error)
89 | | (false, None, None) => NotCalled
90 | };
91 |
92 | let convertJsInputToReason = (apolloData: renderPropObjJS) => {
93 | result: apolloDataToReason(apolloData),
94 | data:
95 | switch (apolloData.data |> ReasonApolloUtils.getNonEmptyObj) {
96 | | None => None
97 | | Some(data) =>
98 | switch (Config.parse(data)) {
99 | | parsedData => Some(parsedData)
100 | | exception _ => None
101 | }
102 | },
103 | error: apolloData.error |> Js.Nullable.toOption,
104 | loading: apolloData.loading,
105 | networkStatus: apolloData.networkStatus->Js.Nullable.toOption,
106 | };
107 |
108 | module JsMutation = {
109 | [@bs.module "react-apollo"] [@react.component]
110 | external make:
111 | (
112 | ~mutation: queryString,
113 | ~variables: Js.Json.t=?,
114 | ~onCompleted: unit => unit=?,
115 | ~onError: apolloError => unit=?,
116 | ~children: (
117 | jsMutationParams => Js.Promise.t(executionResult),
118 | renderPropObjJS
119 | ) =>
120 | React.element
121 | ) =>
122 | React.element =
123 | "Mutation";
124 | };
125 |
126 | [@react.component]
127 | let make = (~variables=?, ~onError=?, ~onCompleted=?, ~children) =>
128 |
129 | {(mutation, apolloData) =>
130 | children(
131 | apolloMutationFactory(~jsMutation=mutation),
132 | apolloData |> convertJsInputToReason,
133 | )}
134 | ;
135 | };
136 |
--------------------------------------------------------------------------------
/src/graphql-types/ReasonApolloQuery.re:
--------------------------------------------------------------------------------
1 | open! ReasonApolloTypes;
2 |
3 | type updateQueryOptions = {
4 | fetchMoreResult: option(Js.Json.t),
5 | variables: option(Js.Json.t),
6 | };
7 |
8 | type onErrorT;
9 | type updateQueryT = (Js.Json.t, updateQueryOptions) => Js.Json.t;
10 | type updateSubscriptionOptions = {
11 | subscriptionData: option(Js.Json.t),
12 | variables: option(Js.Json.t),
13 | };
14 | type updateQuerySubscriptionT =
15 | (Js.Json.t, updateSubscriptionOptions) => Js.Json.t;
16 |
17 | type subscribeToMoreOptions = {
18 | document: queryString,
19 | variables: option(Js.Json.t),
20 | updateQuery: option(updateQuerySubscriptionT),
21 | onError: option(onErrorT),
22 | };
23 |
24 | type fetchMoreOptions = {
25 | variables: option(Js.Json.t),
26 | updateQuery: updateQueryT,
27 | };
28 |
29 | type renderPropObjJS = {
30 | loading: bool,
31 | data: Js.Nullable.t(Js.Json.t),
32 | error: Js.Nullable.t(apolloError),
33 | refetch: Js.Nullable.t(Js.Json.t) => Js.Promise.t(renderPropObjJS),
34 | networkStatus: Js.Nullable.t(int),
35 | variables: Js.Nullable.t(Js.Json.t),
36 | fetchMore: fetchMoreOptions => Js.Promise.t(unit),
37 | subscribeToMore: subscribeToMoreOptions => unit,
38 | };
39 |
40 | module Make = (Config: Config) => {
41 | [@bs.module "graphql-tag"] external gql: gql = "default";
42 |
43 | type response = queryResponse(Config.t);
44 |
45 | type renderPropObj = {
46 | result: response,
47 | data: option(Config.t),
48 | error: option(apolloError),
49 | loading: bool,
50 | refetch: option(Js.Json.t) => Js.Promise.t(response),
51 | fetchMore:
52 | (~variables: option(Js.Json.t), ~updateQuery: updateQueryT, unit) =>
53 | Js.Promise.t(unit),
54 | networkStatus: option(int),
55 | subscribeToMore:
56 | (
57 | ~document: queryString,
58 | ~variables: Js.Json.t=?,
59 | ~updateQuery: updateQuerySubscriptionT=?,
60 | ~onError: onErrorT=?,
61 | unit
62 | ) =>
63 | unit,
64 | };
65 |
66 | let graphqlQueryAST = gql(. Config.query);
67 | let apolloDataToVariant = (apolloData: renderPropObjJS): response =>
68 | switch (
69 | apolloData.loading,
70 | apolloData.data |> ReasonApolloUtils.getNonEmptyObj,
71 | apolloData.error |> Js.Nullable.toOption,
72 | ) {
73 | | (true, _, _) => Loading
74 | | (false, Some(response), _) => Data(Config.parse(response))
75 | | (false, _, Some(error)) => Error(error)
76 | | (false, None, None) =>
77 | Error({
78 | message: "No data",
79 | graphQLErrors: Js.Nullable.null,
80 | networkError: Js.Nullable.null,
81 | })
82 | };
83 |
84 | let convertJsInputToReason = (apolloData: renderPropObjJS) => {
85 | result: apolloData |> apolloDataToVariant,
86 | data:
87 | switch (apolloData.data |> ReasonApolloUtils.getNonEmptyObj) {
88 | | None => None
89 | | Some(data) =>
90 | switch (Config.parse(data)) {
91 | | parsedData => Some(parsedData)
92 | | exception _ => None
93 | }
94 | },
95 | error:
96 | switch (apolloData.error |> Js.Nullable.toOption) {
97 | | Some(error) => Some(error)
98 | | None => None
99 | },
100 | loading: apolloData.loading,
101 | refetch: variables =>
102 | apolloData.refetch(variables |> Js.Nullable.fromOption)
103 | |> Js.Promise.then_(data =>
104 | data |> apolloDataToVariant |> Js.Promise.resolve
105 | ),
106 | fetchMore: (~variables, ~updateQuery, ()) =>
107 | apolloData.fetchMore({variables, updateQuery}),
108 | networkStatus: apolloData.networkStatus->Js.Nullable.toOption,
109 | subscribeToMore:
110 | (~document, ~variables=?, ~updateQuery=?, ~onError=?, ()) => {
111 | apolloData.subscribeToMore({document, variables, updateQuery, onError});
112 | },
113 | };
114 |
115 | module JsQuery = {
116 | [@bs.module "react-apollo"] [@react.component]
117 | external make:
118 | (
119 | ~query: queryString,
120 | ~variables: Js.Json.t=?,
121 | ~pollInterval: int=?,
122 | ~notifyOnNetworkStatusChange: bool=?,
123 | ~fetchPolicy: string=?,
124 | ~errorPolicy: string=?,
125 | ~ssr: bool=?,
126 | ~displayName: string=?,
127 | ~skip: bool=?,
128 | ~onCompleted: Js.Nullable.t(Js.Json.t) => unit=?,
129 | ~onError: apolloError => unit=?,
130 | ~partialRefetch: bool=?,
131 | ~delay: bool=?,
132 | ~context: Js.Json.t=?,
133 | ~children: renderPropObjJS => React.element
134 | ) =>
135 | React.element =
136 | "Query";
137 | };
138 |
139 | [@react.component]
140 | let make =
141 | (
142 | ~variables=?,
143 | ~pollInterval=?,
144 | ~notifyOnNetworkStatusChange=?,
145 | ~fetchPolicy=?,
146 | ~errorPolicy=?,
147 | ~ssr=?,
148 | ~displayName=?,
149 | ~skip=?,
150 | ~onCompleted=?,
151 | ~onError=?,
152 | ~partialRefetch=?,
153 | ~delay=?,
154 | ~context=?,
155 | ~children,
156 | ) =>
157 |
172 | {apolloData => apolloData |> convertJsInputToReason |> children}
173 | ;
174 | };
175 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Apollo Contributor Guide
2 |
3 | Excited about Apollo and want to make it better? We’re excited too!
4 |
5 | Apollo is a community of developers just like you, striving to create the best tools and libraries around GraphQL. We welcome anyone who wants to contribute or provide constructive feedback, no matter the age or level of experience. If you want to help but don't know where to start, let us know, and we'll find something for you.
6 |
7 | Oh, and if you haven't already, sign up for the [Apollo Slack](http://www.apollodata.com/#slack).
8 |
9 | Here are some ways to contribute to the project, from easiest to most difficult:
10 |
11 | * [Reporting bugs](#reporting-bugs)
12 | * [Improving the documentation](#improving-the-documentation)
13 | * [Responding to issues](#responding-to-issues)
14 | * [Small bug fixes](#small-bug-fixes)
15 | * [Suggesting features](#suggesting-features)
16 | * [Big pull requests](#big-prs)
17 |
18 | ## Issues
19 |
20 | ### Reporting bugs
21 |
22 | If you encounter a bug, please file an issue on GitHub via the repository of the sub-project you think contains the bug. If an issue you have is already reported, please add additional information or add a 👍 reaction to indicate your agreement.
23 |
24 | While we will try to be as helpful as we can on any issue reported, please include the following to maximize the chances of a quick fix:
25 |
26 | 1. **Intended outcome:** What you were trying to accomplish when the bug occurred, and as much code as possible related to the source of the problem.
27 | 2. **Actual outcome:** A description of what actually happened, including a screenshot or copy-paste of any related error messages, logs, or other output that might be related. Places to look for information include your browser console, server console, and network logs. Please avoid non-specific phrases like “didn’t work” or “broke”.
28 | 3. **How to reproduce the issue:** Instructions for how the issue can be reproduced by a maintainer or contributor. Be as specific as possible, and only mention what is necessary to reproduce the bug. If possible, try to isolate the exact circumstances in which the bug occurs and avoid speculation over what the cause might be.
29 |
30 | Creating a good reproduction really helps contributors investigate and resolve your issue quickly. In many cases, the act of creating a minimal reproduction illuminates that the source of the bug was somewhere outside the library in question, saving time and effort for everyone.
31 |
32 | Include in the issue a link to your reproduction—a couple good options are a small Github repo or a [CodeSandbox](https://codesandbox.io/). Here's a starter CodeSandbox you can use: https://codesandbox.io/s/yrwE7pvJ7
33 |
34 | If you have a more complicated issue where it is helpful to run it locally, you may consider using [react-apollo-error-template](https://github.com/apollographql/react-apollo-error-template) for reproducing the issue.
35 |
36 | ### Improving the documentation
37 |
38 | Improving the documentation, examples, and other open source content can be the easiest way to contribute to the library. If you see a piece of content that can be better, open a PR with an improvement, no matter how small! If you would like to suggest a big change or major rewrite, we’d love to hear your ideas but please open an issue for discussion before writing the PR.
39 |
40 | ### Responding to issues
41 |
42 | In addition to reporting issues, a great way to contribute to Apollo is to respond to other peoples' issues and try to identify the problem or help them work around it. If you’re interested in taking a more active role in this process, please go ahead and respond to issues. And don't forget to say "Hi" on Apollo Slack!
43 |
44 | ### Small bug fixes
45 |
46 | For a small bug fix change (less than 20 lines of code changed), feel free to open a pull request. We’ll try to merge it as fast as possible and ideally publish a new release on the same day. The only requirement is, make sure you also add a test that verifies the bug you are trying to fix.
47 |
48 | ### Suggesting features
49 |
50 | Most of the features in Apollo came from suggestions by you, the community! We welcome any ideas about how to make Apollo better for your use case. Unless there is overwhelming demand for a feature, it might not get implemented immediately, but please include as much information as possible that will help people have a discussion about your proposal:
51 |
52 | 1. **Use case:** What are you trying to accomplish, in specific terms? Often, there might already be a good way to do what you need and a new feature is unnecessary, but it’s hard to know without information about the specific use case.
53 | 2. **Could this be a plugin?** In many cases, a feature might be too niche to be included in the core of a library, and is better implemented as a companion package. If there isn’t a way to extend the library to do what you want, could we add additional plugin APIs? It’s important to make the case for why a feature should be part of the core functionality of the library.
54 | 3. **Is there a workaround?** Is this a more convenient way to do something that is already possible, or is there some blocker that makes a workaround unfeasible?
55 |
56 | Feature requests will be labeled as such, and we encourage using GitHub issues as a place to discuss new features and possible implementation designs. Please refrain from submitting a pull request to implement a proposed feature until there is consensus that it should be included. This way, you can avoid putting in work that can’t be merged in.
57 |
58 | Once there is a consensus on the need for a new feature, proceed as listed below under “Big PRs”.
59 |
60 | ## Big PRs
61 |
62 | This includes:
63 |
64 | - Big bug fixes
65 | - New features
66 |
67 | For significant changes to a repository, it’s important to settle on a design before starting on the implementation. This way, we can make sure that major improvements get the care and attention they deserve. Since big changes can be risky and might not always get merged, it’s good to reduce the amount of possible wasted effort by agreeing on an implementation design/plan first.
68 |
69 | 1. **Open an issue.** Open an issue about your bug or feature, as described above.
70 | 2. **Reach consensus.** Some contributors and community members should reach an agreement that this feature or bug is important, and that someone should work on implementing or fixing it.
71 | 3. **Agree on intended behavior.** On the issue, reach an agreement about the desired behavior. In the case of a bug fix, it should be clear what it means for the bug to be fixed, and in the case of a feature, it should be clear what it will be like for developers to use the new feature.
72 | 4. **Agree on implementation plan.** Write a plan for how this feature or bug fix should be implemented. What modules need to be added or rewritten? Should this be one pull request or multiple incremental improvements? Who is going to do each part?
73 | 5. **Submit PR.** In the case where multiple dependent patches need to be made to implement the change, only submit one at a time. Otherwise, the others might get stale while the first is reviewed and merged. Make sure to avoid “while we’re here” type changes - if something isn’t relevant to the improvement at hand, it should be in a separate PR; this especially includes code style changes of unrelated code.
74 | 6. **Review.** At least one core contributor should sign off on the change before it’s merged. Look at the “code review” section below to learn about factors are important in the code review. If you want to expedite the code being merged, try to review your own code first!
75 | 7. **Merge and release!**
76 |
77 | ### Code review guidelines
78 |
79 | It’s important that every piece of code in Apollo packages is reviewed by at least one core contributor familiar with that codebase. Here are some things we look for:
80 |
81 | 1. **Required CI checks pass.** This is a prerequisite for the review, and it is the PR author's responsibility. As long as the tests don’t pass, the PR won't get reviewed.
82 | 2. **Simplicity.** Is this the simplest way to achieve the intended goal? If there are too many files, redundant functions, or complex lines of code, suggest a simpler way to do the same thing. In particular, avoid implementing an overly general solution when a simple, small, and pragmatic fix will do.
83 | 3. **Testing.** Do the tests ensure this code won’t break when other stuff changes around it? When it does break, will the tests added help us identify which part of the library has the problem? Did we cover an appropriate set of edge cases? Look at the test coverage report if there is one. Are all significant code paths in the new code exercised at least once?
84 | 4. **No unnecessary or unrelated changes.** PRs shouldn’t come with random formatting changes, especially in unrelated parts of the code. If there is some refactoring that needs to be done, it should be in a separate PR from a bug fix or feature, if possible.
85 | 5. **Code has appropriate comments.** Code should be commented, or written in a clear “self-documenting” way.
86 | 6. **Idiomatic use of the language.** In TypeScript, make sure the typings are specific and correct. In ES2015, make sure to use imports rather than require and const instead of var, etc. Ideally a linter enforces a lot of this, but use your common sense and follow the style of the surrounding code.
87 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Archival
2 | This repo was archived by the Apollo Security team on 2023-05-26
3 |
4 |
5 | # Reason-apollo
6 |
7 | [](https://badge.fury.io/js/reason-apollo)
8 | [](https://spectrum.chat/apollo)
9 |
10 | > react-apollo with ReasonML
11 |
12 | ## Install and setup
13 |
14 | #### Install
15 |
16 | ```
17 | yarn add reason-apollo
18 |
19 | # Add graphql_ppx
20 | yarn add @baransu/graphql_ppx_re --dev
21 | ```
22 |
23 | #### bsconfig
24 |
25 | Add `reason-apollo` to your `bs-dependencies` and
26 | `@baransu/graphql_ppx_re/ppx` to your `ppx-flags`
27 |
28 | **bsconfig.json**
29 |
30 | ```
31 | "bs-dependencies": [
32 | "reason-react",
33 | "reason-apollo"
34 | ],
35 | "ppx-flags": [
36 | "@baransu/graphql_ppx_re/ppx"
37 | ]
38 | ```
39 |
40 | #### Send introspection query
41 |
42 | This will generate a `graphql_schema.json` which will be used to safely type your GraphQL queries/mutations.
43 |
44 | ```
45 | npx get-graphql-schema ENDPOINT_URL -j > graphql_schema.json
46 | ```
47 |
48 | ## Why reason-apollo?
49 |
50 | Watch its usage in this video:
51 |
52 | [](https://www.youtube.com/watch?v=yMqE37LqRLA)
53 |
54 | # Usage
55 |
56 | ## Create the Apollo Client
57 |
58 | **Client.re**
59 |
60 | ```reason
61 | /* Create an InMemoryCache */
62 | let inMemoryCache = ApolloInMemoryCache.createInMemoryCache();
63 |
64 | /* Create an HTTP Link */
65 | let httpLink =
66 | ApolloLinks.createHttpLink(~uri="http://localhost:3010/graphql", ());
67 |
68 | let instance =
69 | ReasonApollo.createApolloClient(~link=httpLink, ~cache=inMemoryCache, ());
70 | ```
71 |
72 | ## ApolloProvider
73 |
74 | **Index.re**
75 |
76 | ```reason
77 | /*
78 | Enhance your application with the `ReasonApollo.Provider`
79 | passing it your client instance
80 | */
81 | ReactDOMRe.renderToElementWithId(
82 |
83 |
84 | ,
85 | "index",
86 | );
87 | ```
88 |
89 | ## Query
90 |
91 | **MyQuery.re**
92 |
93 | ```reason
94 | /* Create a GraphQL Query by using the graphql_ppx */
95 | module GetUserName = [%graphql
96 | {|
97 | query getUserName($id: ID!){
98 | user(id: $ID) {
99 | id
100 | device {
101 | id
102 | brand {
103 | id
104 | name
105 | }
106 | }
107 | }
108 | }
109 | |}
110 | ];
111 |
112 | module GetUserNameQuery = ReasonApollo.CreateQuery(GetUserName);
113 |
114 | [@react.component]
115 | let make = () => {
116 | let userNameQuery = GetUserName.make(~id="42", ());
117 |
118 | ...{({result}) =>
119 | switch (result) {
120 | | Loading => {ReasonReact.string("Loading")}
121 | | Error(error) => {ReasonReact.string(error##message)}
122 | | Data(response) =>
123 |
124 | {/* Handles a deeply nested optional response */
125 | response##user
126 | ->Belt.Option.flatMap(user => user##device)
127 | ->Belt.Option.flatMap(device => device##brand)
128 | ->Belt.Option.mapWithDefault("", brand => brand##name)}
129 |
130 | }
131 | }
132 | ;
133 | };
134 |
135 | ```
136 |
137 | ## Mutation
138 |
139 | **MyMutation.re**
140 |
141 | ```reason
142 | module AddUser = [%graphql
143 | {|
144 | mutation addUser($name: String!) {
145 | addUser(name: $name) {
146 | id
147 | name
148 | }
149 | }
150 | |}
151 | ];
152 |
153 | module AddUserMutation = ReasonApollo.CreateMutation(AddUser);
154 |
155 | [[@react.component]
156 | let make = () => {
157 |
158 | ...{(mutation /* Mutation to call */, _ /* Result of your mutation */) => {
159 | let addNewUserQuery = AddUser.make(~name="Bob", ());
160 |
161 |
163 | mutation(
164 | ~variables=addNewUserQuery##variables,
165 | ~refetchQueries=[|"getAllUsers"|],
166 | (),
167 | )
168 | |> ignore
169 | }>
170 | {ReasonReact.string("Add User")}
171 |
172 |
;
173 | }}
174 | ;
175 | };
176 | ```
177 |
178 | ## Subscription
179 |
180 | **MySubscription.re**
181 |
182 | ```reason
183 | module UserAdded = [%graphql {|
184 | subscription userAdded {
185 | userAdded {
186 | id
187 | name
188 | }
189 | }
190 | |}];
191 |
192 | module UserAddedSubscription = ReasonApollo.CreateSubscription(UserAdded);
193 |
194 | [@react.component]
195 | let make = () => {
196 |
197 | ...{({result}) => {
198 | switch (result) {
199 | | Loading => {ReasonReact.string("Loading")}
200 | | Error(error) => {ReasonReact.string(error##message)}
201 | | Data(_response) =>
202 |
203 |
204 |
205 |
206 | }
207 | }}
208 | ;
209 | };
210 | ```
211 |
212 | ## ApolloConsumer
213 |
214 | If you simply want to have access to the ApolloClient, you can use the `ApolloConsumer`
215 |
216 | ```reason
217 |
218 | ...{apolloClient => {/* We have access to the client! */}}
219 | ;
220 | ```
221 |
222 | ## Tips and Tricks
223 |
224 | ### access deeply nested optional objects
225 |
226 | If for this query
227 |
228 | ```graphql
229 | query {
230 | user {
231 | device {
232 | brand {
233 | name
234 | }
235 | }
236 | }
237 | }
238 | ```
239 |
240 | you end up with that kind of code:
241 |
242 | ```reason
243 | let deviceName =
244 | switch (response##user) {
245 | | None => ""
246 | | Some(user) =>
247 | switch (user##device) {
248 | | None => ""
249 | | Some(device) =>
250 | switch (device##brand) {
251 | | None => ""
252 | | Some(brand) => brand##name
253 | }
254 | }
255 | };
256 |
257 | ```
258 |
259 | 1. Use `Belt`
260 |
261 | ```reason
262 | open Belt.Option;
263 |
264 | let deviceName =
265 | response##user
266 | ->flatMap(user => user##device)
267 | ->flatMap(device => device##brand)
268 | ->mapWithDefault("", brand => brand##name);
269 | ```
270 |
271 | 2. Use `@bsRecord`
272 |
273 | The `@bsRecord` modifier is an [extension](https://github.com/reasonml-community/graphql_ppx#record-conversion) of the graphql syntax for BuckleScipt/ReasonML. It allows you to convert a reason object to a reason record and reap the benefits of pattern matching, but you need to defined the record by yourself.
274 |
275 | ```reason
276 | type brand = {
277 | name: string
278 | };
279 |
280 | type device = {
281 | brand: option(brand)
282 | };
283 |
284 | type user = {
285 | device: option(device)
286 | };
287 |
288 | type response = user;
289 |
290 | query {
291 | user @bsRecord {
292 | device @bsRecord {
293 | brand @bsRecord {
294 | name
295 | }
296 | }
297 | }
298 | }
299 | ```
300 |
301 | This time we can pattern match more precisely.
302 |
303 | ```reason
304 | let deviceName =
305 | switch (response##user) {
306 | | Some({device: Some({brand: {name}})}) => name
307 | | _ => ""
308 | };
309 |
310 | ```
311 |
312 | 3. Use `get_in_ppx`
313 |
314 | `npm install get_in_ppx`
315 | and in `bsconfig.json`
316 | `"ppx-flags": ["get_in_ppx/ppx"]`
317 | you can write
318 |
319 | ```reason
320 | let deviceName = response##user#??device#??brand#?name;
321 | ```
322 |
323 | There's a [blogpost](https://jaredforsyth.com/posts/optional-attribute-access-in-reason/) from Jared Forsyth (author of this ppx) for more explanation.
324 |
325 | ### Use an alias for irregular field names
326 |
327 | You might find yourself consuming an API with field names like `Field`. Currently, reason object field names are required to be camel case. Therefore if you have a request like this:
328 |
329 | ```reason
330 | {
331 | Object {
332 | id
333 | title
334 | }
335 | }
336 | ```
337 |
338 | You will attempt to access the response object but it will throw an error:
339 |
340 | ```reason
341 | response##Object; /* Does not work :( */
342 | ```
343 |
344 | Instead, use an `alias` to modify the response:
345 |
346 | ```reason
347 | {
348 | object: Object {
349 | id
350 | title
351 | }
352 | }
353 | ```
354 |
355 | Then you can access the object like this:
356 |
357 | ```reason
358 | response##object
359 | ```
360 |
361 | ### Generic Error and Loading components
362 |
363 | You can create a generic error and Loading component and compose them like this example:
364 |
365 | ```reason
366 | module QueryView = {
367 | [@react.component]
368 | let make =
369 | (
370 | ~result: ReasonApolloTypes.queryResponse('a),
371 | ~accessData: 'a => option('b),
372 | ~render: ('b, 'c) => React.element,
373 | ~onLoadMore: ('b, 'unit) => unit=(_, ()) => (),
374 | ) => {
375 | switch (result) {
376 | | Error(error) =>
377 | | Loading => ReasonReact.null
378 | | Data(response) =>
379 | switch (accessData(response)) {
380 | | Some(data) => render(data, onLoadMore(data))
381 | | _ =>
382 | }
383 | };
384 | };
385 | };
386 |
387 | ```
388 |
389 | ## FAQ
390 |
391 | ### I've added the schema file, but my build fails saying it couldn't be found?
392 |
393 | In some cases, it seems like there are some differences between the provided `send-introspection-query`
394 | and output from tools you might be using to download the schema (such as `apollo-codegen` or `graphql-cli`).
395 | If your build is failing, please make sure to try with the provided script. In your project root, run:
396 |
397 | ```
398 | npx get-graphql-schema ENDPOINT_URL -j > graphql_schema.json
399 | ```
400 |
--------------------------------------------------------------------------------
/examples/pr/196/client/graphql_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "__schema": {
4 | "queryType": {
5 | "name": "Query"
6 | },
7 | "mutationType": null,
8 | "subscriptionType": null,
9 | "types": [
10 | {
11 | "kind": "OBJECT",
12 | "name": "Query",
13 | "description": "",
14 | "fields": [
15 | {
16 | "name": "wallets",
17 | "description": "",
18 | "args": [],
19 | "type": {
20 | "kind": "NON_NULL",
21 | "name": null,
22 | "ofType": {
23 | "kind": "LIST",
24 | "name": null,
25 | "ofType": {
26 | "kind": "NON_NULL",
27 | "name": null,
28 | "ofType": {
29 | "kind": "OBJECT",
30 | "name": "Wallet",
31 | "ofType": null
32 | }
33 | }
34 | }
35 | },
36 | "isDeprecated": false,
37 | "deprecationReason": null
38 | },
39 | {
40 | "name": "settings",
41 | "description": "",
42 | "args": [],
43 | "type": {
44 | "kind": "NON_NULL",
45 | "name": null,
46 | "ofType": {
47 | "kind": "OBJECT",
48 | "name": "Settings",
49 | "ofType": null
50 | }
51 | },
52 | "isDeprecated": false,
53 | "deprecationReason": null
54 | }
55 | ],
56 | "inputFields": null,
57 | "interfaces": [],
58 | "enumValues": null,
59 | "possibleTypes": null
60 | },
61 | {
62 | "kind": "OBJECT",
63 | "name": "Wallet",
64 | "description": "",
65 | "fields": [
66 | {
67 | "name": "id",
68 | "description": "",
69 | "args": [],
70 | "type": {
71 | "kind": "NON_NULL",
72 | "name": null,
73 | "ofType": {
74 | "kind": "SCALAR",
75 | "name": "ID",
76 | "ofType": null
77 | }
78 | },
79 | "isDeprecated": false,
80 | "deprecationReason": null
81 | },
82 | {
83 | "name": "name",
84 | "description": "",
85 | "args": [],
86 | "type": {
87 | "kind": "NON_NULL",
88 | "name": null,
89 | "ofType": {
90 | "kind": "SCALAR",
91 | "name": "String",
92 | "ofType": null
93 | }
94 | },
95 | "isDeprecated": false,
96 | "deprecationReason": null
97 | }
98 | ],
99 | "inputFields": null,
100 | "interfaces": [],
101 | "enumValues": null,
102 | "possibleTypes": null
103 | },
104 | {
105 | "kind": "SCALAR",
106 | "name": "ID",
107 | "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
108 | "fields": null,
109 | "inputFields": null,
110 | "interfaces": null,
111 | "enumValues": null,
112 | "possibleTypes": null
113 | },
114 | {
115 | "kind": "SCALAR",
116 | "name": "String",
117 | "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.",
118 | "fields": null,
119 | "inputFields": null,
120 | "interfaces": null,
121 | "enumValues": null,
122 | "possibleTypes": null
123 | },
124 | {
125 | "kind": "OBJECT",
126 | "name": "Settings",
127 | "description": "",
128 | "fields": [
129 | {
130 | "name": "id",
131 | "description": "",
132 | "args": [],
133 | "type": {
134 | "kind": "NON_NULL",
135 | "name": null,
136 | "ofType": {
137 | "kind": "SCALAR",
138 | "name": "ID",
139 | "ofType": null
140 | }
141 | },
142 | "isDeprecated": false,
143 | "deprecationReason": null
144 | },
145 | {
146 | "name": "version",
147 | "description": "",
148 | "args": [],
149 | "type": {
150 | "kind": "NON_NULL",
151 | "name": null,
152 | "ofType": {
153 | "kind": "SCALAR",
154 | "name": "String",
155 | "ofType": null
156 | }
157 | },
158 | "isDeprecated": false,
159 | "deprecationReason": null
160 | },
161 | {
162 | "name": "wallets",
163 | "description": "",
164 | "args": [],
165 | "type": {
166 | "kind": "NON_NULL",
167 | "name": null,
168 | "ofType": {
169 | "kind": "LIST",
170 | "name": null,
171 | "ofType": {
172 | "kind": "NON_NULL",
173 | "name": null,
174 | "ofType": {
175 | "kind": "OBJECT",
176 | "name": "Wallet",
177 | "ofType": null
178 | }
179 | }
180 | }
181 | },
182 | "isDeprecated": false,
183 | "deprecationReason": null
184 | }
185 | ],
186 | "inputFields": null,
187 | "interfaces": [],
188 | "enumValues": null,
189 | "possibleTypes": null
190 | },
191 | {
192 | "kind": "OBJECT",
193 | "name": "__Schema",
194 | "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",
195 | "fields": [
196 | {
197 | "name": "types",
198 | "description": "A list of all types supported by this server.",
199 | "args": [],
200 | "type": {
201 | "kind": "NON_NULL",
202 | "name": null,
203 | "ofType": {
204 | "kind": "LIST",
205 | "name": null,
206 | "ofType": {
207 | "kind": "NON_NULL",
208 | "name": null,
209 | "ofType": {
210 | "kind": "OBJECT",
211 | "name": "__Type",
212 | "ofType": null
213 | }
214 | }
215 | }
216 | },
217 | "isDeprecated": false,
218 | "deprecationReason": null
219 | },
220 | {
221 | "name": "queryType",
222 | "description": "The type that query operations will be rooted at.",
223 | "args": [],
224 | "type": {
225 | "kind": "NON_NULL",
226 | "name": null,
227 | "ofType": {
228 | "kind": "OBJECT",
229 | "name": "__Type",
230 | "ofType": null
231 | }
232 | },
233 | "isDeprecated": false,
234 | "deprecationReason": null
235 | },
236 | {
237 | "name": "mutationType",
238 | "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
239 | "args": [],
240 | "type": {
241 | "kind": "OBJECT",
242 | "name": "__Type",
243 | "ofType": null
244 | },
245 | "isDeprecated": false,
246 | "deprecationReason": null
247 | },
248 | {
249 | "name": "subscriptionType",
250 | "description": "If this server support subscription, the type that subscription operations will be rooted at.",
251 | "args": [],
252 | "type": {
253 | "kind": "OBJECT",
254 | "name": "__Type",
255 | "ofType": null
256 | },
257 | "isDeprecated": false,
258 | "deprecationReason": null
259 | },
260 | {
261 | "name": "directives",
262 | "description": "A list of all directives supported by this server.",
263 | "args": [],
264 | "type": {
265 | "kind": "NON_NULL",
266 | "name": null,
267 | "ofType": {
268 | "kind": "LIST",
269 | "name": null,
270 | "ofType": {
271 | "kind": "NON_NULL",
272 | "name": null,
273 | "ofType": {
274 | "kind": "OBJECT",
275 | "name": "__Directive",
276 | "ofType": null
277 | }
278 | }
279 | }
280 | },
281 | "isDeprecated": false,
282 | "deprecationReason": null
283 | }
284 | ],
285 | "inputFields": null,
286 | "interfaces": [],
287 | "enumValues": null,
288 | "possibleTypes": null
289 | },
290 | {
291 | "kind": "OBJECT",
292 | "name": "__Type",
293 | "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",
294 | "fields": [
295 | {
296 | "name": "kind",
297 | "description": null,
298 | "args": [],
299 | "type": {
300 | "kind": "NON_NULL",
301 | "name": null,
302 | "ofType": {
303 | "kind": "ENUM",
304 | "name": "__TypeKind",
305 | "ofType": null
306 | }
307 | },
308 | "isDeprecated": false,
309 | "deprecationReason": null
310 | },
311 | {
312 | "name": "name",
313 | "description": null,
314 | "args": [],
315 | "type": {
316 | "kind": "SCALAR",
317 | "name": "String",
318 | "ofType": null
319 | },
320 | "isDeprecated": false,
321 | "deprecationReason": null
322 | },
323 | {
324 | "name": "description",
325 | "description": null,
326 | "args": [],
327 | "type": {
328 | "kind": "SCALAR",
329 | "name": "String",
330 | "ofType": null
331 | },
332 | "isDeprecated": false,
333 | "deprecationReason": null
334 | },
335 | {
336 | "name": "fields",
337 | "description": null,
338 | "args": [
339 | {
340 | "name": "includeDeprecated",
341 | "description": null,
342 | "type": {
343 | "kind": "SCALAR",
344 | "name": "Boolean",
345 | "ofType": null
346 | },
347 | "defaultValue": "false"
348 | }
349 | ],
350 | "type": {
351 | "kind": "LIST",
352 | "name": null,
353 | "ofType": {
354 | "kind": "NON_NULL",
355 | "name": null,
356 | "ofType": {
357 | "kind": "OBJECT",
358 | "name": "__Field",
359 | "ofType": null
360 | }
361 | }
362 | },
363 | "isDeprecated": false,
364 | "deprecationReason": null
365 | },
366 | {
367 | "name": "interfaces",
368 | "description": null,
369 | "args": [],
370 | "type": {
371 | "kind": "LIST",
372 | "name": null,
373 | "ofType": {
374 | "kind": "NON_NULL",
375 | "name": null,
376 | "ofType": {
377 | "kind": "OBJECT",
378 | "name": "__Type",
379 | "ofType": null
380 | }
381 | }
382 | },
383 | "isDeprecated": false,
384 | "deprecationReason": null
385 | },
386 | {
387 | "name": "possibleTypes",
388 | "description": null,
389 | "args": [],
390 | "type": {
391 | "kind": "LIST",
392 | "name": null,
393 | "ofType": {
394 | "kind": "NON_NULL",
395 | "name": null,
396 | "ofType": {
397 | "kind": "OBJECT",
398 | "name": "__Type",
399 | "ofType": null
400 | }
401 | }
402 | },
403 | "isDeprecated": false,
404 | "deprecationReason": null
405 | },
406 | {
407 | "name": "enumValues",
408 | "description": null,
409 | "args": [
410 | {
411 | "name": "includeDeprecated",
412 | "description": null,
413 | "type": {
414 | "kind": "SCALAR",
415 | "name": "Boolean",
416 | "ofType": null
417 | },
418 | "defaultValue": "false"
419 | }
420 | ],
421 | "type": {
422 | "kind": "LIST",
423 | "name": null,
424 | "ofType": {
425 | "kind": "NON_NULL",
426 | "name": null,
427 | "ofType": {
428 | "kind": "OBJECT",
429 | "name": "__EnumValue",
430 | "ofType": null
431 | }
432 | }
433 | },
434 | "isDeprecated": false,
435 | "deprecationReason": null
436 | },
437 | {
438 | "name": "inputFields",
439 | "description": null,
440 | "args": [],
441 | "type": {
442 | "kind": "LIST",
443 | "name": null,
444 | "ofType": {
445 | "kind": "NON_NULL",
446 | "name": null,
447 | "ofType": {
448 | "kind": "OBJECT",
449 | "name": "__InputValue",
450 | "ofType": null
451 | }
452 | }
453 | },
454 | "isDeprecated": false,
455 | "deprecationReason": null
456 | },
457 | {
458 | "name": "ofType",
459 | "description": null,
460 | "args": [],
461 | "type": {
462 | "kind": "OBJECT",
463 | "name": "__Type",
464 | "ofType": null
465 | },
466 | "isDeprecated": false,
467 | "deprecationReason": null
468 | }
469 | ],
470 | "inputFields": null,
471 | "interfaces": [],
472 | "enumValues": null,
473 | "possibleTypes": null
474 | },
475 | {
476 | "kind": "ENUM",
477 | "name": "__TypeKind",
478 | "description": "An enum describing what kind of type a given `__Type` is.",
479 | "fields": null,
480 | "inputFields": null,
481 | "interfaces": null,
482 | "enumValues": [
483 | {
484 | "name": "SCALAR",
485 | "description": "Indicates this type is a scalar.",
486 | "isDeprecated": false,
487 | "deprecationReason": null
488 | },
489 | {
490 | "name": "OBJECT",
491 | "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
492 | "isDeprecated": false,
493 | "deprecationReason": null
494 | },
495 | {
496 | "name": "INTERFACE",
497 | "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
498 | "isDeprecated": false,
499 | "deprecationReason": null
500 | },
501 | {
502 | "name": "UNION",
503 | "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
504 | "isDeprecated": false,
505 | "deprecationReason": null
506 | },
507 | {
508 | "name": "ENUM",
509 | "description": "Indicates this type is an enum. `enumValues` is a valid field.",
510 | "isDeprecated": false,
511 | "deprecationReason": null
512 | },
513 | {
514 | "name": "INPUT_OBJECT",
515 | "description": "Indicates this type is an input object. `inputFields` is a valid field.",
516 | "isDeprecated": false,
517 | "deprecationReason": null
518 | },
519 | {
520 | "name": "LIST",
521 | "description": "Indicates this type is a list. `ofType` is a valid field.",
522 | "isDeprecated": false,
523 | "deprecationReason": null
524 | },
525 | {
526 | "name": "NON_NULL",
527 | "description": "Indicates this type is a non-null. `ofType` is a valid field.",
528 | "isDeprecated": false,
529 | "deprecationReason": null
530 | }
531 | ],
532 | "possibleTypes": null
533 | },
534 | {
535 | "kind": "SCALAR",
536 | "name": "Boolean",
537 | "description": "The `Boolean` scalar type represents `true` or `false`.",
538 | "fields": null,
539 | "inputFields": null,
540 | "interfaces": null,
541 | "enumValues": null,
542 | "possibleTypes": null
543 | },
544 | {
545 | "kind": "OBJECT",
546 | "name": "__Field",
547 | "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",
548 | "fields": [
549 | {
550 | "name": "name",
551 | "description": null,
552 | "args": [],
553 | "type": {
554 | "kind": "NON_NULL",
555 | "name": null,
556 | "ofType": {
557 | "kind": "SCALAR",
558 | "name": "String",
559 | "ofType": null
560 | }
561 | },
562 | "isDeprecated": false,
563 | "deprecationReason": null
564 | },
565 | {
566 | "name": "description",
567 | "description": null,
568 | "args": [],
569 | "type": {
570 | "kind": "SCALAR",
571 | "name": "String",
572 | "ofType": null
573 | },
574 | "isDeprecated": false,
575 | "deprecationReason": null
576 | },
577 | {
578 | "name": "args",
579 | "description": null,
580 | "args": [],
581 | "type": {
582 | "kind": "NON_NULL",
583 | "name": null,
584 | "ofType": {
585 | "kind": "LIST",
586 | "name": null,
587 | "ofType": {
588 | "kind": "NON_NULL",
589 | "name": null,
590 | "ofType": {
591 | "kind": "OBJECT",
592 | "name": "__InputValue",
593 | "ofType": null
594 | }
595 | }
596 | }
597 | },
598 | "isDeprecated": false,
599 | "deprecationReason": null
600 | },
601 | {
602 | "name": "type",
603 | "description": null,
604 | "args": [],
605 | "type": {
606 | "kind": "NON_NULL",
607 | "name": null,
608 | "ofType": {
609 | "kind": "OBJECT",
610 | "name": "__Type",
611 | "ofType": null
612 | }
613 | },
614 | "isDeprecated": false,
615 | "deprecationReason": null
616 | },
617 | {
618 | "name": "isDeprecated",
619 | "description": null,
620 | "args": [],
621 | "type": {
622 | "kind": "NON_NULL",
623 | "name": null,
624 | "ofType": {
625 | "kind": "SCALAR",
626 | "name": "Boolean",
627 | "ofType": null
628 | }
629 | },
630 | "isDeprecated": false,
631 | "deprecationReason": null
632 | },
633 | {
634 | "name": "deprecationReason",
635 | "description": null,
636 | "args": [],
637 | "type": {
638 | "kind": "SCALAR",
639 | "name": "String",
640 | "ofType": null
641 | },
642 | "isDeprecated": false,
643 | "deprecationReason": null
644 | }
645 | ],
646 | "inputFields": null,
647 | "interfaces": [],
648 | "enumValues": null,
649 | "possibleTypes": null
650 | },
651 | {
652 | "kind": "OBJECT",
653 | "name": "__InputValue",
654 | "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",
655 | "fields": [
656 | {
657 | "name": "name",
658 | "description": null,
659 | "args": [],
660 | "type": {
661 | "kind": "NON_NULL",
662 | "name": null,
663 | "ofType": {
664 | "kind": "SCALAR",
665 | "name": "String",
666 | "ofType": null
667 | }
668 | },
669 | "isDeprecated": false,
670 | "deprecationReason": null
671 | },
672 | {
673 | "name": "description",
674 | "description": null,
675 | "args": [],
676 | "type": {
677 | "kind": "SCALAR",
678 | "name": "String",
679 | "ofType": null
680 | },
681 | "isDeprecated": false,
682 | "deprecationReason": null
683 | },
684 | {
685 | "name": "type",
686 | "description": null,
687 | "args": [],
688 | "type": {
689 | "kind": "NON_NULL",
690 | "name": null,
691 | "ofType": {
692 | "kind": "OBJECT",
693 | "name": "__Type",
694 | "ofType": null
695 | }
696 | },
697 | "isDeprecated": false,
698 | "deprecationReason": null
699 | },
700 | {
701 | "name": "defaultValue",
702 | "description": "A GraphQL-formatted string representing the default value for this input value.",
703 | "args": [],
704 | "type": {
705 | "kind": "SCALAR",
706 | "name": "String",
707 | "ofType": null
708 | },
709 | "isDeprecated": false,
710 | "deprecationReason": null
711 | }
712 | ],
713 | "inputFields": null,
714 | "interfaces": [],
715 | "enumValues": null,
716 | "possibleTypes": null
717 | },
718 | {
719 | "kind": "OBJECT",
720 | "name": "__EnumValue",
721 | "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",
722 | "fields": [
723 | {
724 | "name": "name",
725 | "description": null,
726 | "args": [],
727 | "type": {
728 | "kind": "NON_NULL",
729 | "name": null,
730 | "ofType": {
731 | "kind": "SCALAR",
732 | "name": "String",
733 | "ofType": null
734 | }
735 | },
736 | "isDeprecated": false,
737 | "deprecationReason": null
738 | },
739 | {
740 | "name": "description",
741 | "description": null,
742 | "args": [],
743 | "type": {
744 | "kind": "SCALAR",
745 | "name": "String",
746 | "ofType": null
747 | },
748 | "isDeprecated": false,
749 | "deprecationReason": null
750 | },
751 | {
752 | "name": "isDeprecated",
753 | "description": null,
754 | "args": [],
755 | "type": {
756 | "kind": "NON_NULL",
757 | "name": null,
758 | "ofType": {
759 | "kind": "SCALAR",
760 | "name": "Boolean",
761 | "ofType": null
762 | }
763 | },
764 | "isDeprecated": false,
765 | "deprecationReason": null
766 | },
767 | {
768 | "name": "deprecationReason",
769 | "description": null,
770 | "args": [],
771 | "type": {
772 | "kind": "SCALAR",
773 | "name": "String",
774 | "ofType": null
775 | },
776 | "isDeprecated": false,
777 | "deprecationReason": null
778 | }
779 | ],
780 | "inputFields": null,
781 | "interfaces": [],
782 | "enumValues": null,
783 | "possibleTypes": null
784 | },
785 | {
786 | "kind": "OBJECT",
787 | "name": "__Directive",
788 | "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",
789 | "fields": [
790 | {
791 | "name": "name",
792 | "description": null,
793 | "args": [],
794 | "type": {
795 | "kind": "NON_NULL",
796 | "name": null,
797 | "ofType": {
798 | "kind": "SCALAR",
799 | "name": "String",
800 | "ofType": null
801 | }
802 | },
803 | "isDeprecated": false,
804 | "deprecationReason": null
805 | },
806 | {
807 | "name": "description",
808 | "description": null,
809 | "args": [],
810 | "type": {
811 | "kind": "SCALAR",
812 | "name": "String",
813 | "ofType": null
814 | },
815 | "isDeprecated": false,
816 | "deprecationReason": null
817 | },
818 | {
819 | "name": "locations",
820 | "description": null,
821 | "args": [],
822 | "type": {
823 | "kind": "NON_NULL",
824 | "name": null,
825 | "ofType": {
826 | "kind": "LIST",
827 | "name": null,
828 | "ofType": {
829 | "kind": "NON_NULL",
830 | "name": null,
831 | "ofType": {
832 | "kind": "ENUM",
833 | "name": "__DirectiveLocation",
834 | "ofType": null
835 | }
836 | }
837 | }
838 | },
839 | "isDeprecated": false,
840 | "deprecationReason": null
841 | },
842 | {
843 | "name": "args",
844 | "description": null,
845 | "args": [],
846 | "type": {
847 | "kind": "NON_NULL",
848 | "name": null,
849 | "ofType": {
850 | "kind": "LIST",
851 | "name": null,
852 | "ofType": {
853 | "kind": "NON_NULL",
854 | "name": null,
855 | "ofType": {
856 | "kind": "OBJECT",
857 | "name": "__InputValue",
858 | "ofType": null
859 | }
860 | }
861 | }
862 | },
863 | "isDeprecated": false,
864 | "deprecationReason": null
865 | }
866 | ],
867 | "inputFields": null,
868 | "interfaces": [],
869 | "enumValues": null,
870 | "possibleTypes": null
871 | },
872 | {
873 | "kind": "ENUM",
874 | "name": "__DirectiveLocation",
875 | "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",
876 | "fields": null,
877 | "inputFields": null,
878 | "interfaces": null,
879 | "enumValues": [
880 | {
881 | "name": "QUERY",
882 | "description": "Location adjacent to a query operation.",
883 | "isDeprecated": false,
884 | "deprecationReason": null
885 | },
886 | {
887 | "name": "MUTATION",
888 | "description": "Location adjacent to a mutation operation.",
889 | "isDeprecated": false,
890 | "deprecationReason": null
891 | },
892 | {
893 | "name": "SUBSCRIPTION",
894 | "description": "Location adjacent to a subscription operation.",
895 | "isDeprecated": false,
896 | "deprecationReason": null
897 | },
898 | {
899 | "name": "FIELD",
900 | "description": "Location adjacent to a field.",
901 | "isDeprecated": false,
902 | "deprecationReason": null
903 | },
904 | {
905 | "name": "FRAGMENT_DEFINITION",
906 | "description": "Location adjacent to a fragment definition.",
907 | "isDeprecated": false,
908 | "deprecationReason": null
909 | },
910 | {
911 | "name": "FRAGMENT_SPREAD",
912 | "description": "Location adjacent to a fragment spread.",
913 | "isDeprecated": false,
914 | "deprecationReason": null
915 | },
916 | {
917 | "name": "INLINE_FRAGMENT",
918 | "description": "Location adjacent to an inline fragment.",
919 | "isDeprecated": false,
920 | "deprecationReason": null
921 | },
922 | {
923 | "name": "VARIABLE_DEFINITION",
924 | "description": "Location adjacent to a variable definition.",
925 | "isDeprecated": false,
926 | "deprecationReason": null
927 | },
928 | {
929 | "name": "SCHEMA",
930 | "description": "Location adjacent to a schema definition.",
931 | "isDeprecated": false,
932 | "deprecationReason": null
933 | },
934 | {
935 | "name": "SCALAR",
936 | "description": "Location adjacent to a scalar definition.",
937 | "isDeprecated": false,
938 | "deprecationReason": null
939 | },
940 | {
941 | "name": "OBJECT",
942 | "description": "Location adjacent to an object type definition.",
943 | "isDeprecated": false,
944 | "deprecationReason": null
945 | },
946 | {
947 | "name": "FIELD_DEFINITION",
948 | "description": "Location adjacent to a field definition.",
949 | "isDeprecated": false,
950 | "deprecationReason": null
951 | },
952 | {
953 | "name": "ARGUMENT_DEFINITION",
954 | "description": "Location adjacent to an argument definition.",
955 | "isDeprecated": false,
956 | "deprecationReason": null
957 | },
958 | {
959 | "name": "INTERFACE",
960 | "description": "Location adjacent to an interface definition.",
961 | "isDeprecated": false,
962 | "deprecationReason": null
963 | },
964 | {
965 | "name": "UNION",
966 | "description": "Location adjacent to a union definition.",
967 | "isDeprecated": false,
968 | "deprecationReason": null
969 | },
970 | {
971 | "name": "ENUM",
972 | "description": "Location adjacent to an enum definition.",
973 | "isDeprecated": false,
974 | "deprecationReason": null
975 | },
976 | {
977 | "name": "ENUM_VALUE",
978 | "description": "Location adjacent to an enum value definition.",
979 | "isDeprecated": false,
980 | "deprecationReason": null
981 | },
982 | {
983 | "name": "INPUT_OBJECT",
984 | "description": "Location adjacent to an input object type definition.",
985 | "isDeprecated": false,
986 | "deprecationReason": null
987 | },
988 | {
989 | "name": "INPUT_FIELD_DEFINITION",
990 | "description": "Location adjacent to an input object field definition.",
991 | "isDeprecated": false,
992 | "deprecationReason": null
993 | }
994 | ],
995 | "possibleTypes": null
996 | },
997 | {
998 | "kind": "ENUM",
999 | "name": "CacheControlScope",
1000 | "description": "",
1001 | "fields": null,
1002 | "inputFields": null,
1003 | "interfaces": null,
1004 | "enumValues": [
1005 | {
1006 | "name": "PUBLIC",
1007 | "description": "",
1008 | "isDeprecated": false,
1009 | "deprecationReason": null
1010 | },
1011 | {
1012 | "name": "PRIVATE",
1013 | "description": "",
1014 | "isDeprecated": false,
1015 | "deprecationReason": null
1016 | }
1017 | ],
1018 | "possibleTypes": null
1019 | },
1020 | {
1021 | "kind": "SCALAR",
1022 | "name": "Upload",
1023 | "description": "The `Upload` scalar type represents a file upload.",
1024 | "fields": null,
1025 | "inputFields": null,
1026 | "interfaces": null,
1027 | "enumValues": null,
1028 | "possibleTypes": null
1029 | },
1030 | {
1031 | "kind": "SCALAR",
1032 | "name": "Int",
1033 | "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ",
1034 | "fields": null,
1035 | "inputFields": null,
1036 | "interfaces": null,
1037 | "enumValues": null,
1038 | "possibleTypes": null
1039 | }
1040 | ],
1041 | "directives": [
1042 | {
1043 | "name": "cacheControl",
1044 | "description": "",
1045 | "locations": [
1046 | "FIELD_DEFINITION",
1047 | "OBJECT",
1048 | "INTERFACE"
1049 | ],
1050 | "args": [
1051 | {
1052 | "name": "maxAge",
1053 | "description": "",
1054 | "type": {
1055 | "kind": "SCALAR",
1056 | "name": "Int",
1057 | "ofType": null
1058 | },
1059 | "defaultValue": null
1060 | },
1061 | {
1062 | "name": "scope",
1063 | "description": "",
1064 | "type": {
1065 | "kind": "ENUM",
1066 | "name": "CacheControlScope",
1067 | "ofType": null
1068 | },
1069 | "defaultValue": null
1070 | }
1071 | ]
1072 | },
1073 | {
1074 | "name": "skip",
1075 | "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
1076 | "locations": [
1077 | "FIELD",
1078 | "FRAGMENT_SPREAD",
1079 | "INLINE_FRAGMENT"
1080 | ],
1081 | "args": [
1082 | {
1083 | "name": "if",
1084 | "description": "Skipped when true.",
1085 | "type": {
1086 | "kind": "NON_NULL",
1087 | "name": null,
1088 | "ofType": {
1089 | "kind": "SCALAR",
1090 | "name": "Boolean",
1091 | "ofType": null
1092 | }
1093 | },
1094 | "defaultValue": null
1095 | }
1096 | ]
1097 | },
1098 | {
1099 | "name": "include",
1100 | "description": "Directs the executor to include this field or fragment only when the `if` argument is true.",
1101 | "locations": [
1102 | "FIELD",
1103 | "FRAGMENT_SPREAD",
1104 | "INLINE_FRAGMENT"
1105 | ],
1106 | "args": [
1107 | {
1108 | "name": "if",
1109 | "description": "Included when true.",
1110 | "type": {
1111 | "kind": "NON_NULL",
1112 | "name": null,
1113 | "ofType": {
1114 | "kind": "SCALAR",
1115 | "name": "Boolean",
1116 | "ofType": null
1117 | }
1118 | },
1119 | "defaultValue": null
1120 | }
1121 | ]
1122 | },
1123 | {
1124 | "name": "deprecated",
1125 | "description": "Marks an element of a GraphQL schema as no longer supported.",
1126 | "locations": [
1127 | "FIELD_DEFINITION",
1128 | "ENUM_VALUE"
1129 | ],
1130 | "args": [
1131 | {
1132 | "name": "reason",
1133 | "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/).",
1134 | "type": {
1135 | "kind": "SCALAR",
1136 | "name": "String",
1137 | "ofType": null
1138 | },
1139 | "defaultValue": "\"No longer supported\""
1140 | }
1141 | ]
1142 | }
1143 | ]
1144 | }
1145 | }
1146 | }
--------------------------------------------------------------------------------
/examples/realtime-chat-application/graphql_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "__schema": {
4 | "queryType": {
5 | "name": "Query"
6 | },
7 | "mutationType": {
8 | "name": "Mutation"
9 | },
10 | "subscriptionType": {
11 | "name": "Subscription"
12 | },
13 | "types": [
14 | {
15 | "kind": "OBJECT",
16 | "name": "Query",
17 | "description": "",
18 | "fields": [
19 | {
20 | "name": "messages",
21 | "description": "",
22 | "args": [],
23 | "type": {
24 | "kind": "NON_NULL",
25 | "name": null,
26 | "ofType": {
27 | "kind": "LIST",
28 | "name": null,
29 | "ofType": {
30 | "kind": "NON_NULL",
31 | "name": null,
32 | "ofType": {
33 | "kind": "OBJECT",
34 | "name": "Message",
35 | "ofType": null
36 | }
37 | }
38 | }
39 | },
40 | "isDeprecated": false,
41 | "deprecationReason": null
42 | }
43 | ],
44 | "inputFields": null,
45 | "interfaces": [],
46 | "enumValues": null,
47 | "possibleTypes": null
48 | },
49 | {
50 | "kind": "OBJECT",
51 | "name": "Message",
52 | "description": "",
53 | "fields": [
54 | {
55 | "name": "id",
56 | "description": "",
57 | "args": [],
58 | "type": {
59 | "kind": "NON_NULL",
60 | "name": null,
61 | "ofType": {
62 | "kind": "SCALAR",
63 | "name": "ID",
64 | "ofType": null
65 | }
66 | },
67 | "isDeprecated": false,
68 | "deprecationReason": null
69 | },
70 | {
71 | "name": "text",
72 | "description": "",
73 | "args": [],
74 | "type": {
75 | "kind": "NON_NULL",
76 | "name": null,
77 | "ofType": {
78 | "kind": "SCALAR",
79 | "name": "String",
80 | "ofType": null
81 | }
82 | },
83 | "isDeprecated": false,
84 | "deprecationReason": null
85 | },
86 | {
87 | "name": "author",
88 | "description": "",
89 | "args": [],
90 | "type": {
91 | "kind": "NON_NULL",
92 | "name": null,
93 | "ofType": {
94 | "kind": "OBJECT",
95 | "name": "User",
96 | "ofType": null
97 | }
98 | },
99 | "isDeprecated": false,
100 | "deprecationReason": null
101 | }
102 | ],
103 | "inputFields": null,
104 | "interfaces": [],
105 | "enumValues": null,
106 | "possibleTypes": null
107 | },
108 | {
109 | "kind": "SCALAR",
110 | "name": "ID",
111 | "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
112 | "fields": null,
113 | "inputFields": null,
114 | "interfaces": null,
115 | "enumValues": null,
116 | "possibleTypes": null
117 | },
118 | {
119 | "kind": "SCALAR",
120 | "name": "String",
121 | "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.",
122 | "fields": null,
123 | "inputFields": null,
124 | "interfaces": null,
125 | "enumValues": null,
126 | "possibleTypes": null
127 | },
128 | {
129 | "kind": "OBJECT",
130 | "name": "User",
131 | "description": "",
132 | "fields": [
133 | {
134 | "name": "id",
135 | "description": "",
136 | "args": [],
137 | "type": {
138 | "kind": "NON_NULL",
139 | "name": null,
140 | "ofType": {
141 | "kind": "SCALAR",
142 | "name": "ID",
143 | "ofType": null
144 | }
145 | },
146 | "isDeprecated": false,
147 | "deprecationReason": null
148 | },
149 | {
150 | "name": "name",
151 | "description": "",
152 | "args": [],
153 | "type": {
154 | "kind": "NON_NULL",
155 | "name": null,
156 | "ofType": {
157 | "kind": "SCALAR",
158 | "name": "String",
159 | "ofType": null
160 | }
161 | },
162 | "isDeprecated": false,
163 | "deprecationReason": null
164 | }
165 | ],
166 | "inputFields": null,
167 | "interfaces": [],
168 | "enumValues": null,
169 | "possibleTypes": null
170 | },
171 | {
172 | "kind": "OBJECT",
173 | "name": "Mutation",
174 | "description": "",
175 | "fields": [
176 | {
177 | "name": "addMessage",
178 | "description": "",
179 | "args": [
180 | {
181 | "name": "userId",
182 | "description": "",
183 | "type": {
184 | "kind": "NON_NULL",
185 | "name": null,
186 | "ofType": {
187 | "kind": "SCALAR",
188 | "name": "ID",
189 | "ofType": null
190 | }
191 | },
192 | "defaultValue": null
193 | },
194 | {
195 | "name": "text",
196 | "description": "",
197 | "type": {
198 | "kind": "NON_NULL",
199 | "name": null,
200 | "ofType": {
201 | "kind": "SCALAR",
202 | "name": "String",
203 | "ofType": null
204 | }
205 | },
206 | "defaultValue": null
207 | }
208 | ],
209 | "type": {
210 | "kind": "NON_NULL",
211 | "name": null,
212 | "ofType": {
213 | "kind": "OBJECT",
214 | "name": "Message",
215 | "ofType": null
216 | }
217 | },
218 | "isDeprecated": false,
219 | "deprecationReason": null
220 | },
221 | {
222 | "name": "addUser",
223 | "description": "",
224 | "args": [
225 | {
226 | "name": "name",
227 | "description": "",
228 | "type": {
229 | "kind": "NON_NULL",
230 | "name": null,
231 | "ofType": {
232 | "kind": "SCALAR",
233 | "name": "String",
234 | "ofType": null
235 | }
236 | },
237 | "defaultValue": null
238 | }
239 | ],
240 | "type": {
241 | "kind": "NON_NULL",
242 | "name": null,
243 | "ofType": {
244 | "kind": "OBJECT",
245 | "name": "User",
246 | "ofType": null
247 | }
248 | },
249 | "isDeprecated": false,
250 | "deprecationReason": null
251 | }
252 | ],
253 | "inputFields": null,
254 | "interfaces": [],
255 | "enumValues": null,
256 | "possibleTypes": null
257 | },
258 | {
259 | "kind": "OBJECT",
260 | "name": "Subscription",
261 | "description": "",
262 | "fields": [
263 | {
264 | "name": "messageAdded",
265 | "description": "",
266 | "args": [],
267 | "type": {
268 | "kind": "OBJECT",
269 | "name": "Message",
270 | "ofType": null
271 | },
272 | "isDeprecated": false,
273 | "deprecationReason": null
274 | }
275 | ],
276 | "inputFields": null,
277 | "interfaces": [],
278 | "enumValues": null,
279 | "possibleTypes": null
280 | },
281 | {
282 | "kind": "OBJECT",
283 | "name": "__Schema",
284 | "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",
285 | "fields": [
286 | {
287 | "name": "types",
288 | "description": "A list of all types supported by this server.",
289 | "args": [],
290 | "type": {
291 | "kind": "NON_NULL",
292 | "name": null,
293 | "ofType": {
294 | "kind": "LIST",
295 | "name": null,
296 | "ofType": {
297 | "kind": "NON_NULL",
298 | "name": null,
299 | "ofType": {
300 | "kind": "OBJECT",
301 | "name": "__Type",
302 | "ofType": null
303 | }
304 | }
305 | }
306 | },
307 | "isDeprecated": false,
308 | "deprecationReason": null
309 | },
310 | {
311 | "name": "queryType",
312 | "description": "The type that query operations will be rooted at.",
313 | "args": [],
314 | "type": {
315 | "kind": "NON_NULL",
316 | "name": null,
317 | "ofType": {
318 | "kind": "OBJECT",
319 | "name": "__Type",
320 | "ofType": null
321 | }
322 | },
323 | "isDeprecated": false,
324 | "deprecationReason": null
325 | },
326 | {
327 | "name": "mutationType",
328 | "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
329 | "args": [],
330 | "type": {
331 | "kind": "OBJECT",
332 | "name": "__Type",
333 | "ofType": null
334 | },
335 | "isDeprecated": false,
336 | "deprecationReason": null
337 | },
338 | {
339 | "name": "subscriptionType",
340 | "description": "If this server support subscription, the type that subscription operations will be rooted at.",
341 | "args": [],
342 | "type": {
343 | "kind": "OBJECT",
344 | "name": "__Type",
345 | "ofType": null
346 | },
347 | "isDeprecated": false,
348 | "deprecationReason": null
349 | },
350 | {
351 | "name": "directives",
352 | "description": "A list of all directives supported by this server.",
353 | "args": [],
354 | "type": {
355 | "kind": "NON_NULL",
356 | "name": null,
357 | "ofType": {
358 | "kind": "LIST",
359 | "name": null,
360 | "ofType": {
361 | "kind": "NON_NULL",
362 | "name": null,
363 | "ofType": {
364 | "kind": "OBJECT",
365 | "name": "__Directive",
366 | "ofType": null
367 | }
368 | }
369 | }
370 | },
371 | "isDeprecated": false,
372 | "deprecationReason": null
373 | }
374 | ],
375 | "inputFields": null,
376 | "interfaces": [],
377 | "enumValues": null,
378 | "possibleTypes": null
379 | },
380 | {
381 | "kind": "OBJECT",
382 | "name": "__Type",
383 | "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",
384 | "fields": [
385 | {
386 | "name": "kind",
387 | "description": null,
388 | "args": [],
389 | "type": {
390 | "kind": "NON_NULL",
391 | "name": null,
392 | "ofType": {
393 | "kind": "ENUM",
394 | "name": "__TypeKind",
395 | "ofType": null
396 | }
397 | },
398 | "isDeprecated": false,
399 | "deprecationReason": null
400 | },
401 | {
402 | "name": "name",
403 | "description": null,
404 | "args": [],
405 | "type": {
406 | "kind": "SCALAR",
407 | "name": "String",
408 | "ofType": null
409 | },
410 | "isDeprecated": false,
411 | "deprecationReason": null
412 | },
413 | {
414 | "name": "description",
415 | "description": null,
416 | "args": [],
417 | "type": {
418 | "kind": "SCALAR",
419 | "name": "String",
420 | "ofType": null
421 | },
422 | "isDeprecated": false,
423 | "deprecationReason": null
424 | },
425 | {
426 | "name": "fields",
427 | "description": null,
428 | "args": [
429 | {
430 | "name": "includeDeprecated",
431 | "description": null,
432 | "type": {
433 | "kind": "SCALAR",
434 | "name": "Boolean",
435 | "ofType": null
436 | },
437 | "defaultValue": "false"
438 | }
439 | ],
440 | "type": {
441 | "kind": "LIST",
442 | "name": null,
443 | "ofType": {
444 | "kind": "NON_NULL",
445 | "name": null,
446 | "ofType": {
447 | "kind": "OBJECT",
448 | "name": "__Field",
449 | "ofType": null
450 | }
451 | }
452 | },
453 | "isDeprecated": false,
454 | "deprecationReason": null
455 | },
456 | {
457 | "name": "interfaces",
458 | "description": null,
459 | "args": [],
460 | "type": {
461 | "kind": "LIST",
462 | "name": null,
463 | "ofType": {
464 | "kind": "NON_NULL",
465 | "name": null,
466 | "ofType": {
467 | "kind": "OBJECT",
468 | "name": "__Type",
469 | "ofType": null
470 | }
471 | }
472 | },
473 | "isDeprecated": false,
474 | "deprecationReason": null
475 | },
476 | {
477 | "name": "possibleTypes",
478 | "description": null,
479 | "args": [],
480 | "type": {
481 | "kind": "LIST",
482 | "name": null,
483 | "ofType": {
484 | "kind": "NON_NULL",
485 | "name": null,
486 | "ofType": {
487 | "kind": "OBJECT",
488 | "name": "__Type",
489 | "ofType": null
490 | }
491 | }
492 | },
493 | "isDeprecated": false,
494 | "deprecationReason": null
495 | },
496 | {
497 | "name": "enumValues",
498 | "description": null,
499 | "args": [
500 | {
501 | "name": "includeDeprecated",
502 | "description": null,
503 | "type": {
504 | "kind": "SCALAR",
505 | "name": "Boolean",
506 | "ofType": null
507 | },
508 | "defaultValue": "false"
509 | }
510 | ],
511 | "type": {
512 | "kind": "LIST",
513 | "name": null,
514 | "ofType": {
515 | "kind": "NON_NULL",
516 | "name": null,
517 | "ofType": {
518 | "kind": "OBJECT",
519 | "name": "__EnumValue",
520 | "ofType": null
521 | }
522 | }
523 | },
524 | "isDeprecated": false,
525 | "deprecationReason": null
526 | },
527 | {
528 | "name": "inputFields",
529 | "description": null,
530 | "args": [],
531 | "type": {
532 | "kind": "LIST",
533 | "name": null,
534 | "ofType": {
535 | "kind": "NON_NULL",
536 | "name": null,
537 | "ofType": {
538 | "kind": "OBJECT",
539 | "name": "__InputValue",
540 | "ofType": null
541 | }
542 | }
543 | },
544 | "isDeprecated": false,
545 | "deprecationReason": null
546 | },
547 | {
548 | "name": "ofType",
549 | "description": null,
550 | "args": [],
551 | "type": {
552 | "kind": "OBJECT",
553 | "name": "__Type",
554 | "ofType": null
555 | },
556 | "isDeprecated": false,
557 | "deprecationReason": null
558 | }
559 | ],
560 | "inputFields": null,
561 | "interfaces": [],
562 | "enumValues": null,
563 | "possibleTypes": null
564 | },
565 | {
566 | "kind": "ENUM",
567 | "name": "__TypeKind",
568 | "description": "An enum describing what kind of type a given `__Type` is.",
569 | "fields": null,
570 | "inputFields": null,
571 | "interfaces": null,
572 | "enumValues": [
573 | {
574 | "name": "SCALAR",
575 | "description": "Indicates this type is a scalar.",
576 | "isDeprecated": false,
577 | "deprecationReason": null
578 | },
579 | {
580 | "name": "OBJECT",
581 | "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
582 | "isDeprecated": false,
583 | "deprecationReason": null
584 | },
585 | {
586 | "name": "INTERFACE",
587 | "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
588 | "isDeprecated": false,
589 | "deprecationReason": null
590 | },
591 | {
592 | "name": "UNION",
593 | "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
594 | "isDeprecated": false,
595 | "deprecationReason": null
596 | },
597 | {
598 | "name": "ENUM",
599 | "description": "Indicates this type is an enum. `enumValues` is a valid field.",
600 | "isDeprecated": false,
601 | "deprecationReason": null
602 | },
603 | {
604 | "name": "INPUT_OBJECT",
605 | "description": "Indicates this type is an input object. `inputFields` is a valid field.",
606 | "isDeprecated": false,
607 | "deprecationReason": null
608 | },
609 | {
610 | "name": "LIST",
611 | "description": "Indicates this type is a list. `ofType` is a valid field.",
612 | "isDeprecated": false,
613 | "deprecationReason": null
614 | },
615 | {
616 | "name": "NON_NULL",
617 | "description": "Indicates this type is a non-null. `ofType` is a valid field.",
618 | "isDeprecated": false,
619 | "deprecationReason": null
620 | }
621 | ],
622 | "possibleTypes": null
623 | },
624 | {
625 | "kind": "SCALAR",
626 | "name": "Boolean",
627 | "description": "The `Boolean` scalar type represents `true` or `false`.",
628 | "fields": null,
629 | "inputFields": null,
630 | "interfaces": null,
631 | "enumValues": null,
632 | "possibleTypes": null
633 | },
634 | {
635 | "kind": "OBJECT",
636 | "name": "__Field",
637 | "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",
638 | "fields": [
639 | {
640 | "name": "name",
641 | "description": null,
642 | "args": [],
643 | "type": {
644 | "kind": "NON_NULL",
645 | "name": null,
646 | "ofType": {
647 | "kind": "SCALAR",
648 | "name": "String",
649 | "ofType": null
650 | }
651 | },
652 | "isDeprecated": false,
653 | "deprecationReason": null
654 | },
655 | {
656 | "name": "description",
657 | "description": null,
658 | "args": [],
659 | "type": {
660 | "kind": "SCALAR",
661 | "name": "String",
662 | "ofType": null
663 | },
664 | "isDeprecated": false,
665 | "deprecationReason": null
666 | },
667 | {
668 | "name": "args",
669 | "description": null,
670 | "args": [],
671 | "type": {
672 | "kind": "NON_NULL",
673 | "name": null,
674 | "ofType": {
675 | "kind": "LIST",
676 | "name": null,
677 | "ofType": {
678 | "kind": "NON_NULL",
679 | "name": null,
680 | "ofType": {
681 | "kind": "OBJECT",
682 | "name": "__InputValue",
683 | "ofType": null
684 | }
685 | }
686 | }
687 | },
688 | "isDeprecated": false,
689 | "deprecationReason": null
690 | },
691 | {
692 | "name": "type",
693 | "description": null,
694 | "args": [],
695 | "type": {
696 | "kind": "NON_NULL",
697 | "name": null,
698 | "ofType": {
699 | "kind": "OBJECT",
700 | "name": "__Type",
701 | "ofType": null
702 | }
703 | },
704 | "isDeprecated": false,
705 | "deprecationReason": null
706 | },
707 | {
708 | "name": "isDeprecated",
709 | "description": null,
710 | "args": [],
711 | "type": {
712 | "kind": "NON_NULL",
713 | "name": null,
714 | "ofType": {
715 | "kind": "SCALAR",
716 | "name": "Boolean",
717 | "ofType": null
718 | }
719 | },
720 | "isDeprecated": false,
721 | "deprecationReason": null
722 | },
723 | {
724 | "name": "deprecationReason",
725 | "description": null,
726 | "args": [],
727 | "type": {
728 | "kind": "SCALAR",
729 | "name": "String",
730 | "ofType": null
731 | },
732 | "isDeprecated": false,
733 | "deprecationReason": null
734 | }
735 | ],
736 | "inputFields": null,
737 | "interfaces": [],
738 | "enumValues": null,
739 | "possibleTypes": null
740 | },
741 | {
742 | "kind": "OBJECT",
743 | "name": "__InputValue",
744 | "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",
745 | "fields": [
746 | {
747 | "name": "name",
748 | "description": null,
749 | "args": [],
750 | "type": {
751 | "kind": "NON_NULL",
752 | "name": null,
753 | "ofType": {
754 | "kind": "SCALAR",
755 | "name": "String",
756 | "ofType": null
757 | }
758 | },
759 | "isDeprecated": false,
760 | "deprecationReason": null
761 | },
762 | {
763 | "name": "description",
764 | "description": null,
765 | "args": [],
766 | "type": {
767 | "kind": "SCALAR",
768 | "name": "String",
769 | "ofType": null
770 | },
771 | "isDeprecated": false,
772 | "deprecationReason": null
773 | },
774 | {
775 | "name": "type",
776 | "description": null,
777 | "args": [],
778 | "type": {
779 | "kind": "NON_NULL",
780 | "name": null,
781 | "ofType": {
782 | "kind": "OBJECT",
783 | "name": "__Type",
784 | "ofType": null
785 | }
786 | },
787 | "isDeprecated": false,
788 | "deprecationReason": null
789 | },
790 | {
791 | "name": "defaultValue",
792 | "description": "A GraphQL-formatted string representing the default value for this input value.",
793 | "args": [],
794 | "type": {
795 | "kind": "SCALAR",
796 | "name": "String",
797 | "ofType": null
798 | },
799 | "isDeprecated": false,
800 | "deprecationReason": null
801 | }
802 | ],
803 | "inputFields": null,
804 | "interfaces": [],
805 | "enumValues": null,
806 | "possibleTypes": null
807 | },
808 | {
809 | "kind": "OBJECT",
810 | "name": "__EnumValue",
811 | "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",
812 | "fields": [
813 | {
814 | "name": "name",
815 | "description": null,
816 | "args": [],
817 | "type": {
818 | "kind": "NON_NULL",
819 | "name": null,
820 | "ofType": {
821 | "kind": "SCALAR",
822 | "name": "String",
823 | "ofType": null
824 | }
825 | },
826 | "isDeprecated": false,
827 | "deprecationReason": null
828 | },
829 | {
830 | "name": "description",
831 | "description": null,
832 | "args": [],
833 | "type": {
834 | "kind": "SCALAR",
835 | "name": "String",
836 | "ofType": null
837 | },
838 | "isDeprecated": false,
839 | "deprecationReason": null
840 | },
841 | {
842 | "name": "isDeprecated",
843 | "description": null,
844 | "args": [],
845 | "type": {
846 | "kind": "NON_NULL",
847 | "name": null,
848 | "ofType": {
849 | "kind": "SCALAR",
850 | "name": "Boolean",
851 | "ofType": null
852 | }
853 | },
854 | "isDeprecated": false,
855 | "deprecationReason": null
856 | },
857 | {
858 | "name": "deprecationReason",
859 | "description": null,
860 | "args": [],
861 | "type": {
862 | "kind": "SCALAR",
863 | "name": "String",
864 | "ofType": null
865 | },
866 | "isDeprecated": false,
867 | "deprecationReason": null
868 | }
869 | ],
870 | "inputFields": null,
871 | "interfaces": [],
872 | "enumValues": null,
873 | "possibleTypes": null
874 | },
875 | {
876 | "kind": "OBJECT",
877 | "name": "__Directive",
878 | "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",
879 | "fields": [
880 | {
881 | "name": "name",
882 | "description": null,
883 | "args": [],
884 | "type": {
885 | "kind": "NON_NULL",
886 | "name": null,
887 | "ofType": {
888 | "kind": "SCALAR",
889 | "name": "String",
890 | "ofType": null
891 | }
892 | },
893 | "isDeprecated": false,
894 | "deprecationReason": null
895 | },
896 | {
897 | "name": "description",
898 | "description": null,
899 | "args": [],
900 | "type": {
901 | "kind": "SCALAR",
902 | "name": "String",
903 | "ofType": null
904 | },
905 | "isDeprecated": false,
906 | "deprecationReason": null
907 | },
908 | {
909 | "name": "locations",
910 | "description": null,
911 | "args": [],
912 | "type": {
913 | "kind": "NON_NULL",
914 | "name": null,
915 | "ofType": {
916 | "kind": "LIST",
917 | "name": null,
918 | "ofType": {
919 | "kind": "NON_NULL",
920 | "name": null,
921 | "ofType": {
922 | "kind": "ENUM",
923 | "name": "__DirectiveLocation",
924 | "ofType": null
925 | }
926 | }
927 | }
928 | },
929 | "isDeprecated": false,
930 | "deprecationReason": null
931 | },
932 | {
933 | "name": "args",
934 | "description": null,
935 | "args": [],
936 | "type": {
937 | "kind": "NON_NULL",
938 | "name": null,
939 | "ofType": {
940 | "kind": "LIST",
941 | "name": null,
942 | "ofType": {
943 | "kind": "NON_NULL",
944 | "name": null,
945 | "ofType": {
946 | "kind": "OBJECT",
947 | "name": "__InputValue",
948 | "ofType": null
949 | }
950 | }
951 | }
952 | },
953 | "isDeprecated": false,
954 | "deprecationReason": null
955 | },
956 | {
957 | "name": "onOperation",
958 | "description": null,
959 | "args": [],
960 | "type": {
961 | "kind": "NON_NULL",
962 | "name": null,
963 | "ofType": {
964 | "kind": "SCALAR",
965 | "name": "Boolean",
966 | "ofType": null
967 | }
968 | },
969 | "isDeprecated": true,
970 | "deprecationReason": "Use `locations`."
971 | },
972 | {
973 | "name": "onFragment",
974 | "description": null,
975 | "args": [],
976 | "type": {
977 | "kind": "NON_NULL",
978 | "name": null,
979 | "ofType": {
980 | "kind": "SCALAR",
981 | "name": "Boolean",
982 | "ofType": null
983 | }
984 | },
985 | "isDeprecated": true,
986 | "deprecationReason": "Use `locations`."
987 | },
988 | {
989 | "name": "onField",
990 | "description": null,
991 | "args": [],
992 | "type": {
993 | "kind": "NON_NULL",
994 | "name": null,
995 | "ofType": {
996 | "kind": "SCALAR",
997 | "name": "Boolean",
998 | "ofType": null
999 | }
1000 | },
1001 | "isDeprecated": true,
1002 | "deprecationReason": "Use `locations`."
1003 | }
1004 | ],
1005 | "inputFields": null,
1006 | "interfaces": [],
1007 | "enumValues": null,
1008 | "possibleTypes": null
1009 | },
1010 | {
1011 | "kind": "ENUM",
1012 | "name": "__DirectiveLocation",
1013 | "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",
1014 | "fields": null,
1015 | "inputFields": null,
1016 | "interfaces": null,
1017 | "enumValues": [
1018 | {
1019 | "name": "QUERY",
1020 | "description": "Location adjacent to a query operation.",
1021 | "isDeprecated": false,
1022 | "deprecationReason": null
1023 | },
1024 | {
1025 | "name": "MUTATION",
1026 | "description": "Location adjacent to a mutation operation.",
1027 | "isDeprecated": false,
1028 | "deprecationReason": null
1029 | },
1030 | {
1031 | "name": "SUBSCRIPTION",
1032 | "description": "Location adjacent to a subscription operation.",
1033 | "isDeprecated": false,
1034 | "deprecationReason": null
1035 | },
1036 | {
1037 | "name": "FIELD",
1038 | "description": "Location adjacent to a field.",
1039 | "isDeprecated": false,
1040 | "deprecationReason": null
1041 | },
1042 | {
1043 | "name": "FRAGMENT_DEFINITION",
1044 | "description": "Location adjacent to a fragment definition.",
1045 | "isDeprecated": false,
1046 | "deprecationReason": null
1047 | },
1048 | {
1049 | "name": "FRAGMENT_SPREAD",
1050 | "description": "Location adjacent to a fragment spread.",
1051 | "isDeprecated": false,
1052 | "deprecationReason": null
1053 | },
1054 | {
1055 | "name": "INLINE_FRAGMENT",
1056 | "description": "Location adjacent to an inline fragment.",
1057 | "isDeprecated": false,
1058 | "deprecationReason": null
1059 | },
1060 | {
1061 | "name": "SCHEMA",
1062 | "description": "Location adjacent to a schema definition.",
1063 | "isDeprecated": false,
1064 | "deprecationReason": null
1065 | },
1066 | {
1067 | "name": "SCALAR",
1068 | "description": "Location adjacent to a scalar definition.",
1069 | "isDeprecated": false,
1070 | "deprecationReason": null
1071 | },
1072 | {
1073 | "name": "OBJECT",
1074 | "description": "Location adjacent to an object type definition.",
1075 | "isDeprecated": false,
1076 | "deprecationReason": null
1077 | },
1078 | {
1079 | "name": "FIELD_DEFINITION",
1080 | "description": "Location adjacent to a field definition.",
1081 | "isDeprecated": false,
1082 | "deprecationReason": null
1083 | },
1084 | {
1085 | "name": "ARGUMENT_DEFINITION",
1086 | "description": "Location adjacent to an argument definition.",
1087 | "isDeprecated": false,
1088 | "deprecationReason": null
1089 | },
1090 | {
1091 | "name": "INTERFACE",
1092 | "description": "Location adjacent to an interface definition.",
1093 | "isDeprecated": false,
1094 | "deprecationReason": null
1095 | },
1096 | {
1097 | "name": "UNION",
1098 | "description": "Location adjacent to a union definition.",
1099 | "isDeprecated": false,
1100 | "deprecationReason": null
1101 | },
1102 | {
1103 | "name": "ENUM",
1104 | "description": "Location adjacent to an enum definition.",
1105 | "isDeprecated": false,
1106 | "deprecationReason": null
1107 | },
1108 | {
1109 | "name": "ENUM_VALUE",
1110 | "description": "Location adjacent to an enum value definition.",
1111 | "isDeprecated": false,
1112 | "deprecationReason": null
1113 | },
1114 | {
1115 | "name": "INPUT_OBJECT",
1116 | "description": "Location adjacent to an input object type definition.",
1117 | "isDeprecated": false,
1118 | "deprecationReason": null
1119 | },
1120 | {
1121 | "name": "INPUT_FIELD_DEFINITION",
1122 | "description": "Location adjacent to an input object field definition.",
1123 | "isDeprecated": false,
1124 | "deprecationReason": null
1125 | }
1126 | ],
1127 | "possibleTypes": null
1128 | },
1129 | {
1130 | "kind": "SCALAR",
1131 | "name": "Upload",
1132 | "description": "The `Upload` scalar type represents a file upload promise that resolves an object containing `stream`, `filename`, `mimetype` and `encoding`.",
1133 | "fields": null,
1134 | "inputFields": null,
1135 | "interfaces": null,
1136 | "enumValues": null,
1137 | "possibleTypes": null
1138 | }
1139 | ],
1140 | "directives": [
1141 | {
1142 | "name": "skip",
1143 | "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
1144 | "locations": [
1145 | "FIELD",
1146 | "FRAGMENT_SPREAD",
1147 | "INLINE_FRAGMENT"
1148 | ],
1149 | "args": [
1150 | {
1151 | "name": "if",
1152 | "description": "Skipped when true.",
1153 | "type": {
1154 | "kind": "NON_NULL",
1155 | "name": null,
1156 | "ofType": {
1157 | "kind": "SCALAR",
1158 | "name": "Boolean",
1159 | "ofType": null
1160 | }
1161 | },
1162 | "defaultValue": null
1163 | }
1164 | ]
1165 | },
1166 | {
1167 | "name": "include",
1168 | "description": "Directs the executor to include this field or fragment only when the `if` argument is true.",
1169 | "locations": [
1170 | "FIELD",
1171 | "FRAGMENT_SPREAD",
1172 | "INLINE_FRAGMENT"
1173 | ],
1174 | "args": [
1175 | {
1176 | "name": "if",
1177 | "description": "Included when true.",
1178 | "type": {
1179 | "kind": "NON_NULL",
1180 | "name": null,
1181 | "ofType": {
1182 | "kind": "SCALAR",
1183 | "name": "Boolean",
1184 | "ofType": null
1185 | }
1186 | },
1187 | "defaultValue": null
1188 | }
1189 | ]
1190 | },
1191 | {
1192 | "name": "deprecated",
1193 | "description": "Marks an element of a GraphQL schema as no longer supported.",
1194 | "locations": [
1195 | "FIELD_DEFINITION",
1196 | "ENUM_VALUE"
1197 | ],
1198 | "args": [
1199 | {
1200 | "name": "reason",
1201 | "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).",
1202 | "type": {
1203 | "kind": "SCALAR",
1204 | "name": "String",
1205 | "ofType": null
1206 | },
1207 | "defaultValue": "\"No longer supported\""
1208 | }
1209 | ]
1210 | }
1211 | ]
1212 | }
1213 | }
1214 | }
--------------------------------------------------------------------------------