├── .gitignore
├── README.md
├── advanced
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .install
│ ├── index.js
│ ├── package.json
│ └── yarn.lock
├── README.md
├── package.json
├── public
│ ├── _redirects
│ ├── favicon.ico
│ └── index.html
├── server
│ ├── .env
│ ├── .gitignore
│ ├── package.json
│ ├── prisma
│ │ ├── datamodel.prisma
│ │ ├── prisma.yml
│ │ └── seed.graphql
│ ├── src
│ │ ├── generated
│ │ │ └── prisma-client
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── prisma-schema.js
│ │ ├── index.js
│ │ ├── resolvers
│ │ │ ├── Mutation
│ │ │ │ ├── auth.js
│ │ │ │ └── post.js
│ │ │ ├── Post.js
│ │ │ ├── Query.js
│ │ │ ├── Subscription.js
│ │ │ ├── User.js
│ │ │ └── index.js
│ │ ├── schema.graphql
│ │ └── utils.js
│ └── yarn.lock
├── src
│ ├── assets
│ │ ├── close.svg
│ │ └── plus.svg
│ ├── components
│ │ ├── CreatePage.js
│ │ ├── DetailPage.js
│ │ ├── DraftsPage.js
│ │ ├── FeedPage.js
│ │ ├── LoginPage.js
│ │ ├── LogoutPage.js
│ │ ├── PageNotFound.js
│ │ ├── Post.js
│ │ ├── RootContainer.js
│ │ └── SignupPage.js
│ ├── constant.js
│ ├── constants
│ │ └── modalStyle.js
│ ├── helper
│ │ └── jwtHelper.js
│ ├── index.css
│ └── index.js
└── yarn.lock
├── basic
├── .gitignore
├── .install
│ ├── index.js
│ ├── package.json
│ └── yarn.lock
├── LICENSE
├── README.md
├── package.json
├── public
│ ├── _redirects
│ ├── favicon.ico
│ └── index.html
├── server
│ ├── .gitignore
│ ├── package.json
│ ├── prisma
│ │ ├── datamodel.prisma
│ │ ├── prisma.yml
│ │ └── seed.graphql
│ ├── src
│ │ ├── generated
│ │ │ └── prisma-client
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── prisma-schema.js
│ │ ├── index.js
│ │ └── schema.graphql
│ └── yarn.lock
├── src
│ ├── assets
│ │ ├── close.svg
│ │ └── plus.svg
│ ├── components
│ │ ├── CreatePage.js
│ │ ├── DetailPage.js
│ │ ├── DraftsPage.js
│ │ ├── FeedPage.js
│ │ └── Post.js
│ ├── constants
│ │ └── modalStyle.js
│ ├── index.css
│ └── index.js
└── yarn.lock
├── minimal
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── server
│ ├── .gitignore
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── yarn.lock
├── src
│ ├── components
│ │ ├── App.js
│ │ └── InputName.js
│ ├── index.js
│ ├── logo.svg
│ └── styles
│ │ ├── App.css
│ │ └── index.css
└── yarn.lock
└── renovate.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 | .idea
5 | .netlify
6 | build
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Fullstack GraphQL Boilerplates for React & Node.js
2 |
3 |
4 |
5 | 
6 |
7 | Bootstrap your fullstack GraphQL app within seconds
8 | GraphQL boilerplates provide the perfect foundation for your GraphQL server, no matter if you're just getting started with GraphQL or aim to build a fully-fledged application.
9 |
10 |
11 |
12 | ## Deprecation note
13 |
14 | This repository has been deprecated and is currently unmaintained. You can find up-to-date examples for building GraphQL servers with a database [here](https://github.com/prisma/prisma-examples/).
15 |
16 | ## Features
17 |
18 | - **Rapid scaffolding**: Simply use `graphql create` (from the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli)) to download the boilerplate you want.
19 | - **Easily extensible**: A boilerplate only provides the minimum setup so you can tailor the API to your use case.
20 | - **Best practices**: Each boilerplate incorporates best practices from the GraphQL community.
21 |
22 | For a fully-fledged **React & Apollo tutorial**, visit [How to GraphQL](https://www.howtographql.com/react-apollo/0-introduction/). You can more learn about the idea behind GraphQL boilerplates [here](https://blog.graph.cool/graphql-boilerplates-graphql-create-how-to-setup-a-graphql-project-6428be2f3a5).
23 |
24 | ## Quickstart
25 |
26 | Select a boilerplate and follow the instructions in the belonging README to get started:
27 |
28 | - [`minimal`](./minimal): Minimal boilerplate with basic "Hello World" functionality
29 | - [`basic`](./basic): Basic boilerplate based on a simple data model and with a GraphQL database
30 | - [`advanced`](./advanced): Advanced boilerplate with a GraphQL database, authentication and realtime subscriptions
31 |
32 | All projects are based on [`graphql-yoga`](https://github.com/graphcool/graphql-yoga/) & [Apollo Client](https://github.com/apollographql/apollo-client).
33 |
34 | ## Contributing
35 |
36 | The GraphQL boilerplates are maintained by the GraphQL community, with official support from the [Apollo](https://dev-blog.apollodata.com) & [Graphcool](https://blog.graph.cool/) teams.
37 |
38 | Your feedback is **very helpful**, please share your opinion and thoughts! If you have any questions or want to contribute yourself, join the [`#graphql-boilerplate`](https://graphcool.slack.com/messages/graphql-boilerplate) channel on our [Slack](https://graphcool.slack.com/).
39 |
--------------------------------------------------------------------------------
/advanced/.editorconfig:
--------------------------------------------------------------------------------
1 |
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/advanced/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | scripts/
3 |
--------------------------------------------------------------------------------
/advanced/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "react-app",
3 | "rules": {
4 | "semi": ["error", "never"],
5 | "quotes": ["error", "single", { "allowTemplateLiterals": true }],
6 | "jsx-quotes": ["error", "prefer-double"],
7 | "no-extra-semi": 0,
8 | "no-console": 0
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/advanced/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/advanced/.install/index.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const {
3 | replaceInFiles,
4 | deploy,
5 | writeEnv,
6 | getInfo,
7 | makeSandboxEndpoint,
8 | } = require('graphql-boilerplate-install')
9 |
10 | module.exports = async ({ project, projectDir }) => {
11 | const templateName = 'graphql-boilerplate'
12 |
13 | const endpoint = await makeSandboxEndpoint(project)
14 | console.log(`Deployed Prisma to ${endpoint}.`)
15 |
16 | process.chdir('server/')
17 | replaceInFiles(
18 | ['src/index.js', 'package.json', 'prisma/prisma.yml'],
19 | templateName,
20 | project,
21 | )
22 | replaceInFiles(['prisma/prisma.yml'], '__PRISMA_ENDPOINT__', endpoint)
23 | console.log('Running $ prisma deploy...')
24 | await deploy(false)
25 |
26 | replaceInFiles(
27 | ['src/generated/prisma-client/index.js'],
28 | '__PRISMA_ENDPOINT__',
29 | endpoint,
30 | )
31 |
32 | fs.appendFileSync('.gitignore', '.env*\n')
33 |
34 | console.log(`\
35 | Next steps:
36 | 1. Change directory: \`cd ${projectDir}/server\`
37 | 2. Start local server: \`yarn start\` (you can now open a Playground at http://localhost:4000)
38 | 3. Change directory: \`cd ..\`
39 | 4. Start React app: \`yarn start\`
40 | 5. Open browser: http://localhost:3000
41 | `)
42 | }
43 |
--------------------------------------------------------------------------------
/advanced/.install/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "install",
3 | "version": "0.0.0",
4 | "devDependencies": {
5 | "graphql-boilerplate-install": "0.1.9"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/advanced/.install/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | commander@^2.9.0:
6 | version "2.14.1"
7 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
8 |
9 | cross-spawn@5.1.0, cross-spawn@^5.1.0:
10 | version "5.1.0"
11 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
12 | dependencies:
13 | lru-cache "^4.0.1"
14 | shebang-command "^1.2.0"
15 | which "^1.2.9"
16 |
17 | graphql-boilerplate-install@0.1.9:
18 | version "0.1.9"
19 | resolved "https://registry.yarnpkg.com/graphql-boilerplate-install/-/graphql-boilerplate-install-0.1.9.tgz#bcd7e8dbb2b685820e78a76a5dbb6f24fcadf2c8"
20 | dependencies:
21 | cross-spawn "5.1.0"
22 | node-fetch "^2.1.2"
23 | npm-run "4.1.2"
24 | sillyname "^0.1.0"
25 |
26 | isexe@^2.0.0:
27 | version "2.0.0"
28 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
29 |
30 | lru-cache@^4.0.1:
31 | version "4.1.1"
32 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
33 | dependencies:
34 | pseudomap "^1.0.2"
35 | yallist "^2.1.2"
36 |
37 | minimist@^1.2.0:
38 | version "1.2.0"
39 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
40 |
41 | node-fetch@^2.1.2:
42 | version "2.1.2"
43 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
44 |
45 | npm-path@^2.0.2, npm-path@^2.0.3:
46 | version "2.0.4"
47 | resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64"
48 | dependencies:
49 | which "^1.2.10"
50 |
51 | npm-run@4.1.2:
52 | version "4.1.2"
53 | resolved "https://registry.yarnpkg.com/npm-run/-/npm-run-4.1.2.tgz#1030e1ec56908c89fcc3fa366d03a2c2ba98eb99"
54 | dependencies:
55 | cross-spawn "^5.1.0"
56 | minimist "^1.2.0"
57 | npm-path "^2.0.3"
58 | npm-which "^3.0.1"
59 | serializerr "^1.0.3"
60 | sync-exec "^0.6.2"
61 |
62 | npm-which@^3.0.1:
63 | version "3.0.1"
64 | resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa"
65 | dependencies:
66 | commander "^2.9.0"
67 | npm-path "^2.0.2"
68 | which "^1.2.10"
69 |
70 | protochain@^1.0.5:
71 | version "1.0.5"
72 | resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260"
73 |
74 | pseudomap@^1.0.2:
75 | version "1.0.2"
76 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
77 |
78 | serializerr@^1.0.3:
79 | version "1.0.3"
80 | resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91"
81 | dependencies:
82 | protochain "^1.0.5"
83 |
84 | shebang-command@^1.2.0:
85 | version "1.2.0"
86 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
87 | dependencies:
88 | shebang-regex "^1.0.0"
89 |
90 | shebang-regex@^1.0.0:
91 | version "1.0.0"
92 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
93 |
94 | sillyname@^0.1.0:
95 | version "0.1.0"
96 | resolved "https://registry.yarnpkg.com/sillyname/-/sillyname-0.1.0.tgz#cfd98858e2498671347775efe3bb5141f46c87d6"
97 |
98 | sync-exec@^0.6.2:
99 | version "0.6.2"
100 | resolved "https://registry.yarnpkg.com/sync-exec/-/sync-exec-0.6.2.tgz#717d22cc53f0ce1def5594362f3a89a2ebb91105"
101 |
102 | which@^1.2.10, which@^1.2.9:
103 | version "1.3.0"
104 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
105 | dependencies:
106 | isexe "^2.0.0"
107 |
108 | yallist@^2.1.2:
109 | version "2.1.2"
110 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
111 |
--------------------------------------------------------------------------------
/advanced/README.md:
--------------------------------------------------------------------------------
1 | Boilerplate for a Advanced Fullstack GraphQL App with React
2 |
3 |
4 |
5 | 
6 |
7 | 🚀 Bootstrap your fullstack GraphQL app within seconds
8 | Advanced starter kit for a fullstack GraphQL app with React and Node.js - based on best practices from the GraphQL community.
9 |
10 | ## Features
11 |
12 | - **Scalable GraphQL server:** The server uses [`graphql-yoga`](https://github.com/prisma/graphql-yoga) which is based on Apollo Server & Express
13 | - **Pre-configured Apollo Client:** The project comes with a preconfigured setup for Apollo Client
14 | - **GraphQL database:** Includes GraphQL database binding to [Prisma](https://www.prismagraphql.com) (running on MySQL)
15 | - **Tooling**: Out-of-the-box support for [GraphQL Playground](https://github.com/prisma/graphql-playground) & [query performance tracing](https://github.com/apollographql/apollo-tracing)
16 | - **Extensible**: Simple and flexible [data model](./database/datamodel.graphql) – easy to adjust and extend
17 | - **No configuration overhead**: Preconfigured [`graphql-config`](https://github.com/prisma/graphql-config) setup
18 |
19 | For a fully-fledged **React & Apollo tutorial**, visit [How to GraphQL](https://www.howtographql.com/react-apollo/0-introduction/). You can more learn about the idea behind GraphQL boilerplates [here](https://blog.graph.cool/graphql-boilerplates-graphql-create-how-to-setup-a-graphql-project-6428be2f3a5).
20 |
21 | ## Requirements
22 |
23 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`:
24 |
25 | ```sh
26 | npm install -g graphql-cli
27 | ```
28 |
29 | ## Getting started
30 |
31 | ```sh
32 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `react-fullstack-advanced` boilerplate
33 | graphql create my-app --boilerplate react-fullstack-advanced
34 |
35 | # 2. When prompted, deploy the Prisma service to a _public cluster_
36 |
37 | # 3. Navigate into the `server` directory of the new project
38 | cd my-app/server
39 |
40 | # 4. Start the server
41 | yarn dev # runs server on http://localhost:4000, and opens GraphQL PLayground
42 |
43 | # 5. Open a new tab in the terminal and navigate back into my-app;
44 | # then run the app
45 | cd ..
46 | yarn start
47 | ```
48 |
49 | ## Documentation
50 |
51 | ### Commands
52 |
53 | * `yarn start` starts GraphQL server on `http://localhost:4000`
54 | * `yarn dev` starts GraphQL server on `http://localhost:4000` _and_ opens GraphQL Playground
55 | * `yarn playground` opens the GraphQL Playground for the `projects` from [`.graphqlconfig.yml`](./.graphqlconfig.yml)
56 | * `yarn prisma ` gives access to local version of Prisma CLI (e.g. `yarn prisma deploy`)
57 |
58 | > **Note**: We recommend that you're using `yarn dev` during development as it will give you access to the GraphQL API or your server (defined by the [application schema](./src/schema.graphql)) as well as to the Prisma API directly (defined by the [Prisma database schema](./generated/prisma.graphql)). If you're starting the server with `yarn start`, you'll only be able to access the API of the application schema.
59 |
60 | ### Server structure
61 |
62 | 
63 |
64 | | File name | Description |
65 | | :-- | :-- |
66 | | `├── .graphqlconfig.yml` | Configuration file based on [`graphql-config`](https://github.com/prisma/graphql-config) (e.g. used by GraphQL Playground).|
67 | | `└── database ` (_directory_) | _Contains all files that are related to the Prisma database service_ |\
68 | | ` ├── prisma.yml` | The root configuration file for your Prisma database service ([docs](https://www.prismagraphql.com/docs/reference/prisma.yml/overview-and-example-foatho8aip)) |
69 | | ` └── datamodel.graphql` | Defines your data model (written in [GraphQL SDL](https://blog.graph.cool/graphql-sdl-schema-definition-language-6755bcb9ce51)) |
70 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ |
71 | | ` ├── index.js` | The entry point for your GraphQL server |
72 | | ` ├── schema.graphql` | The **application schema** defining the API exposed to client applications |
73 | | ` └── generated` (_directory_) | _Contains generated files_ |
74 | | ` └── prisma.grapghql` | The **Prisma database schema** defining the Prisma GraphQL API |
75 |
76 | ## Contributing
77 |
78 | The GraphQL boilerplates are maintained by the GraphQL community, with official support from the [Apollo](https://dev-blog.apollodata.com) & [Graphcool](https://blog.graph.cool/) teams.
79 |
80 | Your feedback is **very helpful**, please share your opinion and thoughts! If you have any questions or want to contribute yourself, join the [`#graphql-boilerplate`](https://graphcool.slack.com/messages/graphql-boilerplate) channel on our [Slack](https://graphcool.slack.com/).
81 |
--------------------------------------------------------------------------------
/advanced/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-apollo-instagram-example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "devDependencies": {
6 | "babel-eslint": "7.2.3",
7 | "eslint": "4.19.1",
8 | "eslint-config-react-app": "2.1.0",
9 | "eslint-plugin-flowtype": "2.50.3",
10 | "eslint-plugin-import": "2.31.0",
11 | "eslint-plugin-jsx-a11y": "5.1.1",
12 | "eslint-plugin-react": "7.37.2",
13 | "jwt-decode": "2.2.0",
14 | "prettier-eslint-cli": "4.7.1",
15 | "react-scripts": "2.1.8"
16 | },
17 | "dependencies": {
18 | "apollo-boost": "0.4.9",
19 | "apollo-client": "2.6.10",
20 | "apollo-client-preset": "1.0.8",
21 | "apollo-link": "1.2.14",
22 | "apollo-link-ws": "1.0.20",
23 | "apollo-utilities": "1.3.4",
24 | "babel-cli": "6.26.0",
25 | "eslint-config-prettier": "2.10.0",
26 | "eslint-plugin-babel": "4.1.2",
27 | "eslint-plugin-prettier": "2.7.0",
28 | "graphql": "14.7.0",
29 | "graphql-tag": "2.12.6",
30 | "react": "16.14.0",
31 | "react-apollo": "2.5.8",
32 | "react-dom": "16.14.0",
33 | "react-modal": "3.16.1",
34 | "react-router-dom": "4.4.0-beta.8",
35 | "subscriptions-transport-ws": "0.11.0",
36 | "tachyons": "4.12.0"
37 | },
38 | "scripts": {
39 | "precommit": "yarn run lint && yarn run flow",
40 | "flow": "flow",
41 | "lint": "eslint .",
42 | "start": "react-scripts start",
43 | "build": "react-scripts build",
44 | "test": "react-scripts test --env=jsdom",
45 | "eject": "react-scripts eject",
46 | "prettier": "prettier-eslint --write \"src/**/*.+(js|jsx)\"",
47 | "prettier-dry-run": "prettier-eslint \"src/**/*.+(js|jsx)\" -l debug"
48 | },
49 | "prettier": {
50 | "semi": false,
51 | "singleQuote": true,
52 | "trailingComma": "all"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/advanced/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/advanced/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphql-boilerplates/react-fullstack-graphql/2c4bb39e51fc142acff6041f49901bced9ff9a94/advanced/public/favicon.ico
--------------------------------------------------------------------------------
/advanced/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Advanced React Boilerplate
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/advanced/server/.env:
--------------------------------------------------------------------------------
1 | PRISMA_SECRET="mysecret123"
2 | APP_SECRET="jwtsecret123"
--------------------------------------------------------------------------------
/advanced/server/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | package-lock.json
3 | node_modules
4 | .idea
5 | .vscode
6 | *.log
7 | yarn.lock
8 |
--------------------------------------------------------------------------------
/advanced/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-boilerplate",
3 | "scripts": {
4 | "start": "nodemon -e js,graphql -x node -r dotenv/config src/index.js",
5 | "debug": "nodemon -e js,graphql -x node --inspect -r dotenv/config src/index.js",
6 | "nodemon": "nodemon"
7 | },
8 | "dependencies": {
9 | "bcryptjs": "2.4.3",
10 | "graphql-yoga": "1.18.3",
11 | "jsonwebtoken": "8.5.1",
12 | "prisma-client-lib": "1.34.12"
13 | },
14 | "devDependencies": {
15 | "dotenv": "6.2.0",
16 | "nodemon": "1.19.4",
17 | "prisma": "1.22.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/advanced/server/prisma/datamodel.prisma:
--------------------------------------------------------------------------------
1 | type Post {
2 | id: ID! @id
3 | createdAt: DateTime! @createdAt
4 | updatedAt: DateTime! @updatedAt
5 | published: Boolean! @default(value: false)
6 | title: String!
7 | content: String!
8 | author: User!
9 | }
10 |
11 | type User {
12 | id: ID! @id
13 | email: String! @unique
14 | password: String!
15 | name: String!
16 | posts: [Post!]!
17 | }
--------------------------------------------------------------------------------
/advanced/server/prisma/prisma.yml:
--------------------------------------------------------------------------------
1 | # Specifies the HTTP endpoint of your Prisma API (deployed to a Prisma Demo server).
2 | endpoint: __PRISMA_ENDPOINT__
3 |
4 | # Defines your models, each model is mapped to the database as a table.
5 | datamodel: datamodel.prisma
6 |
7 | # Specifies the language and directory for the generated Prisma client.
8 | generate:
9 | - generator: javascript-client
10 | output: ../src/generated/prisma-client
11 |
12 | # Seed your service with initial data based on `seed.graphql`.
13 | seed:
14 | import: seed.graphql
15 |
16 | # Ensures Prisma client is re-generated after a datamodel change.
17 | hooks:
18 | post-deploy:
19 | - prisma generate
20 |
21 | # If specified, the `secret` must be used to generate a JWT which is attached
22 | # to the `Authorization` header of HTTP requests made against the Prisma API.
23 | # Info: https://www.prisma.io/docs/reference/prisma-api/concepts-utee3eiquo#authentication
24 | # secret: ${env:PRISMA_SECRET}
25 |
--------------------------------------------------------------------------------
/advanced/server/prisma/seed.graphql:
--------------------------------------------------------------------------------
1 |
2 | mutation {
3 | user1: createUser(data: {
4 | email: "alice@prisma.io"
5 | name: "Alice"
6 | password: "$2b$10$dqyYw5XovLjpmkYNiRDEWuwKaRAvLaG45fnXE5b3KTccKZcRPka2m" # "secret42"
7 | posts: {
8 | create: {
9 | title: "Join us for GraphQL Conf 2019 in Berlin"
10 | content: "https://www.graphqlconf.org/"
11 | published: true
12 | }
13 | }
14 | }) {
15 | id
16 | }
17 |
18 | user2: createUser(data: {
19 | email: "bob@prisma.io"
20 | name: "Bob"
21 | password: "$2b$10$o6KioO.taArzboM44Ig85O3ZFZYZpR3XD7mI8T29eP4znU/.xyJbW" # "secret43"
22 | posts: {
23 | create: [{
24 | title: "Subscribe to GraphQL Weekly for community news"
25 | content: "https://graphqlweekly.com/"
26 | published: true
27 | } {
28 | title: "Follow Prisma on Twitter"
29 | content: "https://twitter.com/prisma"
30 | }]
31 | }
32 | }) {
33 | id
34 | }
35 | }
--------------------------------------------------------------------------------
/advanced/server/src/generated/prisma-client/index.d.ts:
--------------------------------------------------------------------------------
1 | // Code generated by Prisma (prisma@1.22.1). DO NOT EDIT.
2 | // Please don't change this file manually but run `prisma generate` to update it.
3 | // For more information, please read the docs: https://www.prisma.io/docs/prisma-client/
4 |
5 | import { DocumentNode, GraphQLSchema } from "graphql";
6 | import { makePrismaClientClass, BaseClientOptions } from "prisma-client-lib";
7 | import { typeDefs } from "./prisma-schema";
8 |
9 | type AtLeastOne }> = Partial &
10 | U[keyof U];
11 |
12 | export interface Exists {
13 | post: (where?: PostWhereInput) => Promise;
14 | user: (where?: UserWhereInput) => Promise;
15 | }
16 |
17 | export interface Node {}
18 |
19 | export type FragmentableArray = Promise> & Fragmentable;
20 |
21 | export interface Fragmentable {
22 | $fragment(fragment: string | DocumentNode): Promise;
23 | }
24 |
25 | export interface Prisma {
26 | $exists: Exists;
27 | $graphql: (
28 | query: string,
29 | variables?: { [key: string]: any }
30 | ) => Promise;
31 |
32 | /**
33 | * Queries
34 | */
35 |
36 | post: (where: PostWhereUniqueInput) => PostPromise;
37 | posts: (
38 | args?: {
39 | where?: PostWhereInput;
40 | orderBy?: PostOrderByInput;
41 | skip?: Int;
42 | after?: String;
43 | before?: String;
44 | first?: Int;
45 | last?: Int;
46 | }
47 | ) => FragmentableArray;
48 | postsConnection: (
49 | args?: {
50 | where?: PostWhereInput;
51 | orderBy?: PostOrderByInput;
52 | skip?: Int;
53 | after?: String;
54 | before?: String;
55 | first?: Int;
56 | last?: Int;
57 | }
58 | ) => PostConnectionPromise;
59 | user: (where: UserWhereUniqueInput) => UserPromise;
60 | users: (
61 | args?: {
62 | where?: UserWhereInput;
63 | orderBy?: UserOrderByInput;
64 | skip?: Int;
65 | after?: String;
66 | before?: String;
67 | first?: Int;
68 | last?: Int;
69 | }
70 | ) => FragmentableArray;
71 | usersConnection: (
72 | args?: {
73 | where?: UserWhereInput;
74 | orderBy?: UserOrderByInput;
75 | skip?: Int;
76 | after?: String;
77 | before?: String;
78 | first?: Int;
79 | last?: Int;
80 | }
81 | ) => UserConnectionPromise;
82 | node: (args: { id: ID_Output }) => Node;
83 |
84 | /**
85 | * Mutations
86 | */
87 |
88 | createPost: (data: PostCreateInput) => PostPromise;
89 | updatePost: (
90 | args: { data: PostUpdateInput; where: PostWhereUniqueInput }
91 | ) => PostPromise;
92 | updateManyPosts: (
93 | args: { data: PostUpdateManyMutationInput; where?: PostWhereInput }
94 | ) => BatchPayloadPromise;
95 | upsertPost: (
96 | args: {
97 | where: PostWhereUniqueInput;
98 | create: PostCreateInput;
99 | update: PostUpdateInput;
100 | }
101 | ) => PostPromise;
102 | deletePost: (where: PostWhereUniqueInput) => PostPromise;
103 | deleteManyPosts: (where?: PostWhereInput) => BatchPayloadPromise;
104 | createUser: (data: UserCreateInput) => UserPromise;
105 | updateUser: (
106 | args: { data: UserUpdateInput; where: UserWhereUniqueInput }
107 | ) => UserPromise;
108 | updateManyUsers: (
109 | args: { data: UserUpdateManyMutationInput; where?: UserWhereInput }
110 | ) => BatchPayloadPromise;
111 | upsertUser: (
112 | args: {
113 | where: UserWhereUniqueInput;
114 | create: UserCreateInput;
115 | update: UserUpdateInput;
116 | }
117 | ) => UserPromise;
118 | deleteUser: (where: UserWhereUniqueInput) => UserPromise;
119 | deleteManyUsers: (where?: UserWhereInput) => BatchPayloadPromise;
120 |
121 | /**
122 | * Subscriptions
123 | */
124 |
125 | $subscribe: Subscription;
126 | }
127 |
128 | export interface Subscription {
129 | post: (
130 | where?: PostSubscriptionWhereInput
131 | ) => PostSubscriptionPayloadSubscription;
132 | user: (
133 | where?: UserSubscriptionWhereInput
134 | ) => UserSubscriptionPayloadSubscription;
135 | }
136 |
137 | export interface ClientConstructor {
138 | new (options?: BaseClientOptions): T;
139 | }
140 |
141 | /**
142 | * Types
143 | */
144 |
145 | export type PostOrderByInput =
146 | | "id_ASC"
147 | | "id_DESC"
148 | | "createdAt_ASC"
149 | | "createdAt_DESC"
150 | | "updatedAt_ASC"
151 | | "updatedAt_DESC"
152 | | "published_ASC"
153 | | "published_DESC"
154 | | "title_ASC"
155 | | "title_DESC"
156 | | "content_ASC"
157 | | "content_DESC";
158 |
159 | export type UserOrderByInput =
160 | | "id_ASC"
161 | | "id_DESC"
162 | | "email_ASC"
163 | | "email_DESC"
164 | | "password_ASC"
165 | | "password_DESC"
166 | | "name_ASC"
167 | | "name_DESC"
168 | | "createdAt_ASC"
169 | | "createdAt_DESC"
170 | | "updatedAt_ASC"
171 | | "updatedAt_DESC";
172 |
173 | export type MutationType = "CREATED" | "UPDATED" | "DELETED";
174 |
175 | export interface UserUpdateOneRequiredWithoutPostsInput {
176 | create?: UserCreateWithoutPostsInput;
177 | update?: UserUpdateWithoutPostsDataInput;
178 | upsert?: UserUpsertWithoutPostsInput;
179 | connect?: UserWhereUniqueInput;
180 | }
181 |
182 | export type PostWhereUniqueInput = AtLeastOne<{
183 | id: ID_Input;
184 | }>;
185 |
186 | export interface PostUpdateWithWhereUniqueWithoutAuthorInput {
187 | where: PostWhereUniqueInput;
188 | data: PostUpdateWithoutAuthorDataInput;
189 | }
190 |
191 | export interface UserCreateInput {
192 | email: String;
193 | password: String;
194 | name: String;
195 | posts?: PostCreateManyWithoutAuthorInput;
196 | }
197 |
198 | export interface PostUpdateManyWithoutAuthorInput {
199 | create?: PostCreateWithoutAuthorInput[] | PostCreateWithoutAuthorInput;
200 | delete?: PostWhereUniqueInput[] | PostWhereUniqueInput;
201 | connect?: PostWhereUniqueInput[] | PostWhereUniqueInput;
202 | disconnect?: PostWhereUniqueInput[] | PostWhereUniqueInput;
203 | update?:
204 | | PostUpdateWithWhereUniqueWithoutAuthorInput[]
205 | | PostUpdateWithWhereUniqueWithoutAuthorInput;
206 | upsert?:
207 | | PostUpsertWithWhereUniqueWithoutAuthorInput[]
208 | | PostUpsertWithWhereUniqueWithoutAuthorInput;
209 | deleteMany?: PostScalarWhereInput[] | PostScalarWhereInput;
210 | updateMany?:
211 | | PostUpdateManyWithWhereNestedInput[]
212 | | PostUpdateManyWithWhereNestedInput;
213 | }
214 |
215 | export interface UserUpsertWithoutPostsInput {
216 | update: UserUpdateWithoutPostsDataInput;
217 | create: UserCreateWithoutPostsInput;
218 | }
219 |
220 | export interface UserWhereInput {
221 | id?: ID_Input;
222 | id_not?: ID_Input;
223 | id_in?: ID_Input[] | ID_Input;
224 | id_not_in?: ID_Input[] | ID_Input;
225 | id_lt?: ID_Input;
226 | id_lte?: ID_Input;
227 | id_gt?: ID_Input;
228 | id_gte?: ID_Input;
229 | id_contains?: ID_Input;
230 | id_not_contains?: ID_Input;
231 | id_starts_with?: ID_Input;
232 | id_not_starts_with?: ID_Input;
233 | id_ends_with?: ID_Input;
234 | id_not_ends_with?: ID_Input;
235 | email?: String;
236 | email_not?: String;
237 | email_in?: String[] | String;
238 | email_not_in?: String[] | String;
239 | email_lt?: String;
240 | email_lte?: String;
241 | email_gt?: String;
242 | email_gte?: String;
243 | email_contains?: String;
244 | email_not_contains?: String;
245 | email_starts_with?: String;
246 | email_not_starts_with?: String;
247 | email_ends_with?: String;
248 | email_not_ends_with?: String;
249 | password?: String;
250 | password_not?: String;
251 | password_in?: String[] | String;
252 | password_not_in?: String[] | String;
253 | password_lt?: String;
254 | password_lte?: String;
255 | password_gt?: String;
256 | password_gte?: String;
257 | password_contains?: String;
258 | password_not_contains?: String;
259 | password_starts_with?: String;
260 | password_not_starts_with?: String;
261 | password_ends_with?: String;
262 | password_not_ends_with?: String;
263 | name?: String;
264 | name_not?: String;
265 | name_in?: String[] | String;
266 | name_not_in?: String[] | String;
267 | name_lt?: String;
268 | name_lte?: String;
269 | name_gt?: String;
270 | name_gte?: String;
271 | name_contains?: String;
272 | name_not_contains?: String;
273 | name_starts_with?: String;
274 | name_not_starts_with?: String;
275 | name_ends_with?: String;
276 | name_not_ends_with?: String;
277 | posts_every?: PostWhereInput;
278 | posts_some?: PostWhereInput;
279 | posts_none?: PostWhereInput;
280 | AND?: UserWhereInput[] | UserWhereInput;
281 | OR?: UserWhereInput[] | UserWhereInput;
282 | NOT?: UserWhereInput[] | UserWhereInput;
283 | }
284 |
285 | export interface PostSubscriptionWhereInput {
286 | mutation_in?: MutationType[] | MutationType;
287 | updatedFields_contains?: String;
288 | updatedFields_contains_every?: String[] | String;
289 | updatedFields_contains_some?: String[] | String;
290 | node?: PostWhereInput;
291 | AND?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
292 | OR?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
293 | NOT?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
294 | }
295 |
296 | export interface PostCreateInput {
297 | published?: Boolean;
298 | title: String;
299 | content: String;
300 | author: UserCreateOneWithoutPostsInput;
301 | }
302 |
303 | export interface PostUpdateManyDataInput {
304 | published?: Boolean;
305 | title?: String;
306 | content?: String;
307 | }
308 |
309 | export interface UserCreateOneWithoutPostsInput {
310 | create?: UserCreateWithoutPostsInput;
311 | connect?: UserWhereUniqueInput;
312 | }
313 |
314 | export interface PostScalarWhereInput {
315 | id?: ID_Input;
316 | id_not?: ID_Input;
317 | id_in?: ID_Input[] | ID_Input;
318 | id_not_in?: ID_Input[] | ID_Input;
319 | id_lt?: ID_Input;
320 | id_lte?: ID_Input;
321 | id_gt?: ID_Input;
322 | id_gte?: ID_Input;
323 | id_contains?: ID_Input;
324 | id_not_contains?: ID_Input;
325 | id_starts_with?: ID_Input;
326 | id_not_starts_with?: ID_Input;
327 | id_ends_with?: ID_Input;
328 | id_not_ends_with?: ID_Input;
329 | createdAt?: DateTimeInput;
330 | createdAt_not?: DateTimeInput;
331 | createdAt_in?: DateTimeInput[] | DateTimeInput;
332 | createdAt_not_in?: DateTimeInput[] | DateTimeInput;
333 | createdAt_lt?: DateTimeInput;
334 | createdAt_lte?: DateTimeInput;
335 | createdAt_gt?: DateTimeInput;
336 | createdAt_gte?: DateTimeInput;
337 | updatedAt?: DateTimeInput;
338 | updatedAt_not?: DateTimeInput;
339 | updatedAt_in?: DateTimeInput[] | DateTimeInput;
340 | updatedAt_not_in?: DateTimeInput[] | DateTimeInput;
341 | updatedAt_lt?: DateTimeInput;
342 | updatedAt_lte?: DateTimeInput;
343 | updatedAt_gt?: DateTimeInput;
344 | updatedAt_gte?: DateTimeInput;
345 | published?: Boolean;
346 | published_not?: Boolean;
347 | title?: String;
348 | title_not?: String;
349 | title_in?: String[] | String;
350 | title_not_in?: String[] | String;
351 | title_lt?: String;
352 | title_lte?: String;
353 | title_gt?: String;
354 | title_gte?: String;
355 | title_contains?: String;
356 | title_not_contains?: String;
357 | title_starts_with?: String;
358 | title_not_starts_with?: String;
359 | title_ends_with?: String;
360 | title_not_ends_with?: String;
361 | content?: String;
362 | content_not?: String;
363 | content_in?: String[] | String;
364 | content_not_in?: String[] | String;
365 | content_lt?: String;
366 | content_lte?: String;
367 | content_gt?: String;
368 | content_gte?: String;
369 | content_contains?: String;
370 | content_not_contains?: String;
371 | content_starts_with?: String;
372 | content_not_starts_with?: String;
373 | content_ends_with?: String;
374 | content_not_ends_with?: String;
375 | AND?: PostScalarWhereInput[] | PostScalarWhereInput;
376 | OR?: PostScalarWhereInput[] | PostScalarWhereInput;
377 | NOT?: PostScalarWhereInput[] | PostScalarWhereInput;
378 | }
379 |
380 | export interface UserCreateWithoutPostsInput {
381 | email: String;
382 | password: String;
383 | name: String;
384 | }
385 |
386 | export interface PostUpsertWithWhereUniqueWithoutAuthorInput {
387 | where: PostWhereUniqueInput;
388 | update: PostUpdateWithoutAuthorDataInput;
389 | create: PostCreateWithoutAuthorInput;
390 | }
391 |
392 | export interface PostUpdateInput {
393 | published?: Boolean;
394 | title?: String;
395 | content?: String;
396 | author?: UserUpdateOneRequiredWithoutPostsInput;
397 | }
398 |
399 | export interface PostWhereInput {
400 | id?: ID_Input;
401 | id_not?: ID_Input;
402 | id_in?: ID_Input[] | ID_Input;
403 | id_not_in?: ID_Input[] | ID_Input;
404 | id_lt?: ID_Input;
405 | id_lte?: ID_Input;
406 | id_gt?: ID_Input;
407 | id_gte?: ID_Input;
408 | id_contains?: ID_Input;
409 | id_not_contains?: ID_Input;
410 | id_starts_with?: ID_Input;
411 | id_not_starts_with?: ID_Input;
412 | id_ends_with?: ID_Input;
413 | id_not_ends_with?: ID_Input;
414 | createdAt?: DateTimeInput;
415 | createdAt_not?: DateTimeInput;
416 | createdAt_in?: DateTimeInput[] | DateTimeInput;
417 | createdAt_not_in?: DateTimeInput[] | DateTimeInput;
418 | createdAt_lt?: DateTimeInput;
419 | createdAt_lte?: DateTimeInput;
420 | createdAt_gt?: DateTimeInput;
421 | createdAt_gte?: DateTimeInput;
422 | updatedAt?: DateTimeInput;
423 | updatedAt_not?: DateTimeInput;
424 | updatedAt_in?: DateTimeInput[] | DateTimeInput;
425 | updatedAt_not_in?: DateTimeInput[] | DateTimeInput;
426 | updatedAt_lt?: DateTimeInput;
427 | updatedAt_lte?: DateTimeInput;
428 | updatedAt_gt?: DateTimeInput;
429 | updatedAt_gte?: DateTimeInput;
430 | published?: Boolean;
431 | published_not?: Boolean;
432 | title?: String;
433 | title_not?: String;
434 | title_in?: String[] | String;
435 | title_not_in?: String[] | String;
436 | title_lt?: String;
437 | title_lte?: String;
438 | title_gt?: String;
439 | title_gte?: String;
440 | title_contains?: String;
441 | title_not_contains?: String;
442 | title_starts_with?: String;
443 | title_not_starts_with?: String;
444 | title_ends_with?: String;
445 | title_not_ends_with?: String;
446 | content?: String;
447 | content_not?: String;
448 | content_in?: String[] | String;
449 | content_not_in?: String[] | String;
450 | content_lt?: String;
451 | content_lte?: String;
452 | content_gt?: String;
453 | content_gte?: String;
454 | content_contains?: String;
455 | content_not_contains?: String;
456 | content_starts_with?: String;
457 | content_not_starts_with?: String;
458 | content_ends_with?: String;
459 | content_not_ends_with?: String;
460 | author?: UserWhereInput;
461 | AND?: PostWhereInput[] | PostWhereInput;
462 | OR?: PostWhereInput[] | PostWhereInput;
463 | NOT?: PostWhereInput[] | PostWhereInput;
464 | }
465 |
466 | export interface UserUpdateInput {
467 | email?: String;
468 | password?: String;
469 | name?: String;
470 | posts?: PostUpdateManyWithoutAuthorInput;
471 | }
472 |
473 | export interface UserUpdateManyMutationInput {
474 | email?: String;
475 | password?: String;
476 | name?: String;
477 | }
478 |
479 | export interface PostCreateManyWithoutAuthorInput {
480 | create?: PostCreateWithoutAuthorInput[] | PostCreateWithoutAuthorInput;
481 | connect?: PostWhereUniqueInput[] | PostWhereUniqueInput;
482 | }
483 |
484 | export interface PostUpdateManyMutationInput {
485 | published?: Boolean;
486 | title?: String;
487 | content?: String;
488 | }
489 |
490 | export interface PostCreateWithoutAuthorInput {
491 | published?: Boolean;
492 | title: String;
493 | content: String;
494 | }
495 |
496 | export interface UserUpdateWithoutPostsDataInput {
497 | email?: String;
498 | password?: String;
499 | name?: String;
500 | }
501 |
502 | export interface PostUpdateManyWithWhereNestedInput {
503 | where: PostScalarWhereInput;
504 | data: PostUpdateManyDataInput;
505 | }
506 |
507 | export interface UserSubscriptionWhereInput {
508 | mutation_in?: MutationType[] | MutationType;
509 | updatedFields_contains?: String;
510 | updatedFields_contains_every?: String[] | String;
511 | updatedFields_contains_some?: String[] | String;
512 | node?: UserWhereInput;
513 | AND?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
514 | OR?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
515 | NOT?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
516 | }
517 |
518 | export interface PostUpdateWithoutAuthorDataInput {
519 | published?: Boolean;
520 | title?: String;
521 | content?: String;
522 | }
523 |
524 | export type UserWhereUniqueInput = AtLeastOne<{
525 | id: ID_Input;
526 | email?: String;
527 | }>;
528 |
529 | export interface NodeNode {
530 | id: ID_Output;
531 | }
532 |
533 | export interface UserPreviousValues {
534 | id: ID_Output;
535 | email: String;
536 | password: String;
537 | name: String;
538 | }
539 |
540 | export interface UserPreviousValuesPromise
541 | extends Promise,
542 | Fragmentable {
543 | id: () => Promise;
544 | email: () => Promise;
545 | password: () => Promise;
546 | name: () => Promise;
547 | }
548 |
549 | export interface UserPreviousValuesSubscription
550 | extends Promise>,
551 | Fragmentable {
552 | id: () => Promise>;
553 | email: () => Promise>;
554 | password: () => Promise>;
555 | name: () => Promise>;
556 | }
557 |
558 | export interface PostPreviousValues {
559 | id: ID_Output;
560 | createdAt: DateTimeOutput;
561 | updatedAt: DateTimeOutput;
562 | published: Boolean;
563 | title: String;
564 | content: String;
565 | }
566 |
567 | export interface PostPreviousValuesPromise
568 | extends Promise,
569 | Fragmentable {
570 | id: () => Promise;
571 | createdAt: () => Promise;
572 | updatedAt: () => Promise;
573 | published: () => Promise;
574 | title: () => Promise;
575 | content: () => Promise;
576 | }
577 |
578 | export interface PostPreviousValuesSubscription
579 | extends Promise>,
580 | Fragmentable {
581 | id: () => Promise>;
582 | createdAt: () => Promise>;
583 | updatedAt: () => Promise>;
584 | published: () => Promise>;
585 | title: () => Promise>;
586 | content: () => Promise>;
587 | }
588 |
589 | export interface Post {
590 | id: ID_Output;
591 | createdAt: DateTimeOutput;
592 | updatedAt: DateTimeOutput;
593 | published: Boolean;
594 | title: String;
595 | content: String;
596 | }
597 |
598 | export interface PostPromise extends Promise, Fragmentable {
599 | id: () => Promise;
600 | createdAt: () => Promise;
601 | updatedAt: () => Promise;
602 | published: () => Promise;
603 | title: () => Promise;
604 | content: () => Promise;
605 | author: () => T;
606 | }
607 |
608 | export interface PostSubscription
609 | extends Promise>,
610 | Fragmentable {
611 | id: () => Promise>;
612 | createdAt: () => Promise>;
613 | updatedAt: () => Promise>;
614 | published: () => Promise>;
615 | title: () => Promise>;
616 | content: () => Promise>;
617 | author: () => T;
618 | }
619 |
620 | export interface AggregatePost {
621 | count: Int;
622 | }
623 |
624 | export interface AggregatePostPromise
625 | extends Promise,
626 | Fragmentable {
627 | count: () => Promise;
628 | }
629 |
630 | export interface AggregatePostSubscription
631 | extends Promise>,
632 | Fragmentable {
633 | count: () => Promise>;
634 | }
635 |
636 | export interface PostEdge {
637 | cursor: String;
638 | }
639 |
640 | export interface PostEdgePromise extends Promise, Fragmentable {
641 | node: () => T;
642 | cursor: () => Promise;
643 | }
644 |
645 | export interface PostEdgeSubscription
646 | extends Promise>,
647 | Fragmentable {
648 | node: () => T;
649 | cursor: () => Promise>;
650 | }
651 |
652 | export interface UserSubscriptionPayload {
653 | mutation: MutationType;
654 | updatedFields?: String[];
655 | }
656 |
657 | export interface UserSubscriptionPayloadPromise
658 | extends Promise,
659 | Fragmentable {
660 | mutation: () => Promise;
661 | node: () => T;
662 | updatedFields: () => Promise;
663 | previousValues: () => T;
664 | }
665 |
666 | export interface UserSubscriptionPayloadSubscription
667 | extends Promise>,
668 | Fragmentable {
669 | mutation: () => Promise>;
670 | node: () => T;
671 | updatedFields: () => Promise>;
672 | previousValues: () => T;
673 | }
674 |
675 | export interface PostSubscriptionPayload {
676 | mutation: MutationType;
677 | updatedFields?: String[];
678 | }
679 |
680 | export interface PostSubscriptionPayloadPromise
681 | extends Promise,
682 | Fragmentable {
683 | mutation: () => Promise;
684 | node: () => T;
685 | updatedFields: () => Promise;
686 | previousValues: () => T;
687 | }
688 |
689 | export interface PostSubscriptionPayloadSubscription
690 | extends Promise>,
691 | Fragmentable {
692 | mutation: () => Promise>;
693 | node: () => T;
694 | updatedFields: () => Promise>;
695 | previousValues: () => T;
696 | }
697 |
698 | export interface PostConnection {}
699 |
700 | export interface PostConnectionPromise
701 | extends Promise,
702 | Fragmentable {
703 | pageInfo: () => T;
704 | edges: >() => T;
705 | aggregate: () => T;
706 | }
707 |
708 | export interface PostConnectionSubscription
709 | extends Promise>,
710 | Fragmentable {
711 | pageInfo: () => T;
712 | edges: >>() => T;
713 | aggregate: () => T;
714 | }
715 |
716 | export interface PageInfo {
717 | hasNextPage: Boolean;
718 | hasPreviousPage: Boolean;
719 | startCursor?: String;
720 | endCursor?: String;
721 | }
722 |
723 | export interface PageInfoPromise extends Promise, Fragmentable {
724 | hasNextPage: () => Promise;
725 | hasPreviousPage: () => Promise;
726 | startCursor: () => Promise;
727 | endCursor: () => Promise;
728 | }
729 |
730 | export interface PageInfoSubscription
731 | extends Promise>,
732 | Fragmentable {
733 | hasNextPage: () => Promise>;
734 | hasPreviousPage: () => Promise>;
735 | startCursor: () => Promise>;
736 | endCursor: () => Promise>;
737 | }
738 |
739 | export interface BatchPayload {
740 | count: Long;
741 | }
742 |
743 | export interface BatchPayloadPromise
744 | extends Promise,
745 | Fragmentable {
746 | count: () => Promise;
747 | }
748 |
749 | export interface BatchPayloadSubscription
750 | extends Promise>,
751 | Fragmentable {
752 | count: () => Promise>;
753 | }
754 |
755 | export interface AggregateUser {
756 | count: Int;
757 | }
758 |
759 | export interface AggregateUserPromise
760 | extends Promise,
761 | Fragmentable {
762 | count: () => Promise;
763 | }
764 |
765 | export interface AggregateUserSubscription
766 | extends Promise>,
767 | Fragmentable {
768 | count: () => Promise>;
769 | }
770 |
771 | export interface User {
772 | id: ID_Output;
773 | email: String;
774 | password: String;
775 | name: String;
776 | }
777 |
778 | export interface UserPromise extends Promise, Fragmentable {
779 | id: () => Promise;
780 | email: () => Promise;
781 | password: () => Promise;
782 | name: () => Promise;
783 | posts: >(
784 | args?: {
785 | where?: PostWhereInput;
786 | orderBy?: PostOrderByInput;
787 | skip?: Int;
788 | after?: String;
789 | before?: String;
790 | first?: Int;
791 | last?: Int;
792 | }
793 | ) => T;
794 | }
795 |
796 | export interface UserSubscription
797 | extends Promise>,
798 | Fragmentable {
799 | id: () => Promise>;
800 | email: () => Promise>;
801 | password: () => Promise>;
802 | name: () => Promise>;
803 | posts: >>(
804 | args?: {
805 | where?: PostWhereInput;
806 | orderBy?: PostOrderByInput;
807 | skip?: Int;
808 | after?: String;
809 | before?: String;
810 | first?: Int;
811 | last?: Int;
812 | }
813 | ) => T;
814 | }
815 |
816 | export interface UserConnection {}
817 |
818 | export interface UserConnectionPromise
819 | extends Promise,
820 | Fragmentable {
821 | pageInfo: () => T;
822 | edges: >() => T;
823 | aggregate: () => T;
824 | }
825 |
826 | export interface UserConnectionSubscription
827 | extends Promise>,
828 | Fragmentable {
829 | pageInfo: () => T;
830 | edges: >>() => T;
831 | aggregate: () => T;
832 | }
833 |
834 | export interface UserEdge {
835 | cursor: String;
836 | }
837 |
838 | export interface UserEdgePromise extends Promise, Fragmentable {
839 | node: () => T;
840 | cursor: () => Promise;
841 | }
842 |
843 | export interface UserEdgeSubscription
844 | extends Promise>,
845 | Fragmentable {
846 | node: () => T;
847 | cursor: () => Promise>;
848 | }
849 |
850 | /*
851 | 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.
852 | */
853 | export type String = string;
854 |
855 | export type Long = string;
856 |
857 | /*
858 | 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.
859 | */
860 | export type ID_Input = string | number;
861 | export type ID_Output = string;
862 |
863 | /*
864 | The `Boolean` scalar type represents `true` or `false`.
865 | */
866 | export type Boolean = boolean;
867 |
868 | /*
869 | DateTime scalar input type, allowing Date
870 | */
871 | export type DateTimeInput = Date | string;
872 |
873 | /*
874 | DateTime scalar output type, which is always a string
875 | */
876 | export type DateTimeOutput = string;
877 |
878 | /*
879 | The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
880 | */
881 | export type Int = number;
882 |
883 | /**
884 | * Model Metadata
885 | */
886 |
887 | export const models = [
888 | {
889 | name: "Post",
890 | embedded: false
891 | },
892 | {
893 | name: "User",
894 | embedded: false
895 | }
896 | ];
897 |
898 | /**
899 | * Type Defs
900 | */
901 |
902 | export const prisma: Prisma;
903 |
--------------------------------------------------------------------------------
/advanced/server/src/generated/prisma-client/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var prisma_lib_1 = require("prisma-client-lib");
4 | var typeDefs = require("./prisma-schema").typeDefs;
5 |
6 | var models = [
7 | {
8 | name: "Post",
9 | embedded: false
10 | },
11 | {
12 | name: "User",
13 | embedded: false
14 | }
15 | ];
16 | exports.Prisma = prisma_lib_1.makePrismaClientClass({
17 | typeDefs,
18 | models,
19 | endpoint: `__PRISMA_ENDPOINT__`
20 | });
21 | exports.prisma = new exports.Prisma();
22 | var models = [
23 | {
24 | name: "Post",
25 | embedded: false
26 | },
27 | {
28 | name: "User",
29 | embedded: false
30 | }
31 | ];
32 |
--------------------------------------------------------------------------------
/advanced/server/src/generated/prisma-client/prisma-schema.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | typeDefs: /* GraphQL */ `type AggregatePost {
3 | count: Int!
4 | }
5 |
6 | type AggregateUser {
7 | count: Int!
8 | }
9 |
10 | type BatchPayload {
11 | count: Long!
12 | }
13 |
14 | scalar DateTime
15 |
16 | scalar Long
17 |
18 | type Mutation {
19 | createPost(data: PostCreateInput!): Post!
20 | updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
21 | updateManyPosts(data: PostUpdateManyMutationInput!, where: PostWhereInput): BatchPayload!
22 | upsertPost(where: PostWhereUniqueInput!, create: PostCreateInput!, update: PostUpdateInput!): Post!
23 | deletePost(where: PostWhereUniqueInput!): Post
24 | deleteManyPosts(where: PostWhereInput): BatchPayload!
25 | createUser(data: UserCreateInput!): User!
26 | updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
27 | updateManyUsers(data: UserUpdateManyMutationInput!, where: UserWhereInput): BatchPayload!
28 | upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
29 | deleteUser(where: UserWhereUniqueInput!): User
30 | deleteManyUsers(where: UserWhereInput): BatchPayload!
31 | }
32 |
33 | enum MutationType {
34 | CREATED
35 | UPDATED
36 | DELETED
37 | }
38 |
39 | interface Node {
40 | id: ID!
41 | }
42 |
43 | type PageInfo {
44 | hasNextPage: Boolean!
45 | hasPreviousPage: Boolean!
46 | startCursor: String
47 | endCursor: String
48 | }
49 |
50 | type Post {
51 | id: ID!
52 | createdAt: DateTime!
53 | updatedAt: DateTime!
54 | published: Boolean!
55 | title: String!
56 | content: String!
57 | author: User!
58 | }
59 |
60 | type PostConnection {
61 | pageInfo: PageInfo!
62 | edges: [PostEdge]!
63 | aggregate: AggregatePost!
64 | }
65 |
66 | input PostCreateInput {
67 | published: Boolean
68 | title: String!
69 | content: String!
70 | author: UserCreateOneWithoutPostsInput!
71 | }
72 |
73 | input PostCreateManyWithoutAuthorInput {
74 | create: [PostCreateWithoutAuthorInput!]
75 | connect: [PostWhereUniqueInput!]
76 | }
77 |
78 | input PostCreateWithoutAuthorInput {
79 | published: Boolean
80 | title: String!
81 | content: String!
82 | }
83 |
84 | type PostEdge {
85 | node: Post!
86 | cursor: String!
87 | }
88 |
89 | enum PostOrderByInput {
90 | id_ASC
91 | id_DESC
92 | createdAt_ASC
93 | createdAt_DESC
94 | updatedAt_ASC
95 | updatedAt_DESC
96 | published_ASC
97 | published_DESC
98 | title_ASC
99 | title_DESC
100 | content_ASC
101 | content_DESC
102 | }
103 |
104 | type PostPreviousValues {
105 | id: ID!
106 | createdAt: DateTime!
107 | updatedAt: DateTime!
108 | published: Boolean!
109 | title: String!
110 | content: String!
111 | }
112 |
113 | input PostScalarWhereInput {
114 | id: ID
115 | id_not: ID
116 | id_in: [ID!]
117 | id_not_in: [ID!]
118 | id_lt: ID
119 | id_lte: ID
120 | id_gt: ID
121 | id_gte: ID
122 | id_contains: ID
123 | id_not_contains: ID
124 | id_starts_with: ID
125 | id_not_starts_with: ID
126 | id_ends_with: ID
127 | id_not_ends_with: ID
128 | createdAt: DateTime
129 | createdAt_not: DateTime
130 | createdAt_in: [DateTime!]
131 | createdAt_not_in: [DateTime!]
132 | createdAt_lt: DateTime
133 | createdAt_lte: DateTime
134 | createdAt_gt: DateTime
135 | createdAt_gte: DateTime
136 | updatedAt: DateTime
137 | updatedAt_not: DateTime
138 | updatedAt_in: [DateTime!]
139 | updatedAt_not_in: [DateTime!]
140 | updatedAt_lt: DateTime
141 | updatedAt_lte: DateTime
142 | updatedAt_gt: DateTime
143 | updatedAt_gte: DateTime
144 | published: Boolean
145 | published_not: Boolean
146 | title: String
147 | title_not: String
148 | title_in: [String!]
149 | title_not_in: [String!]
150 | title_lt: String
151 | title_lte: String
152 | title_gt: String
153 | title_gte: String
154 | title_contains: String
155 | title_not_contains: String
156 | title_starts_with: String
157 | title_not_starts_with: String
158 | title_ends_with: String
159 | title_not_ends_with: String
160 | content: String
161 | content_not: String
162 | content_in: [String!]
163 | content_not_in: [String!]
164 | content_lt: String
165 | content_lte: String
166 | content_gt: String
167 | content_gte: String
168 | content_contains: String
169 | content_not_contains: String
170 | content_starts_with: String
171 | content_not_starts_with: String
172 | content_ends_with: String
173 | content_not_ends_with: String
174 | AND: [PostScalarWhereInput!]
175 | OR: [PostScalarWhereInput!]
176 | NOT: [PostScalarWhereInput!]
177 | }
178 |
179 | type PostSubscriptionPayload {
180 | mutation: MutationType!
181 | node: Post
182 | updatedFields: [String!]
183 | previousValues: PostPreviousValues
184 | }
185 |
186 | input PostSubscriptionWhereInput {
187 | mutation_in: [MutationType!]
188 | updatedFields_contains: String
189 | updatedFields_contains_every: [String!]
190 | updatedFields_contains_some: [String!]
191 | node: PostWhereInput
192 | AND: [PostSubscriptionWhereInput!]
193 | OR: [PostSubscriptionWhereInput!]
194 | NOT: [PostSubscriptionWhereInput!]
195 | }
196 |
197 | input PostUpdateInput {
198 | published: Boolean
199 | title: String
200 | content: String
201 | author: UserUpdateOneRequiredWithoutPostsInput
202 | }
203 |
204 | input PostUpdateManyDataInput {
205 | published: Boolean
206 | title: String
207 | content: String
208 | }
209 |
210 | input PostUpdateManyMutationInput {
211 | published: Boolean
212 | title: String
213 | content: String
214 | }
215 |
216 | input PostUpdateManyWithoutAuthorInput {
217 | create: [PostCreateWithoutAuthorInput!]
218 | delete: [PostWhereUniqueInput!]
219 | connect: [PostWhereUniqueInput!]
220 | disconnect: [PostWhereUniqueInput!]
221 | update: [PostUpdateWithWhereUniqueWithoutAuthorInput!]
222 | upsert: [PostUpsertWithWhereUniqueWithoutAuthorInput!]
223 | deleteMany: [PostScalarWhereInput!]
224 | updateMany: [PostUpdateManyWithWhereNestedInput!]
225 | }
226 |
227 | input PostUpdateManyWithWhereNestedInput {
228 | where: PostScalarWhereInput!
229 | data: PostUpdateManyDataInput!
230 | }
231 |
232 | input PostUpdateWithoutAuthorDataInput {
233 | published: Boolean
234 | title: String
235 | content: String
236 | }
237 |
238 | input PostUpdateWithWhereUniqueWithoutAuthorInput {
239 | where: PostWhereUniqueInput!
240 | data: PostUpdateWithoutAuthorDataInput!
241 | }
242 |
243 | input PostUpsertWithWhereUniqueWithoutAuthorInput {
244 | where: PostWhereUniqueInput!
245 | update: PostUpdateWithoutAuthorDataInput!
246 | create: PostCreateWithoutAuthorInput!
247 | }
248 |
249 | input PostWhereInput {
250 | id: ID
251 | id_not: ID
252 | id_in: [ID!]
253 | id_not_in: [ID!]
254 | id_lt: ID
255 | id_lte: ID
256 | id_gt: ID
257 | id_gte: ID
258 | id_contains: ID
259 | id_not_contains: ID
260 | id_starts_with: ID
261 | id_not_starts_with: ID
262 | id_ends_with: ID
263 | id_not_ends_with: ID
264 | createdAt: DateTime
265 | createdAt_not: DateTime
266 | createdAt_in: [DateTime!]
267 | createdAt_not_in: [DateTime!]
268 | createdAt_lt: DateTime
269 | createdAt_lte: DateTime
270 | createdAt_gt: DateTime
271 | createdAt_gte: DateTime
272 | updatedAt: DateTime
273 | updatedAt_not: DateTime
274 | updatedAt_in: [DateTime!]
275 | updatedAt_not_in: [DateTime!]
276 | updatedAt_lt: DateTime
277 | updatedAt_lte: DateTime
278 | updatedAt_gt: DateTime
279 | updatedAt_gte: DateTime
280 | published: Boolean
281 | published_not: Boolean
282 | title: String
283 | title_not: String
284 | title_in: [String!]
285 | title_not_in: [String!]
286 | title_lt: String
287 | title_lte: String
288 | title_gt: String
289 | title_gte: String
290 | title_contains: String
291 | title_not_contains: String
292 | title_starts_with: String
293 | title_not_starts_with: String
294 | title_ends_with: String
295 | title_not_ends_with: String
296 | content: String
297 | content_not: String
298 | content_in: [String!]
299 | content_not_in: [String!]
300 | content_lt: String
301 | content_lte: String
302 | content_gt: String
303 | content_gte: String
304 | content_contains: String
305 | content_not_contains: String
306 | content_starts_with: String
307 | content_not_starts_with: String
308 | content_ends_with: String
309 | content_not_ends_with: String
310 | author: UserWhereInput
311 | AND: [PostWhereInput!]
312 | OR: [PostWhereInput!]
313 | NOT: [PostWhereInput!]
314 | }
315 |
316 | input PostWhereUniqueInput {
317 | id: ID
318 | }
319 |
320 | type Query {
321 | post(where: PostWhereUniqueInput!): Post
322 | posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post]!
323 | postsConnection(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): PostConnection!
324 | user(where: UserWhereUniqueInput!): User
325 | users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
326 | usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
327 | node(id: ID!): Node
328 | }
329 |
330 | type Subscription {
331 | post(where: PostSubscriptionWhereInput): PostSubscriptionPayload
332 | user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
333 | }
334 |
335 | type User {
336 | id: ID!
337 | email: String!
338 | password: String!
339 | name: String!
340 | posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post!]
341 | }
342 |
343 | type UserConnection {
344 | pageInfo: PageInfo!
345 | edges: [UserEdge]!
346 | aggregate: AggregateUser!
347 | }
348 |
349 | input UserCreateInput {
350 | email: String!
351 | password: String!
352 | name: String!
353 | posts: PostCreateManyWithoutAuthorInput
354 | }
355 |
356 | input UserCreateOneWithoutPostsInput {
357 | create: UserCreateWithoutPostsInput
358 | connect: UserWhereUniqueInput
359 | }
360 |
361 | input UserCreateWithoutPostsInput {
362 | email: String!
363 | password: String!
364 | name: String!
365 | }
366 |
367 | type UserEdge {
368 | node: User!
369 | cursor: String!
370 | }
371 |
372 | enum UserOrderByInput {
373 | id_ASC
374 | id_DESC
375 | email_ASC
376 | email_DESC
377 | password_ASC
378 | password_DESC
379 | name_ASC
380 | name_DESC
381 | createdAt_ASC
382 | createdAt_DESC
383 | updatedAt_ASC
384 | updatedAt_DESC
385 | }
386 |
387 | type UserPreviousValues {
388 | id: ID!
389 | email: String!
390 | password: String!
391 | name: String!
392 | }
393 |
394 | type UserSubscriptionPayload {
395 | mutation: MutationType!
396 | node: User
397 | updatedFields: [String!]
398 | previousValues: UserPreviousValues
399 | }
400 |
401 | input UserSubscriptionWhereInput {
402 | mutation_in: [MutationType!]
403 | updatedFields_contains: String
404 | updatedFields_contains_every: [String!]
405 | updatedFields_contains_some: [String!]
406 | node: UserWhereInput
407 | AND: [UserSubscriptionWhereInput!]
408 | OR: [UserSubscriptionWhereInput!]
409 | NOT: [UserSubscriptionWhereInput!]
410 | }
411 |
412 | input UserUpdateInput {
413 | email: String
414 | password: String
415 | name: String
416 | posts: PostUpdateManyWithoutAuthorInput
417 | }
418 |
419 | input UserUpdateManyMutationInput {
420 | email: String
421 | password: String
422 | name: String
423 | }
424 |
425 | input UserUpdateOneRequiredWithoutPostsInput {
426 | create: UserCreateWithoutPostsInput
427 | update: UserUpdateWithoutPostsDataInput
428 | upsert: UserUpsertWithoutPostsInput
429 | connect: UserWhereUniqueInput
430 | }
431 |
432 | input UserUpdateWithoutPostsDataInput {
433 | email: String
434 | password: String
435 | name: String
436 | }
437 |
438 | input UserUpsertWithoutPostsInput {
439 | update: UserUpdateWithoutPostsDataInput!
440 | create: UserCreateWithoutPostsInput!
441 | }
442 |
443 | input UserWhereInput {
444 | id: ID
445 | id_not: ID
446 | id_in: [ID!]
447 | id_not_in: [ID!]
448 | id_lt: ID
449 | id_lte: ID
450 | id_gt: ID
451 | id_gte: ID
452 | id_contains: ID
453 | id_not_contains: ID
454 | id_starts_with: ID
455 | id_not_starts_with: ID
456 | id_ends_with: ID
457 | id_not_ends_with: ID
458 | email: String
459 | email_not: String
460 | email_in: [String!]
461 | email_not_in: [String!]
462 | email_lt: String
463 | email_lte: String
464 | email_gt: String
465 | email_gte: String
466 | email_contains: String
467 | email_not_contains: String
468 | email_starts_with: String
469 | email_not_starts_with: String
470 | email_ends_with: String
471 | email_not_ends_with: String
472 | password: String
473 | password_not: String
474 | password_in: [String!]
475 | password_not_in: [String!]
476 | password_lt: String
477 | password_lte: String
478 | password_gt: String
479 | password_gte: String
480 | password_contains: String
481 | password_not_contains: String
482 | password_starts_with: String
483 | password_not_starts_with: String
484 | password_ends_with: String
485 | password_not_ends_with: String
486 | name: String
487 | name_not: String
488 | name_in: [String!]
489 | name_not_in: [String!]
490 | name_lt: String
491 | name_lte: String
492 | name_gt: String
493 | name_gte: String
494 | name_contains: String
495 | name_not_contains: String
496 | name_starts_with: String
497 | name_not_starts_with: String
498 | name_ends_with: String
499 | name_not_ends_with: String
500 | posts_every: PostWhereInput
501 | posts_some: PostWhereInput
502 | posts_none: PostWhereInput
503 | AND: [UserWhereInput!]
504 | OR: [UserWhereInput!]
505 | NOT: [UserWhereInput!]
506 | }
507 |
508 | input UserWhereUniqueInput {
509 | id: ID
510 | email: String
511 | }
512 | `
513 | }
514 |
--------------------------------------------------------------------------------
/advanced/server/src/index.js:
--------------------------------------------------------------------------------
1 | const { GraphQLServer } = require('graphql-yoga')
2 | const { prisma } = require('./generated/prisma-client')
3 | const resolvers = require('./resolvers')
4 |
5 | const server = new GraphQLServer({
6 | typeDefs: 'src/schema.graphql',
7 | resolvers,
8 | context: request => {
9 | return {
10 | ...request,
11 | prisma,
12 | }
13 | },
14 | })
15 |
16 | server.start(() => console.log('Server is running on http://localhost:4000'))
17 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/Mutation/auth.js:
--------------------------------------------------------------------------------
1 | const bcrypt = require('bcryptjs')
2 | const jwt = require('jsonwebtoken')
3 |
4 | const auth = {
5 | async signup(parent, args, context) {
6 | const password = await bcrypt.hash(args.password, 10)
7 | const user = await context.prisma.createUser({ ...args, password })
8 |
9 | return {
10 | token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
11 | user,
12 | }
13 | },
14 |
15 | async login(parent, { email, password }, context) {
16 | const user = await context.prisma.user({ email })
17 | if (!user) {
18 | throw new Error(`No user found for email: ${email}`)
19 | }
20 | const passwordValid = await bcrypt.compare(password, user.password)
21 | if (!passwordValid) {
22 | throw new Error('Invalid password')
23 | }
24 | return {
25 | token: jwt.sign({ userId: user.id }, process.env.APP_SECRET),
26 | user,
27 | }
28 | },
29 | }
30 |
31 | module.exports = { auth }
32 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/Mutation/post.js:
--------------------------------------------------------------------------------
1 | const { getUserId } = require('../../utils')
2 |
3 | const post = {
4 | async createDraft(parent, { title, content }, context) {
5 | const userId = getUserId(context)
6 | return context.prisma.createPost({
7 | title,
8 | content,
9 | author: { connect: { id: userId } },
10 | })
11 | },
12 |
13 | async publish(parent, { id }, context) {
14 | const userId = getUserId(context)
15 | const postExists = await context.prisma.$exists.post({
16 | id,
17 | author: { id: userId },
18 | })
19 | if (!postExists) {
20 | throw new Error(`Post not found or you're not the author`)
21 | }
22 |
23 | return context.prisma.updatePost(
24 | {
25 | where: { id },
26 | data: { published: true },
27 | },
28 | )
29 | },
30 |
31 | async deletePost(parent, { id }, context) {
32 | const userId = getUserId(context)
33 | const postExists = await context.prisma.$exists.post({
34 | id,
35 | author: { id: userId },
36 | })
37 | if (!postExists) {
38 | throw new Error(`Post not found or you're not the author`)
39 | }
40 |
41 | return context.prisma.deletePost({ id })
42 | },
43 | }
44 |
45 | module.exports = { post }
46 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/Post.js:
--------------------------------------------------------------------------------
1 | const Post = {
2 | author: ({ id }, args, context) => {
3 | return context.prisma.post({ id }).author()
4 | },
5 | }
6 |
7 | module.exports = {
8 | Post,
9 | }
10 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/Query.js:
--------------------------------------------------------------------------------
1 | const { getUserId } = require('../utils')
2 |
3 | const Query = {
4 | feed(parent, args, context) {
5 | return context.prisma.posts({ where: { published: true } })
6 | },
7 | drafts(parent, args, context) {
8 | const id = getUserId(context)
9 | const where = {
10 | published: false,
11 | author: {
12 | id,
13 | },
14 | }
15 | return context.prisma.posts({ where })
16 | },
17 | post(parent, { id }, context) {
18 | return context.prisma.post({ id })
19 | },
20 | me(parent, args, context) {
21 | const id = getUserId(context)
22 | return context.prisma.user({ id })
23 | },
24 | }
25 |
26 | module.exports = { Query }
27 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/Subscription.js:
--------------------------------------------------------------------------------
1 | const Subscription = {
2 | feedSubscription: {
3 | subscribe: async (parent, args, context) => {
4 | return context.prisma.$subscribe
5 | .post({
6 | mutation_in: ['CREATED', 'UPDATED'],
7 | })
8 | .node()
9 | },
10 | resolve: payload => {
11 | return payload
12 | },
13 | },
14 | }
15 |
16 | module.exports = { Subscription }
17 |
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/User.js:
--------------------------------------------------------------------------------
1 | const User = {
2 | posts: ({ id }, args, context) => {
3 | return context.prisma.user({ id }).posts()
4 | },
5 | }
6 |
7 | module.exports = {
8 | User,
9 | }
--------------------------------------------------------------------------------
/advanced/server/src/resolvers/index.js:
--------------------------------------------------------------------------------
1 | const { Query } = require('./Query')
2 | const { auth } = require('./Mutation/auth')
3 | const { post } = require('./Mutation/post')
4 | const { Subscription } = require('./Subscription')
5 | const { User } = require('./User')
6 | const { Post } = require('./Post')
7 |
8 | module.exports = {
9 | Query,
10 | Mutation: {
11 | ...auth,
12 | ...post,
13 | },
14 | Subscription,
15 | User,
16 | Post,
17 | }
18 |
--------------------------------------------------------------------------------
/advanced/server/src/schema.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | feed: [Post!]!
3 | drafts: [Post!]!
4 | post(id: ID!): Post
5 | me: User
6 | }
7 |
8 | type Mutation {
9 | signup(email: String!, password: String!, name: String!): AuthPayload!
10 | login(email: String!, password: String!): AuthPayload!
11 | createDraft(title: String!, content: String!): Post!
12 | publish(id: ID!): Post!
13 | deletePost(id: ID!): Post!
14 | }
15 |
16 | type Subscription {
17 | feedSubscription: Post
18 | }
19 |
20 | type AuthPayload {
21 | token: String!
22 | user: User!
23 | }
24 |
25 | type User {
26 | id: ID!
27 | email: String!
28 | name: String!
29 | posts: [Post!]!
30 | }
31 |
32 | type Post {
33 | id: ID!
34 | published: Boolean!
35 | title: String!
36 | content: String!
37 | author: User!
38 | }
--------------------------------------------------------------------------------
/advanced/server/src/utils.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken')
2 |
3 | function getUserId(context) {
4 | const Authorization = context.request.get('Authorization')
5 | if (Authorization) {
6 | const token = Authorization.replace('Bearer ', '')
7 | const { userId } = jwt.verify(token, process.env.APP_SECRET)
8 | return userId
9 | }
10 |
11 | throw new AuthError()
12 | }
13 |
14 | class AuthError extends Error {
15 | constructor() {
16 | super('Not authorized')
17 | }
18 | }
19 |
20 | module.exports = {
21 | getUserId,
22 | AuthError
23 | }
--------------------------------------------------------------------------------
/advanced/src/assets/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/advanced/src/assets/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/advanced/src/components/CreatePage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { withRouter } from 'react-router-dom'
3 | import { graphql } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 |
6 | class CreatePage extends Component {
7 | state = {
8 | title: '',
9 | text: '',
10 | }
11 |
12 | render() {
13 | return (
14 |
46 | )
47 | }
48 |
49 | handlePost = async e => {
50 | e.preventDefault()
51 | const { title, text } = this.state
52 | await this.props.createDraftMutation({
53 | variables: { title, text },
54 | })
55 | this.props.history.replace('/drafts')
56 | }
57 | }
58 |
59 | const CREATE_DRAFT_MUTATION = gql`
60 | mutation CreateDraftMutation($title: String!, $text: String!) {
61 | createDraft(title: $title, text: $text) {
62 | id
63 | title
64 | text
65 | }
66 | }
67 | `
68 |
69 | const CreatePageWithMutation = graphql(CREATE_DRAFT_MUTATION, {
70 | name: 'createDraftMutation', // name of the injected prop: this.props.createDraftMutation...
71 | })(CreatePage)
72 |
73 | export default withRouter(CreatePageWithMutation)
74 |
--------------------------------------------------------------------------------
/advanced/src/components/DetailPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import { graphql, compose } from 'react-apollo'
3 | import { withRouter } from 'react-router-dom'
4 | import { gql } from 'apollo-boost'
5 |
6 | class DetailPage extends Component {
7 | render() {
8 | if (this.props.postQuery.loading) {
9 | return (
10 |
11 |
Loading (from {process.env.REACT_APP_GRAPHQL_ENDPOINT})
12 |
13 | )
14 | }
15 |
16 | const { post } = this.props.postQuery
17 |
18 | let action = this._renderAction(post)
19 |
20 | return (
21 |
22 | {post.title}
23 | {post.text}
24 | {action}
25 |
26 | )
27 | }
28 |
29 | _renderAction = ({ id, isPublished }) => {
30 | if (!isPublished) {
31 | return (
32 |
33 | this.publishDraft(id)}
36 | >
37 | Publish
38 | {' '}
39 | this.deletePost(id)}
42 | >
43 | Delete
44 |
45 |
46 | )
47 | }
48 | return (
49 | this.deletePost(id)}
52 | >
53 | Delete
54 |
55 | )
56 | }
57 |
58 | deletePost = async id => {
59 | await this.props.deletePost({
60 | variables: { id },
61 | })
62 | this.props.history.replace('/')
63 | }
64 |
65 | publishDraft = async id => {
66 | await this.props.publishDraft({
67 | variables: { id },
68 | })
69 | this.props.history.replace('/')
70 | }
71 | }
72 |
73 | const POST_QUERY = gql`
74 | query PostQuery($id: ID!) {
75 | post(id: $id) {
76 | id
77 | title
78 | text
79 | isPublished
80 | author {
81 | name
82 | }
83 | }
84 | }
85 | `
86 |
87 | const PUBLISH_MUTATION = gql`
88 | mutation publish($id: ID!) {
89 | publish(id: $id) {
90 | id
91 | isPublished
92 | }
93 | }
94 | `
95 |
96 | const DELETE_MUTATION = gql`
97 | mutation deletePost($id: ID!) {
98 | deletePost(id: $id) {
99 | id
100 | }
101 | }
102 | `
103 |
104 | export default compose(
105 | graphql(POST_QUERY, {
106 | name: 'postQuery',
107 | options: props => ({
108 | variables: {
109 | id: props.match.params.id,
110 | },
111 | }),
112 | }),
113 | graphql(PUBLISH_MUTATION, {
114 | name: 'publishDraft',
115 | }),
116 | graphql(DELETE_MUTATION, {
117 | name: 'deletePost',
118 | }),
119 | withRouter,
120 | )(DetailPage)
121 |
--------------------------------------------------------------------------------
/advanced/src/components/DraftsPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import Post from '../components/Post'
3 | import { graphql } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 |
6 | class DraftsPage extends Component {
7 | componentWillReceiveProps(nextProps) {
8 | if (this.props.location.key !== nextProps.location.key) {
9 | this.props.draftsQuery.refetch()
10 | }
11 | }
12 |
13 | render() {
14 | if (this.props.draftsQuery.loading) {
15 | return (
16 |
17 |
Loading (from {process.env.REACT_APP_GRAPHQL_ENDPOINT})
18 |
19 | )
20 | }
21 |
22 | return (
23 |
24 |
25 |
Drafts
26 |
27 | {this.props.draftsQuery.drafts &&
28 | this.props.draftsQuery.drafts.map(draft => (
29 | this.props.draftsQuery.refetch()}
33 | isDraft={!draft.isPublished}
34 | />
35 | ))}
36 | {this.props.children}
37 |
38 | )
39 | }
40 | }
41 |
42 | const DRAFTS_QUERY = gql`
43 | query DraftsQuery {
44 | drafts {
45 | id
46 | text
47 | title
48 | isPublished
49 | author {
50 | name
51 | }
52 | }
53 | }
54 | `
55 |
56 | export default graphql(DRAFTS_QUERY, {
57 | name: 'draftsQuery', // name of the injected prop: this.props.feedQuery...
58 | options: {
59 | fetchPolicy: 'network-only',
60 | },
61 | })(DraftsPage)
62 |
--------------------------------------------------------------------------------
/advanced/src/components/FeedPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import Post from '../components/Post'
3 | import { graphql } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 |
6 | class FeedPage extends Component {
7 | componentWillReceiveProps(nextProps) {
8 | if (this.props.location.key !== nextProps.location.key) {
9 | this.props.feedQuery.refetch()
10 | }
11 | }
12 |
13 | componentDidMount() {
14 | this.props.subscribeToNewFeed()
15 | }
16 |
17 | render() {
18 | if (this.props.feedQuery.loading) {
19 | return (
20 |
21 |
Loading (from {process.env.REACT_APP_GRAPHQL_ENDPOINT})
22 |
23 | )
24 | }
25 |
26 | return (
27 |
28 | Feed
29 | {this.props.feedQuery.feed &&
30 | this.props.feedQuery.feed.map(post => (
31 | this.props.feedQuery.refetch()}
35 | isDraft={!post.isPublished}
36 | />
37 | ))}
38 | {this.props.children}
39 |
40 | )
41 | }
42 | }
43 |
44 | const FEED_QUERY = gql`
45 | query FeedQuery {
46 | feed {
47 | id
48 | text
49 | title
50 | isPublished
51 | author {
52 | name
53 | }
54 | }
55 | }
56 | `
57 | const FEED_SUBSCRIPTION = gql`
58 | subscription FeedSubscription {
59 | feedSubscription {
60 | node {
61 | id
62 | text
63 | title
64 | isPublished
65 | author {
66 | name
67 | }
68 | }
69 | }
70 | }
71 | `
72 |
73 | export default graphql(FEED_QUERY, {
74 | name: 'feedQuery', // name of the injected prop: this.props.feedQuery...
75 | options: {
76 | fetchPolicy: 'network-only',
77 | },
78 | props: props =>
79 | Object.assign({}, props, {
80 | subscribeToNewFeed: params => {
81 | return props.feedQuery.subscribeToMore({
82 | document: FEED_SUBSCRIPTION,
83 | updateQuery: (prev, { subscriptionData }) => {
84 | if (!subscriptionData.data) {
85 | return prev
86 | }
87 | const newPost = subscriptionData.data.feedSubscription.node
88 | if (prev.feed.find(post => post.id === newPost.id)) {
89 | return prev
90 | }
91 | return Object.assign({}, prev, {
92 | feed: [...prev.feed, newPost],
93 | })
94 | },
95 | })
96 | },
97 | }),
98 | })(FeedPage)
99 |
--------------------------------------------------------------------------------
/advanced/src/components/LoginPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { withRouter } from 'react-router-dom'
3 | import { graphql } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 | import { AUTH_TOKEN } from '../constant'
6 |
7 | class LoginPage extends Component {
8 | state = {
9 | email: '',
10 | password: '',
11 | }
12 |
13 | render() {
14 | return (
15 |
47 | )
48 | }
49 |
50 | _login = async e => {
51 | const { email, password } = this.state
52 | this.props
53 | .loginMutation({
54 | variables: {
55 | email,
56 | password,
57 | },
58 | })
59 | .then(result => {
60 | const token = result.data.login.token
61 |
62 | this.props.refreshTokenFn &&
63 | this.props.refreshTokenFn({
64 | [AUTH_TOKEN]: token,
65 | })
66 | this.props.history.replace('/')
67 | window.location.reload()
68 | })
69 | .catch(err => {
70 | console.log('error')
71 | })
72 | }
73 | }
74 |
75 | const LOGIN_USER_MUTATION = gql`
76 | mutation LoginMutation($email: String!, $password: String!) {
77 | login(email: $email, password: $password) {
78 | token
79 | user {
80 | id
81 | name
82 | email
83 | }
84 | }
85 | }
86 | `
87 |
88 | export default graphql(LOGIN_USER_MUTATION, { name: 'loginMutation' })(
89 | withRouter(LoginPage),
90 | )
91 |
--------------------------------------------------------------------------------
/advanced/src/components/LogoutPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { withRouter } from 'react-router-dom'
3 |
4 | const LogoutPage = () => (
5 |
6 |
7 | You are currently logged out. To see the drafts, please login.
8 |
9 |
10 | )
11 |
12 | export default withRouter(LogoutPage)
13 |
--------------------------------------------------------------------------------
/advanced/src/components/PageNotFound.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | const PageNotFound = ({ location }) => (
5 |
6 |
Sorry, no page found at {location.pathname}
7 |
Go Home
8 |
9 | )
10 |
11 | export default PageNotFound
12 |
--------------------------------------------------------------------------------
/advanced/src/components/Post.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | export default class Post extends Component {
5 | render() {
6 | let title = this.props.post.title
7 | if (this.props.isDraft) {
8 | title = `${title} (Draft)`
9 | }
10 |
11 | return (
12 |
13 |
14 |
15 |
16 |
{title}
17 |
{this.props.post.text}
18 |
By {this.props.post.author.name}
19 |
20 |
21 |
22 |
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/advanced/src/components/RootContainer.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import {
3 | NavLink,
4 | Link,
5 | BrowserRouter as Router,
6 | Route,
7 | Switch,
8 | Redirect,
9 | } from 'react-router-dom'
10 | import FeedPage from './FeedPage'
11 | import DraftsPage from './DraftsPage'
12 | import CreatePage from './CreatePage'
13 | import DetailPage from './DetailPage'
14 | import LoginPage from './LoginPage'
15 | import SignupPage from './SignupPage'
16 | import PageNotFound from './PageNotFound'
17 | import LogoutPage from './LogoutPage'
18 | import { AUTH_TOKEN } from '../constant'
19 | import { isTokenExpired } from '../helper/jwtHelper'
20 | import { graphql } from 'react-apollo'
21 | import { gql } from 'apollo-boost'
22 |
23 | const ProtectedRoute = ({ component: Component, token, ...rest }) => {
24 | return token ? (
25 | } />
26 | ) : (
27 |
28 | )
29 | }
30 |
31 | class RootContainer extends Component {
32 | constructor(props) {
33 | super(props)
34 | this.refreshTokenFn = this.refreshTokenFn.bind(this)
35 |
36 | this.state = {
37 | token: props.token,
38 | }
39 | }
40 |
41 | refreshTokenFn(data = {}) {
42 | const token = data[AUTH_TOKEN]
43 |
44 | if (token) {
45 | localStorage.setItem(AUTH_TOKEN, token)
46 | } else {
47 | localStorage.removeItem(AUTH_TOKEN)
48 | }
49 |
50 | this.setState({
51 | token: data[AUTH_TOKEN],
52 | })
53 | }
54 |
55 | bootStrapData() {
56 | try {
57 | const token = localStorage.getItem(AUTH_TOKEN)
58 | if (token !== null && token !== undefined) {
59 | const expired = isTokenExpired(token)
60 | if (!expired) {
61 | this.setState({ token: token })
62 | } else {
63 | localStorage.removeItem(AUTH_TOKEN)
64 | this.setState({ token: null })
65 | }
66 | }
67 | } catch (e) {
68 | console.log('')
69 | }
70 | }
71 |
72 | //verify localStorage check
73 | componentDidMount() {
74 | this.bootStrapData()
75 | }
76 |
77 | render() {
78 | return (
79 |
80 |
81 | {this.renderNavBar()}
82 | {this.renderRoute()}
83 |
84 |
85 | )
86 | }
87 |
88 | renderNavBar() {
89 | return (
90 |
91 |
92 | Blog
93 |
94 |
101 | Feed
102 |
103 | {this.props.data &&
104 | this.props.data.me &&
105 | this.props.data.me.email &&
106 | this.state.token && (
107 |
114 | Drafts
115 |
116 | )}
117 | {this.state.token ? (
118 | {
120 | this.refreshTokenFn &&
121 | this.refreshTokenFn({
122 | [AUTH_TOKEN]: null,
123 | })
124 | window.location.href = '/'
125 | }}
126 | className="f6 link dim br1 ba ph3 pv2 fr mb2 dib black"
127 | >
128 | Logout
129 |
130 | ) : (
131 |
135 | Login
136 |
137 | )}
138 | {this.props.data &&
139 | this.props.data.me &&
140 | this.props.data.me.email &&
141 | this.state.token && (
142 |
146 | + Create Draft
147 |
148 | )}
149 |
150 | )
151 | }
152 |
153 | renderRoute() {
154 | return (
155 |
156 |
157 |
158 |
163 |
168 |
169 | }
173 | />
174 | (
178 |
179 | )}
180 | />
181 |
182 |
183 |
184 |
185 | )
186 | }
187 | }
188 |
189 | const ME_QUERY = gql`
190 | query MeQuery {
191 | me {
192 | id
193 | email
194 | name
195 | }
196 | }
197 | `
198 |
199 | export default graphql(ME_QUERY, {
200 | options: {
201 | errorPolicy: 'all',
202 | },
203 | })(RootContainer)
204 |
--------------------------------------------------------------------------------
/advanced/src/components/SignupPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { withRouter } from 'react-router-dom'
3 | import { graphql } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 | import { AUTH_TOKEN } from '../constant'
6 |
7 | class SignupPage extends Component {
8 | state = {
9 | email: '',
10 | password: '',
11 | name: '',
12 | }
13 |
14 | render() {
15 | return (
16 |
56 | )
57 | }
58 |
59 | _signup = async e => {
60 | e.preventDefault()
61 | const { email, name, password } = this.state
62 | const result = await this.props.signupMutation({
63 | variables: {
64 | name,
65 | email,
66 | password,
67 | },
68 | })
69 |
70 | const token = result.data.signup.token
71 | localStorage.setItem(AUTH_TOKEN, token)
72 |
73 | this.props.refreshTokenFn &&
74 | this.props.refreshTokenFn({
75 | [AUTH_TOKEN]: token,
76 | })
77 |
78 | this.props.history.replace('/')
79 | window.location.reload()
80 | }
81 | }
82 |
83 | const SIGNUP_USER_MUTATION = gql`
84 | mutation SignupMutation($email: String!, $password: String!, $name: String!) {
85 | signup(email: $email, password: $password, name: $name) {
86 | token
87 | user {
88 | id
89 | name
90 | email
91 | }
92 | }
93 | }
94 | `
95 |
96 | export default graphql(SIGNUP_USER_MUTATION, { name: 'signupMutation' })(
97 | withRouter(SignupPage),
98 | )
99 |
--------------------------------------------------------------------------------
/advanced/src/constant.js:
--------------------------------------------------------------------------------
1 | export const USER_ID = 'user-id'
2 | export const AUTH_TOKEN = 'AUTH_TOKEN'
3 |
4 |
--------------------------------------------------------------------------------
/advanced/src/constants/modalStyle.js:
--------------------------------------------------------------------------------
1 | const modalStyle = {
2 | overlay: {
3 | zIndex: 20,
4 | backgroundColor: 'rgba(255,255,255,.6)',
5 | display: 'flex',
6 | alignItems: 'center',
7 | justifyContent: 'center',
8 | },
9 | content: {
10 | position: 'relative',
11 | width: 600,
12 | height: 'auto',
13 | top: 'initial',
14 | left: 'initial',
15 | right: 'initial',
16 | bottom: 'initial',
17 | borderRadius: 2,
18 | padding: 0,
19 | border: 'none',
20 | background: 'none',
21 | boxShadow: '0 1px 7px rgba(0,0,0,.2)',
22 | },
23 | }
24 |
25 | export default modalStyle
26 |
--------------------------------------------------------------------------------
/advanced/src/helper/jwtHelper.js:
--------------------------------------------------------------------------------
1 | import decode from 'jwt-decode'
2 |
3 | export function getTokenExpirationDate(token) {
4 | const decoded = decode(token)
5 | if (!decoded.exp) {
6 | return null
7 | }
8 | const date = new Date(0) // The 0 here is the key, which sets the date to the epoch
9 | date.setUTCSeconds(decoded.exp)
10 | return date
11 | }
12 |
13 | export function isTokenExpired(token) {
14 | const date = getTokenExpirationDate(token)
15 | const offsetSeconds = 0
16 | if (date === null) {
17 | return false
18 | }
19 | return !(date.valueOf() > new Date().valueOf() + offsetSeconds * 1000)
20 | }
21 |
--------------------------------------------------------------------------------
/advanced/src/index.css:
--------------------------------------------------------------------------------
1 | @import 'https://fonts.googleapis.com/css?family=Open+Sans:300, 400';
2 |
3 | body {
4 | margin: 0;
5 | padding: 0;
6 | font-family: 'Open Sans', sans-serif;
7 | background: rgba(0, 0, 0, 0.05);
8 | }
9 |
10 | html {
11 | box-sizing: border-box;
12 | }
13 |
14 | *,
15 | *:before,
16 | *:after {
17 | box-sizing: inherit;
18 | }
19 |
20 | .post {
21 | box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
22 | width: 350px;
23 | height: 350px;
24 | flex: 0 0 350px;
25 | }
26 |
27 | .post .description {
28 | flex: 1;
29 | padding-left: 25px;
30 | font-size: 25px;
31 | }
32 |
33 | .detail {
34 | width: 600px;
35 | height: 600px;
36 | flex: 0 0 600px;
37 | }
38 |
39 | .detail .description {
40 | flex: 1;
41 | padding-left: 40px;
42 | font-size: 38px;
43 | }
44 |
45 | .title {
46 | font-size: 42px;
47 | }
48 |
49 | .content {
50 | font-size: 18px;
51 | }
52 |
53 | .new-post {
54 | background-color: rgba(0, 0, 0, 0.04);
55 | }
56 |
57 | .close {
58 | opacity: 0.5;
59 | margin-top: 60px;
60 | margin-right: 60px;
61 | }
62 |
63 | .close img {
64 | width: 20px;
65 | height: 20px;
66 | }
67 |
--------------------------------------------------------------------------------
/advanced/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import { HttpLink, InMemoryCache, ApolloClient } from 'apollo-client-preset'
4 | import { WebSocketLink } from 'apollo-link-ws'
5 | import { ApolloLink, split } from 'apollo-link'
6 | import { getMainDefinition } from 'apollo-utilities'
7 | import { AUTH_TOKEN } from './constant'
8 | import RootContainer from './components/RootContainer'
9 | import { ApolloProvider } from 'react-apollo'
10 |
11 | import 'tachyons'
12 | import './index.css'
13 |
14 | const httpLink = new HttpLink({ uri: 'http://localhost:4000' })
15 |
16 | const middlewareLink = new ApolloLink((operation, forward) => {
17 | // get the authentication token from local storage if it exists
18 | const tokenValue = localStorage.getItem(AUTH_TOKEN)
19 | // return the headers to the context so httpLink can read them
20 | operation.setContext({
21 | headers: {
22 | Authorization: tokenValue ? `Bearer ${tokenValue}` : '',
23 | },
24 | })
25 | return forward(operation)
26 | })
27 |
28 | // authenticated httplink
29 | const httpLinkAuth = middlewareLink.concat(httpLink)
30 |
31 | const wsLink = new WebSocketLink({
32 | uri: `ws://localhost:4000`,
33 | options: {
34 | reconnect: true,
35 | connectionParams: {
36 | Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN)}`,
37 | },
38 | },
39 | })
40 |
41 | const link = split(
42 | // split based on operation type
43 | ({ query }) => {
44 | const { kind, operation } = getMainDefinition(query)
45 | return kind === 'OperationDefinition' && operation === 'subscription'
46 | },
47 | wsLink,
48 | httpLinkAuth,
49 | )
50 |
51 | // apollo client setup
52 | const client = new ApolloClient({
53 | link: ApolloLink.from([link]),
54 | cache: new InMemoryCache(),
55 | connectToDevTools: true,
56 | })
57 |
58 | const token = localStorage.getItem(AUTH_TOKEN)
59 |
60 | ReactDOM.render(
61 |
62 |
63 | ,
64 | document.getElementById('root'),
65 | )
66 |
--------------------------------------------------------------------------------
/basic/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | .env
3 |
4 | # dependencies
5 | node_modules
6 |
7 | # testing
8 | coverage
9 | # production
10 | build
11 | .netlify
12 |
13 | # misc
14 | .DS_Store
15 | npm-debug.log
16 |
17 | #IDE
18 | .idea/*
19 | *.swp
20 | .vscode
--------------------------------------------------------------------------------
/basic/.install/index.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const {
3 | replaceInFiles,
4 | deploy,
5 | writeEnv,
6 | getInfo,
7 | makeSandboxEndpoint,
8 | } = require('graphql-boilerplate-install')
9 |
10 | module.exports = async ({ project, projectDir }) => {
11 | const templateName = 'graphql-boilerplate'
12 |
13 | const endpoint = await makeSandboxEndpoint(project)
14 |
15 | process.chdir('server/')
16 | replaceInFiles(
17 | ['src/index.js', 'package.json', 'prisma/prisma.yml'],
18 | templateName,
19 | project,
20 | )
21 | replaceInFiles(['src/index.js'], '__PRISMA_ENDPOINT__', endpoint)
22 | replaceInFiles(['prisma/prisma.yml'], '__PRISMA_ENDPOINT__', endpoint)
23 |
24 | console.log('Running $ prisma deploy...')
25 |
26 | await deploy(false)
27 | const info = await getInfo()
28 |
29 | process.chdir('../')
30 |
31 | replaceInFiles(
32 | ['server/src/generated/prisma-client/index.js'],
33 | '__PRISMA_ENDPOINT__',
34 | info.httpEndpoint,
35 | )
36 |
37 | console.log(`\
38 | Next steps:
39 | 1. Change directory: \`cd ${projectDir}/server\`
40 | 2. Start local server: \`yarn start\` (you can now open a Playground at http://localhost:4000)
41 | 3. Change directory: \`cd ..\`
42 | 4. Start React app: \`yarn start\`
43 | 5. Open browser: http://localhost:3000
44 | `)
45 | }
46 |
--------------------------------------------------------------------------------
/basic/.install/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "install",
3 | "version": "0.0.0",
4 | "devDependencies": {
5 | "graphql-boilerplate-install": "0.1.9"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/basic/.install/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | commander@^2.9.0:
6 | version "2.15.0"
7 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322"
8 |
9 | cross-spawn@5.1.0, cross-spawn@^5.1.0:
10 | version "5.1.0"
11 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
12 | dependencies:
13 | lru-cache "^4.0.1"
14 | shebang-command "^1.2.0"
15 | which "^1.2.9"
16 |
17 | graphql-boilerplate-install@0.1.9:
18 | version "0.1.9"
19 | resolved "https://registry.yarnpkg.com/graphql-boilerplate-install/-/graphql-boilerplate-install-0.1.9.tgz#bcd7e8dbb2b685820e78a76a5dbb6f24fcadf2c8"
20 | dependencies:
21 | cross-spawn "5.1.0"
22 | node-fetch "^2.1.2"
23 | npm-run "4.1.2"
24 | sillyname "^0.1.0"
25 |
26 | isexe@^2.0.0:
27 | version "2.0.0"
28 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
29 |
30 | lru-cache@^4.0.1:
31 | version "4.1.2"
32 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f"
33 | dependencies:
34 | pseudomap "^1.0.2"
35 | yallist "^2.1.2"
36 |
37 | minimist@^1.2.0:
38 | version "1.2.0"
39 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
40 |
41 | node-fetch@^2.1.2:
42 | version "2.1.2"
43 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
44 |
45 | npm-path@^2.0.2, npm-path@^2.0.3:
46 | version "2.0.4"
47 | resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64"
48 | dependencies:
49 | which "^1.2.10"
50 |
51 | npm-run@4.1.2:
52 | version "4.1.2"
53 | resolved "https://registry.yarnpkg.com/npm-run/-/npm-run-4.1.2.tgz#1030e1ec56908c89fcc3fa366d03a2c2ba98eb99"
54 | dependencies:
55 | cross-spawn "^5.1.0"
56 | minimist "^1.2.0"
57 | npm-path "^2.0.3"
58 | npm-which "^3.0.1"
59 | serializerr "^1.0.3"
60 | sync-exec "^0.6.2"
61 |
62 | npm-which@^3.0.1:
63 | version "3.0.1"
64 | resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa"
65 | dependencies:
66 | commander "^2.9.0"
67 | npm-path "^2.0.2"
68 | which "^1.2.10"
69 |
70 | protochain@^1.0.5:
71 | version "1.0.5"
72 | resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260"
73 |
74 | pseudomap@^1.0.2:
75 | version "1.0.2"
76 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
77 |
78 | serializerr@^1.0.3:
79 | version "1.0.3"
80 | resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91"
81 | dependencies:
82 | protochain "^1.0.5"
83 |
84 | shebang-command@^1.2.0:
85 | version "1.2.0"
86 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
87 | dependencies:
88 | shebang-regex "^1.0.0"
89 |
90 | shebang-regex@^1.0.0:
91 | version "1.0.0"
92 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
93 |
94 | sillyname@^0.1.0:
95 | version "0.1.0"
96 | resolved "https://registry.yarnpkg.com/sillyname/-/sillyname-0.1.0.tgz#cfd98858e2498671347775efe3bb5141f46c87d6"
97 |
98 | sync-exec@^0.6.2:
99 | version "0.6.2"
100 | resolved "https://registry.yarnpkg.com/sync-exec/-/sync-exec-0.6.2.tgz#717d22cc53f0ce1def5594362f3a89a2ebb91105"
101 |
102 | which@^1.2.10, which@^1.2.9:
103 | version "1.3.0"
104 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
105 | dependencies:
106 | isexe "^2.0.0"
107 |
108 | yallist@^2.1.2:
109 | version "2.1.2"
110 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
111 |
--------------------------------------------------------------------------------
/basic/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Prisma Examples
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 |
--------------------------------------------------------------------------------
/basic/README.md:
--------------------------------------------------------------------------------
1 | Boilerplate for a Basic Fullstack GraphQL App with React
2 |
3 |
4 |
5 | 
6 |
7 | 🚀 Bootstrap your fullstack GraphQL app within seconds
8 | Basic starter kit for a fullstack GraphQL app with React and Node.js - based on best practices from the GraphQL community.
9 |
10 | ## Features
11 |
12 | - **Scalable GraphQL server:** The server uses [`graphql-yoga`](https://github.com/prisma/graphql-yoga) which is based on Apollo Server & Express
13 | - **Pre-configured Apollo Client:** The project comes with a preconfigured setup for Apollo Client
14 | - **GraphQL database:** Includes GraphQL database binding to [Prisma](https://www.prismagraphql.com) (running on MySQL)
15 | - **Tooling**: Out-of-the-box support for [GraphQL Playground](https://github.com/prisma/graphql-playground) & [query performance tracing](https://github.com/apollographql/apollo-tracing)
16 | - **Extensible**: Simple and flexible [data model](./database/datamodel.graphql) – easy to adjust and extend
17 | - **No configuration overhead**: Preconfigured [`graphql-config`](https://github.com/prisma/graphql-config) setup
18 |
19 | For a fully-fledged **React & Apollo tutorial**, visit [How to GraphQL](https://www.howtographql.com/react-apollo/0-introduction/). You can more learn about the idea behind GraphQL boilerplates [here](https://blog.graph.cool/graphql-boilerplates-graphql-create-how-to-setup-a-graphql-project-6428be2f3a5).
20 |
21 | ## Requirements
22 |
23 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`:
24 |
25 | ```sh
26 | npm install -g graphql-cli
27 | ```
28 |
29 | ## Getting started
30 |
31 | ```sh
32 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `react-fullstack-basic` boilerplate
33 | graphql create my-app --boilerplate react-fullstack-basic
34 |
35 | # 2. When prompted, deploy the Prisma service to a _public cluster_
36 |
37 | # 3. Navigate into the `server` directory of the new project
38 | cd my-app/server
39 |
40 | # 4. Start the server
41 | yarn dev # runs server on http://localhost:4000, and opens GraphQL PLayground
42 |
43 | # 5. Open a new tab in the terminal and navigate back into my-app;
44 | # then run the app
45 | cd ..
46 | yarn start
47 | ```
48 |
49 | ## Documentation
50 |
51 | ### Commands
52 |
53 | * `yarn start` starts GraphQL server on `http://localhost:4000`
54 | * `yarn dev` starts GraphQL server on `http://localhost:4000` _and_ opens GraphQL Playground
55 | * `yarn playground` opens the GraphQL Playground for the `projects` from [`.graphqlconfig.yml`](./.graphqlconfig.yml)
56 | * `yarn prisma ` gives access to local version of Prisma CLI (e.g. `yarn prisma deploy`)
57 |
58 | > **Note**: We recommend that you're using `yarn dev` during development as it will give you access to the GraphQL API or your server (defined by the [application schema](./src/schema.graphql)) as well as to the Prisma API directly (defined by the [Prisma database schema](./generated/prisma.graphql)). If you're starting the server with `yarn start`, you'll only be able to access the API of the application schema.
59 |
60 | ### Server structure
61 |
62 | 
63 |
64 | | File name | Description |
65 | | :-- | :-- |
66 | | `├── .graphqlconfig.yml` | Configuration file based on [`graphql-config`](https://github.com/prisma/graphql-config) (e.g. used by GraphQL Playground).|
67 | | `└── database ` (_directory_) | _Contains all files that are related to the Prisma database service_ |\
68 | | ` ├── prisma.yml` | The root configuration file for your Prisma database service ([docs](https://www.prismagraphql.com/docs/reference/prisma.yml/overview-and-example-foatho8aip)) |
69 | | ` └── datamodel.graphql` | Defines your data model (written in [GraphQL SDL](https://blog.graph.cool/graphql-sdl-schema-definition-language-6755bcb9ce51)) |
70 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ |
71 | | ` ├── index.js` | The entry point for your GraphQL server |
72 | | ` ├── schema.graphql` | The **application schema** defining the API exposed to client applications |
73 | | ` └── generated` (_directory_) | _Contains generated files_ |
74 | | ` └── prisma.grapghql` | The **Prisma database schema** defining the Prisma GraphQL API |
75 |
76 | ## Contributing
77 |
78 | The GraphQL boilerplates are maintained by the GraphQL community, with official support from the [Apollo](https://dev-blog.apollodata.com) & [Graphcool](https://blog.graph.cool/) teams.
79 |
80 | Your feedback is **very helpful**, please share your opinion and thoughts! If you have any questions or want to contribute yourself, join the [`#graphql-boilerplate`](https://graphcool.slack.com/messages/graphql-boilerplate) channel on our [Slack](https://graphcool.slack.com/).
81 |
--------------------------------------------------------------------------------
/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-fullstack-basic",
3 | "version": "1.0.0",
4 | "devDependencies": {
5 | "react-scripts": "2.1.8"
6 | },
7 | "dependencies": {
8 | "apollo-boost": "0.4.9",
9 | "graphql": "14.7.0",
10 | "react": "16.14.0",
11 | "react-apollo": "2.5.8",
12 | "react-dom": "16.14.0",
13 | "react-modal": "3.16.1",
14 | "react-router-dom": "4.4.0-beta.8",
15 | "tachyons": "4.12.0"
16 | },
17 | "scripts": {
18 | "start": "react-scripts start",
19 | "build": "react-scripts build",
20 | "test": "react-scripts test --env=jsdom",
21 | "eject": "react-scripts eject"
22 | },
23 | "browserslist": [
24 | ">0.2%",
25 | "not dead",
26 | "not ie <= 11",
27 | "not op_mini all"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/basic/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/basic/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphql-boilerplates/react-fullstack-graphql/2c4bb39e51fc142acff6041f49901bced9ff9a94/basic/public/favicon.ico
--------------------------------------------------------------------------------
/basic/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React + GraphQL Fullstack Boilerplate
8 |
9 |
10 |
11 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/basic/server/.gitignore:
--------------------------------------------------------------------------------
1 | .env*
2 | dist
3 | package-lock.json
4 | node_modules
5 | .idea
6 | .vscode
7 | *.log
8 | yarn.lock
--------------------------------------------------------------------------------
/basic/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-boilerplate",
3 | "scripts": {
4 | "start": "node src/index.js",
5 | "prisma": "prisma"
6 | },
7 | "dependencies": {
8 | "graphql-yoga": "1.18.3",
9 | "prisma-client-lib": "1.34.12"
10 | },
11 | "devDependencies": {
12 | "prisma": "1.22.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/basic/server/prisma/datamodel.prisma:
--------------------------------------------------------------------------------
1 | type Post {
2 | id: ID! @id
3 | published: Boolean! @default(value: false)
4 | title: String!
5 | content: String!
6 | }
--------------------------------------------------------------------------------
/basic/server/prisma/prisma.yml:
--------------------------------------------------------------------------------
1 | # Specifies the HTTP endpoint of your Prisma API (deployed to a Prisma Demo server).
2 | endpoint: __PRISMA_ENDPOINT__
3 |
4 | # Defines your models, each model is mapped to the database as a table.
5 | datamodel: datamodel.prisma
6 |
7 | # Specifies the language and directory for the generated Prisma client.
8 | generate:
9 | - generator: javascript-client
10 | output: ../src/generated/prisma-client
11 |
12 | seed:
13 | import: seed.graphql
14 |
15 | # Ensures Prisma client is re-generated after a datamodel change.
16 | hooks:
17 | post-deploy:
18 | - prisma generate
19 |
20 | # If specified, the `secret` must be used to generate a JWT which is attached
21 | # to the `Authorization` header of HTTP requests made against the Prisma API.
22 | # Info: https://www.prisma.io/docs/prisma-graphql-api/reference/authentication-ghd4/
23 | # secret: mysecret123
--------------------------------------------------------------------------------
/basic/server/prisma/seed.graphql:
--------------------------------------------------------------------------------
1 | mutation {
2 | post1: createPost(
3 | data: {
4 | title: "Join us for GraphQL Conf 2019 in Berlin"
5 | content: "https://www.graphqlconf.org/"
6 | published: true
7 | }
8 | ) {
9 | id
10 | }
11 |
12 | post2: createPost(
13 | data: {
14 | title: "Subscribe to GraphQL Weekly for community news"
15 | content: "https://graphqlweekly.com/"
16 | published: true
17 | }
18 | ) {
19 | id
20 | }
21 |
22 | post3: createPost(
23 | data: {
24 | title: "Follow Prisma on Twitter"
25 | content: "https://twitter.com/prisma"
26 | }
27 | ) {
28 | id
29 | }
30 | }
--------------------------------------------------------------------------------
/basic/server/src/generated/prisma-client/index.d.ts:
--------------------------------------------------------------------------------
1 | // Code generated by Prisma (prisma@1.22.1). DO NOT EDIT.
2 | // Please don't change this file manually but run `prisma generate` to update it.
3 | // For more information, please read the docs: https://www.prisma.io/docs/prisma-client/
4 |
5 | import { DocumentNode, GraphQLSchema } from "graphql";
6 | import { makePrismaClientClass, BaseClientOptions } from "prisma-client-lib";
7 | import { typeDefs } from "./prisma-schema";
8 |
9 | type AtLeastOne }> = Partial &
10 | U[keyof U];
11 |
12 | export interface Exists {
13 | post: (where?: PostWhereInput) => Promise;
14 | }
15 |
16 | export interface Node {}
17 |
18 | export type FragmentableArray = Promise> & Fragmentable;
19 |
20 | export interface Fragmentable {
21 | $fragment(fragment: string | DocumentNode): Promise;
22 | }
23 |
24 | export interface Prisma {
25 | $exists: Exists;
26 | $graphql: (
27 | query: string,
28 | variables?: { [key: string]: any }
29 | ) => Promise;
30 |
31 | /**
32 | * Queries
33 | */
34 |
35 | post: (where: PostWhereUniqueInput) => PostPromise;
36 | posts: (
37 | args?: {
38 | where?: PostWhereInput;
39 | orderBy?: PostOrderByInput;
40 | skip?: Int;
41 | after?: String;
42 | before?: String;
43 | first?: Int;
44 | last?: Int;
45 | }
46 | ) => FragmentableArray;
47 | postsConnection: (
48 | args?: {
49 | where?: PostWhereInput;
50 | orderBy?: PostOrderByInput;
51 | skip?: Int;
52 | after?: String;
53 | before?: String;
54 | first?: Int;
55 | last?: Int;
56 | }
57 | ) => PostConnectionPromise;
58 | node: (args: { id: ID_Output }) => Node;
59 |
60 | /**
61 | * Mutations
62 | */
63 |
64 | createPost: (data: PostCreateInput) => PostPromise;
65 | updatePost: (
66 | args: { data: PostUpdateInput; where: PostWhereUniqueInput }
67 | ) => PostPromise;
68 | updateManyPosts: (
69 | args: { data: PostUpdateManyMutationInput; where?: PostWhereInput }
70 | ) => BatchPayloadPromise;
71 | upsertPost: (
72 | args: {
73 | where: PostWhereUniqueInput;
74 | create: PostCreateInput;
75 | update: PostUpdateInput;
76 | }
77 | ) => PostPromise;
78 | deletePost: (where: PostWhereUniqueInput) => PostPromise;
79 | deleteManyPosts: (where?: PostWhereInput) => BatchPayloadPromise;
80 |
81 | /**
82 | * Subscriptions
83 | */
84 |
85 | $subscribe: Subscription;
86 | }
87 |
88 | export interface Subscription {
89 | post: (
90 | where?: PostSubscriptionWhereInput
91 | ) => PostSubscriptionPayloadSubscription;
92 | }
93 |
94 | export interface ClientConstructor {
95 | new (options?: BaseClientOptions): T;
96 | }
97 |
98 | /**
99 | * Types
100 | */
101 |
102 | export type PostOrderByInput =
103 | | "id_ASC"
104 | | "id_DESC"
105 | | "published_ASC"
106 | | "published_DESC"
107 | | "title_ASC"
108 | | "title_DESC"
109 | | "content_ASC"
110 | | "content_DESC"
111 | | "createdAt_ASC"
112 | | "createdAt_DESC"
113 | | "updatedAt_ASC"
114 | | "updatedAt_DESC";
115 |
116 | export type MutationType = "CREATED" | "UPDATED" | "DELETED";
117 |
118 | export interface PostCreateInput {
119 | published?: Boolean;
120 | title: String;
121 | content: String;
122 | }
123 |
124 | export interface PostUpdateInput {
125 | published?: Boolean;
126 | title?: String;
127 | content?: String;
128 | }
129 |
130 | export interface PostWhereInput {
131 | id?: ID_Input;
132 | id_not?: ID_Input;
133 | id_in?: ID_Input[] | ID_Input;
134 | id_not_in?: ID_Input[] | ID_Input;
135 | id_lt?: ID_Input;
136 | id_lte?: ID_Input;
137 | id_gt?: ID_Input;
138 | id_gte?: ID_Input;
139 | id_contains?: ID_Input;
140 | id_not_contains?: ID_Input;
141 | id_starts_with?: ID_Input;
142 | id_not_starts_with?: ID_Input;
143 | id_ends_with?: ID_Input;
144 | id_not_ends_with?: ID_Input;
145 | published?: Boolean;
146 | published_not?: Boolean;
147 | title?: String;
148 | title_not?: String;
149 | title_in?: String[] | String;
150 | title_not_in?: String[] | String;
151 | title_lt?: String;
152 | title_lte?: String;
153 | title_gt?: String;
154 | title_gte?: String;
155 | title_contains?: String;
156 | title_not_contains?: String;
157 | title_starts_with?: String;
158 | title_not_starts_with?: String;
159 | title_ends_with?: String;
160 | title_not_ends_with?: String;
161 | content?: String;
162 | content_not?: String;
163 | content_in?: String[] | String;
164 | content_not_in?: String[] | String;
165 | content_lt?: String;
166 | content_lte?: String;
167 | content_gt?: String;
168 | content_gte?: String;
169 | content_contains?: String;
170 | content_not_contains?: String;
171 | content_starts_with?: String;
172 | content_not_starts_with?: String;
173 | content_ends_with?: String;
174 | content_not_ends_with?: String;
175 | AND?: PostWhereInput[] | PostWhereInput;
176 | OR?: PostWhereInput[] | PostWhereInput;
177 | NOT?: PostWhereInput[] | PostWhereInput;
178 | }
179 |
180 | export interface PostUpdateManyMutationInput {
181 | published?: Boolean;
182 | title?: String;
183 | content?: String;
184 | }
185 |
186 | export interface PostSubscriptionWhereInput {
187 | mutation_in?: MutationType[] | MutationType;
188 | updatedFields_contains?: String;
189 | updatedFields_contains_every?: String[] | String;
190 | updatedFields_contains_some?: String[] | String;
191 | node?: PostWhereInput;
192 | AND?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
193 | OR?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
194 | NOT?: PostSubscriptionWhereInput[] | PostSubscriptionWhereInput;
195 | }
196 |
197 | export type PostWhereUniqueInput = AtLeastOne<{
198 | id: ID_Input;
199 | }>;
200 |
201 | export interface NodeNode {
202 | id: ID_Output;
203 | }
204 |
205 | export interface AggregatePost {
206 | count: Int;
207 | }
208 |
209 | export interface AggregatePostPromise
210 | extends Promise,
211 | Fragmentable {
212 | count: () => Promise;
213 | }
214 |
215 | export interface AggregatePostSubscription
216 | extends Promise>,
217 | Fragmentable {
218 | count: () => Promise>;
219 | }
220 |
221 | export interface BatchPayload {
222 | count: Long;
223 | }
224 |
225 | export interface BatchPayloadPromise
226 | extends Promise,
227 | Fragmentable {
228 | count: () => Promise;
229 | }
230 |
231 | export interface BatchPayloadSubscription
232 | extends Promise>,
233 | Fragmentable {
234 | count: () => Promise>;
235 | }
236 |
237 | export interface PostPreviousValues {
238 | id: ID_Output;
239 | published: Boolean;
240 | title: String;
241 | content: String;
242 | }
243 |
244 | export interface PostPreviousValuesPromise
245 | extends Promise,
246 | Fragmentable {
247 | id: () => Promise;
248 | published: () => Promise;
249 | title: () => Promise;
250 | content: () => Promise;
251 | }
252 |
253 | export interface PostPreviousValuesSubscription
254 | extends Promise>,
255 | Fragmentable {
256 | id: () => Promise>;
257 | published: () => Promise>;
258 | title: () => Promise>;
259 | content: () => Promise>;
260 | }
261 |
262 | export interface PostEdge {
263 | cursor: String;
264 | }
265 |
266 | export interface PostEdgePromise extends Promise, Fragmentable {
267 | node: () => T;
268 | cursor: () => Promise;
269 | }
270 |
271 | export interface PostEdgeSubscription
272 | extends Promise>,
273 | Fragmentable {
274 | node: () => T;
275 | cursor: () => Promise>;
276 | }
277 |
278 | export interface PostSubscriptionPayload {
279 | mutation: MutationType;
280 | updatedFields?: String[];
281 | }
282 |
283 | export interface PostSubscriptionPayloadPromise
284 | extends Promise,
285 | Fragmentable {
286 | mutation: () => Promise;
287 | node: () => T;
288 | updatedFields: () => Promise;
289 | previousValues: () => T;
290 | }
291 |
292 | export interface PostSubscriptionPayloadSubscription
293 | extends Promise>,
294 | Fragmentable {
295 | mutation: () => Promise>;
296 | node: () => T;
297 | updatedFields: () => Promise>;
298 | previousValues: () => T;
299 | }
300 |
301 | export interface Post {
302 | id: ID_Output;
303 | published: Boolean;
304 | title: String;
305 | content: String;
306 | }
307 |
308 | export interface PostPromise extends Promise, Fragmentable {
309 | id: () => Promise;
310 | published: () => Promise;
311 | title: () => Promise;
312 | content: () => Promise;
313 | }
314 |
315 | export interface PostSubscription
316 | extends Promise>,
317 | Fragmentable {
318 | id: () => Promise>;
319 | published: () => Promise>;
320 | title: () => Promise>;
321 | content: () => Promise>;
322 | }
323 |
324 | export interface PostConnection {}
325 |
326 | export interface PostConnectionPromise
327 | extends Promise,
328 | Fragmentable {
329 | pageInfo: () => T;
330 | edges: >() => T;
331 | aggregate: () => T;
332 | }
333 |
334 | export interface PostConnectionSubscription
335 | extends Promise>,
336 | Fragmentable {
337 | pageInfo: () => T;
338 | edges: >>() => T;
339 | aggregate: () => T;
340 | }
341 |
342 | export interface PageInfo {
343 | hasNextPage: Boolean;
344 | hasPreviousPage: Boolean;
345 | startCursor?: String;
346 | endCursor?: String;
347 | }
348 |
349 | export interface PageInfoPromise extends Promise, Fragmentable {
350 | hasNextPage: () => Promise;
351 | hasPreviousPage: () => Promise;
352 | startCursor: () => Promise;
353 | endCursor: () => Promise;
354 | }
355 |
356 | export interface PageInfoSubscription
357 | extends Promise>,
358 | Fragmentable {
359 | hasNextPage: () => Promise>;
360 | hasPreviousPage: () => Promise>;
361 | startCursor: () => Promise>;
362 | endCursor: () => Promise>;
363 | }
364 |
365 | /*
366 | The `Boolean` scalar type represents `true` or `false`.
367 | */
368 | export type Boolean = boolean;
369 |
370 | export type Long = string;
371 |
372 | /*
373 | 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.
374 | */
375 | export type ID_Input = string | number;
376 | export type ID_Output = string;
377 |
378 | /*
379 | 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.
380 | */
381 | export type String = string;
382 |
383 | /*
384 | The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
385 | */
386 | export type Int = number;
387 |
388 | /**
389 | * Model Metadata
390 | */
391 |
392 | export const models = [
393 | {
394 | name: "Post",
395 | embedded: false
396 | }
397 | ];
398 |
399 | /**
400 | * Type Defs
401 | */
402 |
403 | export const prisma: Prisma;
404 |
--------------------------------------------------------------------------------
/basic/server/src/generated/prisma-client/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var prisma_lib_1 = require("prisma-client-lib");
4 | var typeDefs = require("./prisma-schema").typeDefs;
5 |
6 | var models = [
7 | {
8 | name: "Post",
9 | embedded: false
10 | }
11 | ];
12 | exports.Prisma = prisma_lib_1.makePrismaClientClass({
13 | typeDefs,
14 | models,
15 | endpoint: `__PRISMA_ENDPOINT__`
16 | });
17 | exports.prisma = new exports.Prisma();
18 | var models = [
19 | {
20 | name: "Post",
21 | embedded: false
22 | }
23 | ];
24 |
--------------------------------------------------------------------------------
/basic/server/src/generated/prisma-client/prisma-schema.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | typeDefs: /* GraphQL */ `type AggregatePost {
3 | count: Int!
4 | }
5 |
6 | type BatchPayload {
7 | count: Long!
8 | }
9 |
10 | scalar Long
11 |
12 | type Mutation {
13 | createPost(data: PostCreateInput!): Post!
14 | updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
15 | updateManyPosts(data: PostUpdateManyMutationInput!, where: PostWhereInput): BatchPayload!
16 | upsertPost(where: PostWhereUniqueInput!, create: PostCreateInput!, update: PostUpdateInput!): Post!
17 | deletePost(where: PostWhereUniqueInput!): Post
18 | deleteManyPosts(where: PostWhereInput): BatchPayload!
19 | }
20 |
21 | enum MutationType {
22 | CREATED
23 | UPDATED
24 | DELETED
25 | }
26 |
27 | interface Node {
28 | id: ID!
29 | }
30 |
31 | type PageInfo {
32 | hasNextPage: Boolean!
33 | hasPreviousPage: Boolean!
34 | startCursor: String
35 | endCursor: String
36 | }
37 |
38 | type Post {
39 | id: ID!
40 | published: Boolean!
41 | title: String!
42 | content: String!
43 | }
44 |
45 | type PostConnection {
46 | pageInfo: PageInfo!
47 | edges: [PostEdge]!
48 | aggregate: AggregatePost!
49 | }
50 |
51 | input PostCreateInput {
52 | published: Boolean
53 | title: String!
54 | content: String!
55 | }
56 |
57 | type PostEdge {
58 | node: Post!
59 | cursor: String!
60 | }
61 |
62 | enum PostOrderByInput {
63 | id_ASC
64 | id_DESC
65 | published_ASC
66 | published_DESC
67 | title_ASC
68 | title_DESC
69 | content_ASC
70 | content_DESC
71 | createdAt_ASC
72 | createdAt_DESC
73 | updatedAt_ASC
74 | updatedAt_DESC
75 | }
76 |
77 | type PostPreviousValues {
78 | id: ID!
79 | published: Boolean!
80 | title: String!
81 | content: String!
82 | }
83 |
84 | type PostSubscriptionPayload {
85 | mutation: MutationType!
86 | node: Post
87 | updatedFields: [String!]
88 | previousValues: PostPreviousValues
89 | }
90 |
91 | input PostSubscriptionWhereInput {
92 | mutation_in: [MutationType!]
93 | updatedFields_contains: String
94 | updatedFields_contains_every: [String!]
95 | updatedFields_contains_some: [String!]
96 | node: PostWhereInput
97 | AND: [PostSubscriptionWhereInput!]
98 | OR: [PostSubscriptionWhereInput!]
99 | NOT: [PostSubscriptionWhereInput!]
100 | }
101 |
102 | input PostUpdateInput {
103 | published: Boolean
104 | title: String
105 | content: String
106 | }
107 |
108 | input PostUpdateManyMutationInput {
109 | published: Boolean
110 | title: String
111 | content: String
112 | }
113 |
114 | input PostWhereInput {
115 | id: ID
116 | id_not: ID
117 | id_in: [ID!]
118 | id_not_in: [ID!]
119 | id_lt: ID
120 | id_lte: ID
121 | id_gt: ID
122 | id_gte: ID
123 | id_contains: ID
124 | id_not_contains: ID
125 | id_starts_with: ID
126 | id_not_starts_with: ID
127 | id_ends_with: ID
128 | id_not_ends_with: ID
129 | published: Boolean
130 | published_not: Boolean
131 | title: String
132 | title_not: String
133 | title_in: [String!]
134 | title_not_in: [String!]
135 | title_lt: String
136 | title_lte: String
137 | title_gt: String
138 | title_gte: String
139 | title_contains: String
140 | title_not_contains: String
141 | title_starts_with: String
142 | title_not_starts_with: String
143 | title_ends_with: String
144 | title_not_ends_with: String
145 | content: String
146 | content_not: String
147 | content_in: [String!]
148 | content_not_in: [String!]
149 | content_lt: String
150 | content_lte: String
151 | content_gt: String
152 | content_gte: String
153 | content_contains: String
154 | content_not_contains: String
155 | content_starts_with: String
156 | content_not_starts_with: String
157 | content_ends_with: String
158 | content_not_ends_with: String
159 | AND: [PostWhereInput!]
160 | OR: [PostWhereInput!]
161 | NOT: [PostWhereInput!]
162 | }
163 |
164 | input PostWhereUniqueInput {
165 | id: ID
166 | }
167 |
168 | type Query {
169 | post(where: PostWhereUniqueInput!): Post
170 | posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post]!
171 | postsConnection(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): PostConnection!
172 | node(id: ID!): Node
173 | }
174 |
175 | type Subscription {
176 | post(where: PostSubscriptionWhereInput): PostSubscriptionPayload
177 | }
178 | `
179 | }
180 |
--------------------------------------------------------------------------------
/basic/server/src/index.js:
--------------------------------------------------------------------------------
1 | const { GraphQLServer } = require('graphql-yoga')
2 | const { prisma } = require('./generated/prisma-client')
3 |
4 | const resolvers = {
5 | Query: {
6 | feed: (parent, args, context) => {
7 | return context.prisma.posts({ where: { published: true } })
8 | },
9 | drafts: (parent, args, context) => {
10 | return context.prisma.posts({ where: { published: false } })
11 | },
12 | post: (parent, { id }, context) => {
13 | return context.prisma.post({ id })
14 | },
15 | },
16 | Mutation: {
17 | createDraft(parent, { title, content }, context) {
18 | return context.prisma.createPost({
19 | title,
20 | content,
21 | })
22 | },
23 | deletePost(parent, { id }, context) {
24 | return context.prisma.deletePost({ id })
25 | },
26 | publish(parent, { id }, context) {
27 | return context.prisma.updatePost({
28 | where: { id },
29 | data: { published: true },
30 | })
31 | },
32 | },
33 | }
34 |
35 | const server = new GraphQLServer({
36 | typeDefs: './src/schema.graphql',
37 | resolvers,
38 | context: {
39 | prisma,
40 | },
41 | })
42 |
43 | server.start(() => console.log('Server is running on http://localhost:4000'))
44 |
--------------------------------------------------------------------------------
/basic/server/src/schema.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | feed: [Post!]!
3 | drafts: [Post!]!
4 | post(id: ID!): Post
5 | }
6 |
7 | type Mutation {
8 | createDraft(title: String!, content: String): Post
9 | deletePost(id: ID!): Post
10 | publish(id: ID!): Post
11 | }
12 |
13 | type Post {
14 | id: ID!
15 | published: Boolean!
16 | title: String!
17 | content: String!
18 | }
--------------------------------------------------------------------------------
/basic/src/assets/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/basic/src/assets/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/basic/src/components/CreatePage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { withRouter } from 'react-router-dom'
3 | import { Mutation } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 | import { DRAFTS_QUERY } from './DraftsPage'
6 |
7 | class CreatePage extends Component {
8 | state = {
9 | title: '',
10 | content: '',
11 | }
12 |
13 | render() {
14 | return (
15 | {
18 | const { drafts } = cache.readQuery({ query: DRAFTS_QUERY })
19 | cache.writeQuery({
20 | query: DRAFTS_QUERY,
21 | data: { drafts: drafts.concat([data.createDraft]) },
22 | })
23 | }}
24 | >
25 | {(createDraft, { data, loading, error }) => {
26 | return (
27 |
68 | )
69 | }}
70 |
71 | )
72 | }
73 |
74 | }
75 |
76 | const CREATE_DRAFT_MUTATION = gql`
77 | mutation CreateDraftMutation($title: String!, $content: String!) {
78 | createDraft(title: $title, content: $content) {
79 | id
80 | title
81 | content
82 | }
83 | }
84 | `
85 |
86 | export default withRouter(CreatePage)
87 |
--------------------------------------------------------------------------------
/basic/src/components/DetailPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import { Query, Mutation } from 'react-apollo'
3 | import { withRouter } from 'react-router-dom'
4 | import { gql } from 'apollo-boost'
5 | import { DRAFTS_QUERY } from './DraftsPage'
6 | import { FEED_QUERY } from './FeedPage'
7 |
8 | class DetailPage extends Component {
9 | render() {
10 | return (
11 |
12 | {({ data, loading, error }) => {
13 | if (loading) {
14 | return (
15 |
18 | )
19 | }
20 |
21 | if (error) {
22 | return (
23 |
24 |
An unexpected error occured.
25 |
26 | )
27 | }
28 |
29 | const { post } = data
30 | const action = this._renderAction(post)
31 | return (
32 |
33 | {data.post.title}
34 | {data.post.content}
35 | {action}
36 |
37 | )
38 | }}
39 |
40 | )
41 | }
42 |
43 | _renderAction = ({ id, published }) => {
44 | const publishMutation = (
45 | {
48 | const { drafts } = cache.readQuery({ query: DRAFTS_QUERY })
49 | const { feed } = cache.readQuery({ query: FEED_QUERY })
50 | cache.writeQuery({
51 | query: FEED_QUERY,
52 | data: { feed: feed.concat([data.publish]) },
53 | })
54 | cache.writeQuery({
55 | query: DRAFTS_QUERY,
56 | data: {
57 | drafts: drafts.filter(draft => draft.id !== data.publish.id),
58 | },
59 | })
60 | }}
61 | >
62 | {(publish, { data, loading, error }) => {
63 | return (
64 | {
67 | await publish({
68 | variables: { id },
69 | })
70 | this.props.history.replace('/')
71 | }}
72 | >
73 | Publish
74 |
75 | )
76 | }}
77 |
78 | )
79 | const deleteMutation = (
80 | {
83 | if (published) {
84 | const { feed } = cache.readQuery({ query: FEED_QUERY })
85 | cache.writeQuery({
86 | query: FEED_QUERY,
87 | data: {
88 | feed: feed.filter(post => post.id !== data.deletePost.id),
89 | },
90 | })
91 | } else {
92 | const { drafts } = cache.readQuery({ query: DRAFTS_QUERY })
93 | cache.writeQuery({
94 | query: DRAFTS_QUERY,
95 | data: {
96 | drafts: drafts.filter(draft => draft.id !== data.deletePost.id),
97 | },
98 | })
99 | }
100 | }}
101 | >
102 | {(deletePost, { data, loading, error }) => {
103 | return (
104 | {
107 | await deletePost({
108 | variables: { id },
109 | })
110 | this.props.history.replace('/')
111 | }}
112 | >
113 | Delete
114 |
115 | )
116 | }}
117 |
118 | )
119 | if (!published) {
120 | return (
121 |
122 | {publishMutation}
123 | {deleteMutation}
124 |
125 | )
126 | }
127 | return deleteMutation
128 | }
129 |
130 | }
131 |
132 | const POST_QUERY = gql`
133 | query PostQuery($id: ID!) {
134 | post(id: $id) {
135 | id
136 | title
137 | content
138 | published
139 | }
140 | }
141 | `
142 |
143 | const PUBLISH_MUTATION = gql`
144 | mutation PublishMutation($id: ID!) {
145 | publish(id: $id) {
146 | id
147 | published
148 | }
149 | }
150 | `
151 |
152 | const DELETE_MUTATION = gql`
153 | mutation DeleteMutatoin($id: ID!) {
154 | deletePost(id: $id) {
155 | id
156 | }
157 | }
158 | `
159 |
160 | export default withRouter(DetailPage)
161 |
--------------------------------------------------------------------------------
/basic/src/components/DraftsPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import Post from '../components/Post'
3 | import { Query } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 |
6 | export default class DraftsPage extends Component {
7 | render() {
8 | return (
9 |
10 | {({ data, loading, error, refetch }) => {
11 | if (loading) {
12 | return (
13 |
16 | )
17 | }
18 |
19 | if (error) {
20 | return (
21 |
22 |
An unexpected error occured.
23 |
24 | )
25 | }
26 | return (
27 |
28 |
29 |
Drafts
30 |
31 | {data.drafts &&
32 | data.drafts.map(draft => (
33 | refetch()}
37 | isDraft={!draft.published}
38 | />
39 | ))}
40 | {this.props.children}
41 |
42 | )
43 | }}
44 |
45 | )
46 | }
47 | }
48 |
49 | export const DRAFTS_QUERY = gql`
50 | query DraftsQuery {
51 | drafts {
52 | id
53 | content
54 | title
55 | published
56 | }
57 | }
58 | `
59 |
--------------------------------------------------------------------------------
/basic/src/components/FeedPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react'
2 | import Post from '../components/Post'
3 | import { Query } from 'react-apollo'
4 | import { gql } from 'apollo-boost'
5 |
6 | export default class FeedPage extends Component {
7 | render() {
8 | return (
9 |
10 | {({ data, loading, error, refetch }) => {
11 | if (loading) {
12 | return (
13 |
16 | )
17 | }
18 |
19 | if (error) {
20 | return (
21 |
22 |
An unexpected error occured.
23 |
24 | )
25 | }
26 |
27 | return (
28 |
29 | Feed
30 | {data.feed &&
31 | data.feed.map(post => (
32 | refetch()}
36 | isDraft={!post.published}
37 | />
38 | ))}
39 | {this.props.children}
40 |
41 | )
42 | }}
43 |
44 | )
45 | }
46 | }
47 |
48 | export const FEED_QUERY = gql`
49 | query FeedQuery {
50 | feed {
51 | id
52 | content
53 | title
54 | published
55 | }
56 | }
57 | `
58 |
--------------------------------------------------------------------------------
/basic/src/components/Post.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | export default class Post extends Component {
5 | render() {
6 | let title = this.props.post.title
7 | if (this.props.isDraft) {
8 | title = `${title} (Draft)`
9 | }
10 |
11 | return (
12 |
13 | {title}
14 | {this.props.post.content}
15 |
16 | )
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/basic/src/constants/modalStyle.js:
--------------------------------------------------------------------------------
1 | const modalStyle = {
2 | overlay: {
3 | zIndex: 20,
4 | backgroundColor: 'rgba(255,255,255,.6)',
5 | display: 'flex',
6 | alignItems: 'center',
7 | justifyContent: 'center',
8 | },
9 | content: {
10 | position: 'relative',
11 | width: 600,
12 | height: 'auto',
13 | top: 'initial',
14 | left: 'initial',
15 | right: 'initial',
16 | bottom: 'initial',
17 | borderRadius: 2,
18 | padding: 0,
19 | border: 'none',
20 | background: 'none',
21 | boxShadow: '0 1px 7px rgba(0,0,0,.2)',
22 | },
23 | }
24 |
25 | export default modalStyle
26 |
--------------------------------------------------------------------------------
/basic/src/index.css:
--------------------------------------------------------------------------------
1 | @import 'https://fonts.googleapis.com/css?family=Open+Sans:300, 400';
2 |
3 | body {
4 | margin: 0;
5 | padding: 0;
6 | font-family: 'Open Sans', sans-serif;
7 | background: rgba(0, 0, 0, 0.05);
8 | }
9 |
10 | html {
11 | box-sizing: border-box;
12 | }
13 |
14 | *,
15 | *:before,
16 | *:after {
17 | box-sizing: inherit;
18 | }
19 |
20 | .post {
21 | box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
22 | width: 350px;
23 | height: 350px;
24 | flex: 0 0 350px;
25 | }
26 |
27 | .post .description {
28 | flex: 1;
29 | padding-left: 25px;
30 | font-size: 25px;
31 | }
32 |
33 | .detail {
34 | width: 600px;
35 | height: 600px;
36 | flex: 0 0 600px;
37 | }
38 |
39 | .detail .description {
40 | flex: 1;
41 | padding-left: 40px;
42 | font-size: 38px;
43 | }
44 |
45 | .title {
46 | font-size: 42px;
47 | }
48 |
49 | .content {
50 | font-size: 18px;
51 | }
52 |
53 | .new-post {
54 | background-color: rgba(0, 0, 0, 0.04);
55 | }
56 |
57 | .close {
58 | opacity: 0.5;
59 | margin-top: 60px;
60 | margin-right: 60px;
61 | }
62 |
63 | .close img {
64 | width: 20px;
65 | height: 20px;
66 | }
67 |
--------------------------------------------------------------------------------
/basic/src/index.js:
--------------------------------------------------------------------------------
1 | import React, {Fragment} from 'react'
2 | import ReactDOM from 'react-dom'
3 | import {
4 | NavLink,
5 | Link,
6 | BrowserRouter as Router,
7 | Route,
8 | Switch,
9 | } from 'react-router-dom'
10 | import { ApolloProvider } from 'react-apollo'
11 | import ApolloClient from 'apollo-boost'
12 |
13 | import FeedPage from './components/FeedPage'
14 | import DraftsPage from './components/DraftsPage'
15 | import CreatePage from './components/CreatePage'
16 | import DetailPage from './components/DetailPage'
17 |
18 | import 'tachyons'
19 | import './index.css'
20 |
21 | const client = new ApolloClient({ uri: 'http://localhost:4000' })
22 |
23 | ReactDOM.render(
24 |
25 |
26 |
27 |
28 |
33 | Blog
34 |
35 |
42 | Feed
43 |
44 |
51 | Drafts
52 |
53 |
57 | + Create Draft
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | ,
71 | document.getElementById('root'),
72 | )
73 |
--------------------------------------------------------------------------------
/minimal/README.md:
--------------------------------------------------------------------------------
1 | Boilerplate for a Basic Fullstack GraphQL App with React
2 |
3 |
4 |
5 | 
6 |
7 | 🚀 Bootstrap your fullstack GraphQL app within seconds
8 | Basic starter kit for a fullstack GraphQL app with React and Node.js.
9 |
10 | ## Features
11 |
12 | - **Scalable GraphQL server:** The server uses [`graphql-yoga`](https://github.com/prisma/graphql-yoga) which is based on Apollo Server & Express
13 | - **Pre-configured Apollo Client:** The project comes with a preconfigured setup for Apollo Client
14 | - **Simple Hello World example:** Where it either returns `Hello !` if name argument is provided or else it returns `Hello World!`
15 |
16 | For a fully-fledged **React & Apollo tutorial**, visit [How to GraphQL](https://www.howtographql.com/react-apollo/0-introduction/).
17 |
18 | ### Commands
19 |
20 | * `yarn start` or `npm run start` starts GraphQL server on `http://localhost:4000`
21 |
22 | ## Contributing
23 |
24 | The GraphQL boilerplates are maintained by the GraphQL community, with official support from the [Apollo](https://www.apollographql.com/) & [Prisma](https://www.prisma.io) teams.
25 |
26 | Your feedback is **very helpful**, please share your opinion and thoughts! If you have any questions or want to contribute yourself, join the `#graphql-boilerplate` channel on our [Slack](https://slack.prisma.io/).
--------------------------------------------------------------------------------
/minimal/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minimal",
3 | "dependencies": {
4 | "apollo-boost": "0.4.9",
5 | "graphql": "14.7.0",
6 | "react": "16.14.0",
7 | "react-apollo": "2.5.8",
8 | "react-dom": "16.14.0",
9 | "react-scripts": "2.1.8"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/minimal/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphql-boilerplates/react-fullstack-graphql/2c4bb39e51fc142acff6041f49901bced9ff9a94/minimal/public/favicon.ico
--------------------------------------------------------------------------------
/minimal/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 | You need to enable JavaScript to run this app.
27 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/minimal/server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package.json.lock
--------------------------------------------------------------------------------
/minimal/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-boilerplate",
3 | "scripts": {
4 | "start": "node src/index.js"
5 | },
6 | "dependencies": {
7 | "graphql-yoga": "1.18.3"
8 | }
9 | }
--------------------------------------------------------------------------------
/minimal/server/src/index.js:
--------------------------------------------------------------------------------
1 | const { GraphQLServer } = require('graphql-yoga')
2 |
3 | const typeDefs = `
4 | type Query {
5 | hello(name: String): String
6 | }
7 | `
8 |
9 | const resolvers = {
10 | Query: {
11 | hello: (_, args) => `Hello ${args.name || 'World'}!`,
12 | },
13 | }
14 |
15 | const server = new GraphQLServer({ typeDefs, resolvers })
16 | server.start(() => console.log(`Server is running at http://localhost:4000`))
17 |
--------------------------------------------------------------------------------
/minimal/server/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/aws-lambda@8.10.13":
6 | version "8.10.13"
7 | resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.13.tgz#92cc06b1cc88b5d0b327d2671dcf3daea96923a5"
8 | integrity sha512-a1sC60Bqll4N2RYnd4+XuynrVd8LO+uZrgwCVaAER0ldMQ00LRM4iTjU2ulPoQF6P5bHZK5hL/6IF9088VJhUA==
9 |
10 | "@types/body-parser@*":
11 | version "1.17.0"
12 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c"
13 | integrity sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==
14 | dependencies:
15 | "@types/connect" "*"
16 | "@types/node" "*"
17 |
18 | "@types/connect@*":
19 | version "3.4.32"
20 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28"
21 | integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==
22 | dependencies:
23 | "@types/node" "*"
24 |
25 | "@types/cors@^2.8.4":
26 | version "2.8.4"
27 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.4.tgz#50991a759a29c0b89492751008c6af7a7c8267b0"
28 | integrity sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==
29 | dependencies:
30 | "@types/express" "*"
31 |
32 | "@types/events@*":
33 | version "1.2.0"
34 | resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86"
35 | integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==
36 |
37 | "@types/express-serve-static-core@*":
38 | version "4.16.0"
39 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7"
40 | integrity sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==
41 | dependencies:
42 | "@types/events" "*"
43 | "@types/node" "*"
44 | "@types/range-parser" "*"
45 |
46 | "@types/express@*", "@types/express@^4.11.1":
47 | version "4.16.0"
48 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19"
49 | integrity sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==
50 | dependencies:
51 | "@types/body-parser" "*"
52 | "@types/express-serve-static-core" "*"
53 | "@types/serve-static" "*"
54 |
55 | "@types/graphql-deduplicator@^2.0.0":
56 | version "2.0.0"
57 | resolved "https://registry.yarnpkg.com/@types/graphql-deduplicator/-/graphql-deduplicator-2.0.0.tgz#9e577b8f3feb3d067b0ca756f4a1fb356d533922"
58 | integrity sha512-swUwj5hWF1yFzbUXStLJrUa0ksAt11B8+SwhsAjQAX0LYJ1LLioAyuDcJ9bovWbsNzIXJYXLvljSPQw8nR728w==
59 |
60 | "@types/graphql@^14.0.0":
61 | version "14.0.3"
62 | resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-14.0.3.tgz#389e2e5b83ecdb376d9f98fae2094297bc112c1c"
63 | integrity sha512-TcFkpEjcQK7w8OcrQcd7iIBPjU0rdyi3ldj6d0iJ4PPSzbWqPBvXj9KSwO14hTOX2dm9RoiH7VuxksJLNYdXUQ==
64 |
65 | "@types/mime@*":
66 | version "2.0.0"
67 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b"
68 | integrity sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==
69 |
70 | "@types/node@*":
71 | version "10.12.12"
72 | resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.12.tgz#e15a9d034d9210f00320ef718a50c4a799417c47"
73 | integrity sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==
74 |
75 | "@types/range-parser@*":
76 | version "1.2.2"
77 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d"
78 | integrity sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==
79 |
80 | "@types/serve-static@*":
81 | version "1.13.2"
82 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48"
83 | integrity sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==
84 | dependencies:
85 | "@types/express-serve-static-core" "*"
86 | "@types/mime" "*"
87 |
88 | "@types/zen-observable@^0.5.3":
89 | version "0.5.4"
90 | resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.4.tgz#b863a4191e525206819e008097ebf0fb2e3a1cdc"
91 | integrity sha512-sW6xN96wUak4tgc89d0tbTg7QDGYhGv5hvQIS6h4mRCd8h2btiZ80loPU8cyLwsBbA4ZeQt0FjvUhJ4rNhdsGg==
92 |
93 | accepts@~1.3.5:
94 | version "1.3.5"
95 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
96 | integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I=
97 | dependencies:
98 | mime-types "~2.1.18"
99 | negotiator "0.6.1"
100 |
101 | apollo-cache-control@^0.1.0:
102 | version "0.1.1"
103 | resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.1.1.tgz#173d14ceb3eb9e7cb53de7eb8b61bee6159d4171"
104 | integrity sha512-XJQs167e9u+e5ybSi51nGYr70NPBbswdvTEHtbtXbwkZ+n9t0SLPvUcoqceayOSwjK1XYOdU/EKPawNdb3rLQA==
105 | dependencies:
106 | graphql-extensions "^0.0.x"
107 |
108 | apollo-link@^1.2.3:
109 | version "1.2.4"
110 | resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.4.tgz#ab4d21d2e428db848e88b5e8f4adc717b19c954b"
111 | integrity sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==
112 | dependencies:
113 | apollo-utilities "^1.0.0"
114 | zen-observable-ts "^0.8.11"
115 |
116 | apollo-server-core@^1.3.6, apollo-server-core@^1.4.0:
117 | version "1.4.0"
118 | resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.4.0.tgz#4faff7f110bfdd6c3f47008302ae24140f94c592"
119 | integrity sha512-BP1Vh39krgEjkQxbjTdBURUjLHbFq1zeOChDJgaRsMxGtlhzuLWwwC6lLdPatN8jEPbeHq8Tndp9QZ3iQZOKKA==
120 | dependencies:
121 | apollo-cache-control "^0.1.0"
122 | apollo-tracing "^0.1.0"
123 | graphql-extensions "^0.0.x"
124 |
125 | apollo-server-express@^1.3.6:
126 | version "1.4.0"
127 | resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.4.0.tgz#7d7c58d6d6f9892b83fe575669093bb66738b125"
128 | integrity sha512-zkH00nxhLnJfO0HgnNPBTfZw8qI5ILaPZ5TecMCI9+Y9Ssr2b0bFr9pBRsXy9eudPhI+/O4yqegSUsnLdF/CPw==
129 | dependencies:
130 | apollo-server-core "^1.4.0"
131 | apollo-server-module-graphiql "^1.4.0"
132 |
133 | apollo-server-lambda@1.3.6:
134 | version "1.3.6"
135 | resolved "https://registry.yarnpkg.com/apollo-server-lambda/-/apollo-server-lambda-1.3.6.tgz#bdaac37f143c6798e40b8ae75580ba673cea260e"
136 | integrity sha1-varDfxQ8Z5jkC4rnVYC6ZzzqJg4=
137 | dependencies:
138 | apollo-server-core "^1.3.6"
139 | apollo-server-module-graphiql "^1.3.4"
140 |
141 | apollo-server-module-graphiql@^1.3.4, apollo-server-module-graphiql@^1.4.0:
142 | version "1.4.0"
143 | resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.4.0.tgz#c559efa285578820709f1769bb85d3b3eed3d8ec"
144 | integrity sha512-GmkOcb5he2x5gat+TuiTvabnBf1m4jzdecal3XbXBh/Jg+kx4hcvO3TTDFQ9CuTprtzdcVyA11iqG7iOMOt7vA==
145 |
146 | apollo-tracing@^0.1.0:
147 | version "0.1.4"
148 | resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.1.4.tgz#5b8ae1b01526b160ee6e552a7f131923a9aedcc7"
149 | integrity sha512-Uv+1nh5AsNmC3m130i2u3IqbS+nrxyVV3KYimH5QKsdPjxxIQB3JAT+jJmpeDxBel8gDVstNmCh82QSLxLSIdQ==
150 | dependencies:
151 | graphql-extensions "~0.0.9"
152 |
153 | apollo-upload-server@^7.0.0:
154 | version "7.1.0"
155 | resolved "https://registry.yarnpkg.com/apollo-upload-server/-/apollo-upload-server-7.1.0.tgz#21e07b52252b3749b913468599813e13cfca805f"
156 | integrity sha512-cD9ReCeyurYwZyEDqJYb5TOc9dt8yhPzS+MtrY3iJdqw+pqiiyPngAvVXHjN+Ca7Lajvom4/AT/PBrYVDMM3Kw==
157 | dependencies:
158 | busboy "^0.2.14"
159 | fs-capacitor "^1.0.0"
160 | http-errors "^1.7.0"
161 | object-path "^0.11.4"
162 |
163 | apollo-utilities@^1.0.0, apollo-utilities@^1.0.1:
164 | version "1.0.26"
165 | resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.26.tgz#589c66bf4d16223531351cf667a230c787def1da"
166 | integrity sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==
167 | dependencies:
168 | fast-json-stable-stringify "^2.0.0"
169 |
170 | array-flatten@1.1.1:
171 | version "1.1.1"
172 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
173 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
174 |
175 | async-limiter@~1.0.0:
176 | version "1.0.0"
177 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
178 | integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
179 |
180 | backo2@^1.0.2:
181 | version "1.0.2"
182 | resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
183 | integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
184 |
185 | body-parser-graphql@1.1.0:
186 | version "1.1.0"
187 | resolved "https://registry.yarnpkg.com/body-parser-graphql/-/body-parser-graphql-1.1.0.tgz#80a80353c7cb623562fd375750dfe018d75f0f7c"
188 | integrity sha512-bOBF4n1AnUjcY1SzLeibeIx4XOuYqEkjn/Lm4yKhnN6KedoXMv4hVqgcKHGRnxOMJP64tErqrQU+4cihhpbJXg==
189 | dependencies:
190 | body-parser "^1.18.2"
191 |
192 | body-parser@1.18.3, body-parser@^1.18.2:
193 | version "1.18.3"
194 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
195 | integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
196 | dependencies:
197 | bytes "3.0.0"
198 | content-type "~1.0.4"
199 | debug "2.6.9"
200 | depd "~1.1.2"
201 | http-errors "~1.6.3"
202 | iconv-lite "0.4.23"
203 | on-finished "~2.3.0"
204 | qs "6.5.2"
205 | raw-body "2.3.3"
206 | type-is "~1.6.16"
207 |
208 | buffer-from@^1.0.0:
209 | version "1.1.1"
210 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
211 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
212 |
213 | busboy@^0.2.14:
214 | version "0.2.14"
215 | resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
216 | integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
217 | dependencies:
218 | dicer "0.2.5"
219 | readable-stream "1.1.x"
220 |
221 | busboy@^0.3.1:
222 | version "0.3.1"
223 | resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
224 | integrity sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==
225 | dependencies:
226 | dicer "0.3.0"
227 |
228 | bytes@3.0.0:
229 | version "3.0.0"
230 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
231 | integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
232 |
233 | content-disposition@0.5.2:
234 | version "0.5.2"
235 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
236 | integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
237 |
238 | content-type@~1.0.4:
239 | version "1.0.4"
240 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
241 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
242 |
243 | cookie-signature@1.0.6:
244 | version "1.0.6"
245 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
246 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
247 |
248 | cookie@0.3.1:
249 | version "0.3.1"
250 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
251 | integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
252 |
253 | core-js@^2.5.3:
254 | version "2.6.0"
255 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4"
256 | integrity sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==
257 |
258 | core-util-is@~1.0.0:
259 | version "1.0.2"
260 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
261 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
262 |
263 | cors@^2.8.4:
264 | version "2.8.5"
265 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
266 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
267 | dependencies:
268 | object-assign "^4"
269 | vary "^1"
270 |
271 | debug@2.6.9:
272 | version "2.6.9"
273 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
274 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
275 | dependencies:
276 | ms "2.0.0"
277 |
278 | depd@~1.1.2:
279 | version "1.1.2"
280 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
281 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
282 |
283 | deprecated-decorator@^0.1.6:
284 | version "0.1.6"
285 | resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37"
286 | integrity sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=
287 |
288 | destroy@~1.0.4:
289 | version "1.0.4"
290 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
291 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
292 |
293 | dicer@0.2.5:
294 | version "0.2.5"
295 | resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
296 | integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
297 | dependencies:
298 | readable-stream "1.1.x"
299 | streamsearch "0.1.2"
300 |
301 | dicer@0.3.0:
302 | version "0.3.0"
303 | resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
304 | integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==
305 | dependencies:
306 | streamsearch "0.1.2"
307 |
308 | ee-first@1.1.1:
309 | version "1.1.1"
310 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
311 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
312 |
313 | encodeurl@~1.0.2:
314 | version "1.0.2"
315 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
316 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
317 |
318 | escape-html@~1.0.3:
319 | version "1.0.3"
320 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
321 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
322 |
323 | etag@~1.8.1:
324 | version "1.8.1"
325 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
326 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
327 |
328 | eventemitter3@^3.1.0:
329 | version "3.1.0"
330 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
331 | integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==
332 |
333 | express@^4.16.3:
334 | version "4.16.4"
335 | resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
336 | integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
337 | dependencies:
338 | accepts "~1.3.5"
339 | array-flatten "1.1.1"
340 | body-parser "1.18.3"
341 | content-disposition "0.5.2"
342 | content-type "~1.0.4"
343 | cookie "0.3.1"
344 | cookie-signature "1.0.6"
345 | debug "2.6.9"
346 | depd "~1.1.2"
347 | encodeurl "~1.0.2"
348 | escape-html "~1.0.3"
349 | etag "~1.8.1"
350 | finalhandler "1.1.1"
351 | fresh "0.5.2"
352 | merge-descriptors "1.0.1"
353 | methods "~1.1.2"
354 | on-finished "~2.3.0"
355 | parseurl "~1.3.2"
356 | path-to-regexp "0.1.7"
357 | proxy-addr "~2.0.4"
358 | qs "6.5.2"
359 | range-parser "~1.2.0"
360 | safe-buffer "5.1.2"
361 | send "0.16.2"
362 | serve-static "1.13.2"
363 | setprototypeof "1.1.0"
364 | statuses "~1.4.0"
365 | type-is "~1.6.16"
366 | utils-merge "1.0.1"
367 | vary "~1.1.2"
368 |
369 | fast-json-stable-stringify@^2.0.0:
370 | version "2.0.0"
371 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
372 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
373 |
374 | finalhandler@1.1.1:
375 | version "1.1.1"
376 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
377 | integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
378 | dependencies:
379 | debug "2.6.9"
380 | encodeurl "~1.0.2"
381 | escape-html "~1.0.3"
382 | on-finished "~2.3.0"
383 | parseurl "~1.3.2"
384 | statuses "~1.4.0"
385 | unpipe "~1.0.0"
386 |
387 | forwarded@~0.1.2:
388 | version "0.1.2"
389 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
390 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
391 |
392 | fresh@0.5.2:
393 | version "0.5.2"
394 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
395 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
396 |
397 | fs-capacitor@^1.0.0:
398 | version "1.0.1"
399 | resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-1.0.1.tgz#ff9dbfa14dfaf4472537720f19c3088ed9278df0"
400 | integrity sha512-XdZK0Q78WP29Vm3FGgJRhRhrBm51PagovzWtW2kJ3Q6cYJbGtZqWSGTSPwvtEkyjIirFd7b8Yes/dpOYjt4RRQ==
401 |
402 | fs-capacitor@^2.0.4:
403 | version "2.0.4"
404 | resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c"
405 | integrity sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==
406 |
407 | graphql-deduplicator@^2.0.1:
408 | version "2.0.2"
409 | resolved "https://registry.yarnpkg.com/graphql-deduplicator/-/graphql-deduplicator-2.0.2.tgz#d8608161cf6be97725e178df0c41f6a1f9f778f3"
410 | integrity sha512-0CGmTmQh4UvJfsaTPppJAcHwHln8Ayat7yXXxdnuWT+Mb1dBzkbErabCWzjXyKh/RefqlGTTA7EQOZHofMaKJA==
411 |
412 | graphql-extensions@^0.0.x, graphql-extensions@~0.0.9:
413 | version "0.0.10"
414 | resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.0.10.tgz#34bdb2546d43f6a5bc89ab23c295ec0466c6843d"
415 | integrity sha512-TnQueqUDCYzOSrpQb3q1ngDSP2otJSF+9yNLrQGPzkMsvnQ+v6e2d5tl+B35D4y+XpmvVnAn4T3ZK28mkILveA==
416 | dependencies:
417 | core-js "^2.5.3"
418 | source-map-support "^0.5.1"
419 |
420 | graphql-import@^0.7.0:
421 | version "0.7.1"
422 | resolved "https://registry.yarnpkg.com/graphql-import/-/graphql-import-0.7.1.tgz#4add8d91a5f752d764b0a4a7a461fcd93136f223"
423 | integrity sha512-YpwpaPjRUVlw2SN3OPljpWbVRWAhMAyfSba5U47qGMOSsPLi2gYeJtngGpymjm9nk57RFWEpjqwh4+dpYuFAPw==
424 | dependencies:
425 | lodash "^4.17.4"
426 | resolve-from "^4.0.0"
427 |
428 | graphql-middleware@4.0.1:
429 | version "4.0.1"
430 | resolved "https://registry.yarnpkg.com/graphql-middleware/-/graphql-middleware-4.0.1.tgz#8c627b22cc046a47e9474a813cf9e0bd50fa0c4b"
431 | integrity sha512-r9r+pcHV4yZW7LAOcjQYTbNY6nR9SrLgpVZKbrtgXxpQW/MUc1N8q3PESciebvp5s0EEUgRchcRjUkyaArCIFw==
432 | dependencies:
433 | graphql-tools "^4.0.5"
434 |
435 | graphql-playground-html@1.6.12:
436 | version "1.6.12"
437 | resolved "https://registry.yarnpkg.com/graphql-playground-html/-/graphql-playground-html-1.6.12.tgz#8b3b34ab6013e2c877f0ceaae478fafc8ca91b85"
438 | integrity sha512-yOYFwwSMBL0MwufeL8bkrNDgRE7eF/kTHiwrqn9FiR9KLcNIl1xw9l9a+6yIRZM56JReQOHpbQFXTZn1IuSKRg==
439 |
440 | graphql-playground-middleware-express@1.7.11:
441 | version "1.7.11"
442 | resolved "https://registry.yarnpkg.com/graphql-playground-middleware-express/-/graphql-playground-middleware-express-1.7.11.tgz#bbffd784a37133bfa7165bdd8f429081dbf4bcf6"
443 | integrity sha512-sKItB4s3FxqlwCgXdMfwRAfssSoo31bcFsGAAg/HzaZLicY6CDlofKXP8G5iPDerB6NaoAcAaBLutLzl9sd4fQ==
444 | dependencies:
445 | graphql-playground-html "1.6.12"
446 |
447 | graphql-playground-middleware-lambda@1.7.12:
448 | version "1.7.12"
449 | resolved "https://registry.yarnpkg.com/graphql-playground-middleware-lambda/-/graphql-playground-middleware-lambda-1.7.12.tgz#1b06440a288dbcd53f935b43e5b9ca2738a06305"
450 | integrity sha512-fJ1Y0Ck5ctmfaQFoWv7vNnVP7We19P3miVmOT85YPrjpzbMYv0wPfxm4Zjt8nnqXr0KU9nGW53tz3K7/Lvzxtw==
451 | dependencies:
452 | graphql-playground-html "1.6.12"
453 |
454 | graphql-subscriptions@^0.5.8:
455 | version "0.5.8"
456 | resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz#13a6143c546bce390404657dc73ca501def30aa7"
457 | integrity sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ==
458 | dependencies:
459 | iterall "^1.2.1"
460 |
461 | graphql-tools@^4.0.0:
462 | version "4.0.3"
463 | resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.3.tgz#23b5cb52c519212b1b2e4630a361464396ad264b"
464 | integrity sha512-NNZM0WSnVLX1zIMUxu7SjzLZ4prCp15N5L2T2ro02OVyydZ0fuCnZYRnx/yK9xjGWbZA0Q58yEO//Bv/psJWrg==
465 | dependencies:
466 | apollo-link "^1.2.3"
467 | apollo-utilities "^1.0.1"
468 | deprecated-decorator "^0.1.6"
469 | iterall "^1.1.3"
470 | uuid "^3.1.0"
471 |
472 | graphql-tools@^4.0.5:
473 | version "4.0.5"
474 | resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.5.tgz#d2b41ee0a330bfef833e5cdae7e1f0b0d86b1754"
475 | integrity sha512-kQCh3IZsMqquDx7zfIGWBau42xe46gmqabwYkpPlCLIjcEY1XK+auP7iGRD9/205BPyoQdY8hT96MPpgERdC9Q==
476 | dependencies:
477 | apollo-link "^1.2.3"
478 | apollo-utilities "^1.0.1"
479 | deprecated-decorator "^0.1.6"
480 | iterall "^1.1.3"
481 | uuid "^3.1.0"
482 |
483 | graphql-upload@^8.0.0:
484 | version "8.0.7"
485 | resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-8.0.7.tgz#8644264e241529552ea4b3797e7ee15809cf01a3"
486 | integrity sha512-gi2yygbDPXbHPC7H0PNPqP++VKSoNoJO4UrXWq4T0Bi4IhyUd3Ycop/FSxhx2svWIK3jdXR/i0vi91yR1aAF0g==
487 | dependencies:
488 | busboy "^0.3.1"
489 | fs-capacitor "^2.0.4"
490 | http-errors "^1.7.2"
491 | object-path "^0.11.4"
492 |
493 | graphql-yoga@1.18.3:
494 | version "1.18.3"
495 | resolved "https://registry.yarnpkg.com/graphql-yoga/-/graphql-yoga-1.18.3.tgz#047fa511dbef63cf6d6ea7c06a71202d37444844"
496 | integrity sha512-tR6JYbwLSBVu0Z8M7BIyt1PHhhexmRwneYM8Ru/g2pixrtsWbelBFAXU7bDPhXrqZ49Zxt2zLJ60x3bLNGo/bQ==
497 | dependencies:
498 | "@types/aws-lambda" "8.10.13"
499 | "@types/cors" "^2.8.4"
500 | "@types/express" "^4.11.1"
501 | "@types/graphql" "^14.0.0"
502 | "@types/graphql-deduplicator" "^2.0.0"
503 | "@types/zen-observable" "^0.5.3"
504 | apollo-server-express "^1.3.6"
505 | apollo-server-lambda "1.3.6"
506 | apollo-upload-server "^7.0.0"
507 | body-parser-graphql "1.1.0"
508 | cors "^2.8.4"
509 | express "^4.16.3"
510 | graphql "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
511 | graphql-deduplicator "^2.0.1"
512 | graphql-import "^0.7.0"
513 | graphql-middleware "4.0.1"
514 | graphql-playground-middleware-express "1.7.11"
515 | graphql-playground-middleware-lambda "1.7.12"
516 | graphql-subscriptions "^0.5.8"
517 | graphql-tools "^4.0.0"
518 | graphql-upload "^8.0.0"
519 | subscriptions-transport-ws "^0.9.8"
520 |
521 | "graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0":
522 | version "14.0.2"
523 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650"
524 | integrity sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==
525 | dependencies:
526 | iterall "^1.2.2"
527 |
528 | http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
529 | version "1.6.3"
530 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
531 | integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
532 | dependencies:
533 | depd "~1.1.2"
534 | inherits "2.0.3"
535 | setprototypeof "1.1.0"
536 | statuses ">= 1.4.0 < 2"
537 |
538 | http-errors@^1.7.0:
539 | version "1.7.1"
540 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.1.tgz#6a4ffe5d35188e1c39f872534690585852e1f027"
541 | integrity sha512-jWEUgtZWGSMba9I1N3gc1HmvpBUaNC9vDdA46yScAdp+C5rdEuKWUBLWTQpW9FwSWSbYYs++b6SDCxf9UEJzfw==
542 | dependencies:
543 | depd "~1.1.2"
544 | inherits "2.0.3"
545 | setprototypeof "1.1.0"
546 | statuses ">= 1.5.0 < 2"
547 | toidentifier "1.0.0"
548 |
549 | http-errors@^1.7.2:
550 | version "1.7.2"
551 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
552 | integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
553 | dependencies:
554 | depd "~1.1.2"
555 | inherits "2.0.3"
556 | setprototypeof "1.1.1"
557 | statuses ">= 1.5.0 < 2"
558 | toidentifier "1.0.0"
559 |
560 | iconv-lite@0.4.23:
561 | version "0.4.23"
562 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
563 | integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
564 | dependencies:
565 | safer-buffer ">= 2.1.2 < 3"
566 |
567 | inherits@2.0.3, inherits@~2.0.1:
568 | version "2.0.3"
569 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
570 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
571 |
572 | ipaddr.js@1.8.0:
573 | version "1.8.0"
574 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
575 | integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
576 |
577 | isarray@0.0.1:
578 | version "0.0.1"
579 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
580 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
581 |
582 | iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2:
583 | version "1.2.2"
584 | resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
585 | integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
586 |
587 | lodash@^4.17.4:
588 | version "4.17.11"
589 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
590 | integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
591 |
592 | media-typer@0.3.0:
593 | version "0.3.0"
594 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
595 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
596 |
597 | merge-descriptors@1.0.1:
598 | version "1.0.1"
599 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
600 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
601 |
602 | methods@~1.1.2:
603 | version "1.1.2"
604 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
605 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
606 |
607 | mime-db@~1.37.0:
608 | version "1.37.0"
609 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
610 | integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
611 |
612 | mime-types@~2.1.18:
613 | version "2.1.21"
614 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
615 | integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==
616 | dependencies:
617 | mime-db "~1.37.0"
618 |
619 | mime@1.4.1:
620 | version "1.4.1"
621 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
622 | integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
623 |
624 | ms@2.0.0:
625 | version "2.0.0"
626 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
627 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
628 |
629 | negotiator@0.6.1:
630 | version "0.6.1"
631 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
632 | integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
633 |
634 | object-assign@^4:
635 | version "4.1.1"
636 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
637 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
638 |
639 | object-path@^0.11.4:
640 | version "0.11.4"
641 | resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949"
642 | integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=
643 |
644 | on-finished@~2.3.0:
645 | version "2.3.0"
646 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
647 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
648 | dependencies:
649 | ee-first "1.1.1"
650 |
651 | parseurl@~1.3.2:
652 | version "1.3.2"
653 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
654 | integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
655 |
656 | path-to-regexp@0.1.7:
657 | version "0.1.7"
658 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
659 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
660 |
661 | proxy-addr@~2.0.4:
662 | version "2.0.4"
663 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
664 | integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
665 | dependencies:
666 | forwarded "~0.1.2"
667 | ipaddr.js "1.8.0"
668 |
669 | qs@6.5.2:
670 | version "6.5.2"
671 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
672 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
673 |
674 | range-parser@~1.2.0:
675 | version "1.2.0"
676 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
677 | integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
678 |
679 | raw-body@2.3.3:
680 | version "2.3.3"
681 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
682 | integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==
683 | dependencies:
684 | bytes "3.0.0"
685 | http-errors "1.6.3"
686 | iconv-lite "0.4.23"
687 | unpipe "1.0.0"
688 |
689 | readable-stream@1.1.x:
690 | version "1.1.14"
691 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
692 | integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
693 | dependencies:
694 | core-util-is "~1.0.0"
695 | inherits "~2.0.1"
696 | isarray "0.0.1"
697 | string_decoder "~0.10.x"
698 |
699 | resolve-from@^4.0.0:
700 | version "4.0.0"
701 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
702 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
703 |
704 | safe-buffer@5.1.2:
705 | version "5.1.2"
706 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
707 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
708 |
709 | "safer-buffer@>= 2.1.2 < 3":
710 | version "2.1.2"
711 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
712 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
713 |
714 | send@0.16.2:
715 | version "0.16.2"
716 | resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
717 | integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
718 | dependencies:
719 | debug "2.6.9"
720 | depd "~1.1.2"
721 | destroy "~1.0.4"
722 | encodeurl "~1.0.2"
723 | escape-html "~1.0.3"
724 | etag "~1.8.1"
725 | fresh "0.5.2"
726 | http-errors "~1.6.2"
727 | mime "1.4.1"
728 | ms "2.0.0"
729 | on-finished "~2.3.0"
730 | range-parser "~1.2.0"
731 | statuses "~1.4.0"
732 |
733 | serve-static@1.13.2:
734 | version "1.13.2"
735 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
736 | integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
737 | dependencies:
738 | encodeurl "~1.0.2"
739 | escape-html "~1.0.3"
740 | parseurl "~1.3.2"
741 | send "0.16.2"
742 |
743 | setprototypeof@1.1.0:
744 | version "1.1.0"
745 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
746 | integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
747 |
748 | setprototypeof@1.1.1:
749 | version "1.1.1"
750 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
751 | integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
752 |
753 | source-map-support@^0.5.1:
754 | version "0.5.9"
755 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
756 | integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
757 | dependencies:
758 | buffer-from "^1.0.0"
759 | source-map "^0.6.0"
760 |
761 | source-map@^0.6.0:
762 | version "0.6.1"
763 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
764 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
765 |
766 | "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2":
767 | version "1.5.0"
768 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
769 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
770 |
771 | statuses@~1.4.0:
772 | version "1.4.0"
773 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
774 | integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
775 |
776 | streamsearch@0.1.2:
777 | version "0.1.2"
778 | resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
779 | integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
780 |
781 | string_decoder@~0.10.x:
782 | version "0.10.31"
783 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
784 | integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
785 |
786 | subscriptions-transport-ws@^0.9.8:
787 | version "0.9.15"
788 | resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.15.tgz#68a8b7ba0037d8c489fb2f5a102d1494db297d0d"
789 | integrity sha512-f9eBfWdHsePQV67QIX+VRhf++dn1adyC/PZHP6XI5AfKnZ4n0FW+v5omxwdHVpd4xq2ZijaHEcmlQrhBY79ZWQ==
790 | dependencies:
791 | backo2 "^1.0.2"
792 | eventemitter3 "^3.1.0"
793 | iterall "^1.2.1"
794 | symbol-observable "^1.0.4"
795 | ws "^5.2.0"
796 |
797 | symbol-observable@^1.0.4:
798 | version "1.2.0"
799 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
800 | integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
801 |
802 | toidentifier@1.0.0:
803 | version "1.0.0"
804 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
805 | integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
806 |
807 | type-is@~1.6.16:
808 | version "1.6.16"
809 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
810 | integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==
811 | dependencies:
812 | media-typer "0.3.0"
813 | mime-types "~2.1.18"
814 |
815 | unpipe@1.0.0, unpipe@~1.0.0:
816 | version "1.0.0"
817 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
818 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
819 |
820 | utils-merge@1.0.1:
821 | version "1.0.1"
822 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
823 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
824 |
825 | uuid@^3.1.0:
826 | version "3.3.2"
827 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
828 | integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
829 |
830 | vary@^1, vary@~1.1.2:
831 | version "1.1.2"
832 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
833 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
834 |
835 | ws@^5.2.0:
836 | version "5.2.2"
837 | resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
838 | integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
839 | dependencies:
840 | async-limiter "~1.0.0"
841 |
842 | zen-observable-ts@^0.8.11:
843 | version "0.8.11"
844 | resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz#d54a27cd17dc4b4bb6bd008e5c096af7fcb068a9"
845 | integrity sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==
846 | dependencies:
847 | zen-observable "^0.8.0"
848 |
849 | zen-observable@^0.8.0:
850 | version "0.8.11"
851 | resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.11.tgz#d3415885eeeb42ee5abb9821c95bb518fcd6d199"
852 | integrity sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==
853 |
--------------------------------------------------------------------------------
/minimal/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { gql } from 'apollo-boost'
3 | import { Query } from 'react-apollo'
4 | import logo from '../logo.svg'
5 | import '../styles/App.css'
6 | import InputName from './InputName'
7 |
8 | class App extends Component {
9 | render() {
10 | return (
11 |
12 |
13 |
14 |
15 | {props => {
16 | console.log(props)
17 | const { data, loading, error, refetch } = props
18 | if (loading) {
19 | return Loading
20 | }
21 |
22 | if (error) {
23 | return An unexpected error occurred
24 | }
25 |
26 | return (
27 |
28 |
What's your name?
29 |
{
31 | refetch({
32 | name,
33 | })
34 | }}
35 | />
36 | {data.hello}
37 |
38 | )
39 | }}
40 |
41 |
42 |
43 | )
44 | }
45 | }
46 |
47 | const HELLO_QUERY = gql`
48 | query HelloQuery($name: String) {
49 | hello(name: $name)
50 | }
51 | `
52 |
53 | export default App
54 |
--------------------------------------------------------------------------------
/minimal/src/components/InputName.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class InputName extends Component {
4 | constructor(props) {
5 | super(props)
6 |
7 | this.state = {
8 | name: '',
9 | }
10 | }
11 |
12 | render() {
13 | return (
14 |
15 | {
19 | this.setState({ name: e.target.value })
20 | }}
21 | />
22 | {
24 | this.props.onSubmit(this.state.name)
25 | }}
26 | >
27 | Send
28 |
29 |
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/minimal/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import '../src/styles/index.css'
4 | import App from '../src/components/App'
5 | import { ApolloProvider } from 'react-apollo'
6 | import ApolloClient from 'apollo-boost'
7 |
8 | const client = new ApolloClient({
9 | uri: 'http://localhost:4000',
10 | })
11 |
12 | //Apollo Client
13 | ReactDOM.render(
14 |
15 |
16 | ,
17 | document.getElementById('root'),
18 | )
--------------------------------------------------------------------------------
/minimal/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Shape
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/minimal/src/styles/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background-color: #222;
12 | height: 250px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-title {
18 | font-size: 1.5em;
19 | }
20 |
21 | .App-intro {
22 | font-size: large;
23 | }
24 |
25 | h3 {
26 | text-align: center;
27 | padding:10px;
28 | }
29 |
30 | @keyframes App-logo-spin {
31 | from { transform: rotate(0deg); }
32 | to { transform: rotate(360deg); }
33 | }
34 |
--------------------------------------------------------------------------------
/minimal/src/styles/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | ":skipStatusChecks"
5 | ],
6 | "ignoreDeps": ["prisma"],
7 | "automerge": true,
8 | "major": {
9 | "automerge": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------