├── .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 | ![](https://imgur.com/ousyQaC.png) 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 | ![](https://imgur.com/ousyQaC.png) 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 | ![](https://imgur.com/95faUsa.png) 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 |
15 |
16 |

Create Draft

17 | this.setState({ title: e.target.value })} 21 | placeholder="Title" 22 | type="text" 23 | value={this.state.title} 24 | /> 25 |