├── basic ├── static │ └── .gitkeep ├── config │ ├── prod.env.js │ ├── dev.env.js │ └── index.js ├── server │ ├── .gitignore │ ├── database │ │ ├── datamodel.prisma │ │ ├── prisma.yml │ │ └── seed.graphql │ ├── .graphqlconfig.yml │ ├── src │ │ ├── schema.graphql │ │ ├── index.js │ │ └── generated │ │ │ └── prisma.graphql │ └── package.json ├── build │ ├── logo.png │ ├── dev-client.js │ ├── vue-loader.conf.js │ ├── build.js │ ├── check-versions.js │ ├── webpack.base.conf.js │ ├── dev-server.js │ ├── utils.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── .install │ ├── package.json │ ├── index.js │ └── yarn.lock ├── .editorconfig ├── src │ ├── components │ │ ├── NotFoundPage.vue │ │ ├── Post.vue │ │ ├── FeedPage.vue │ │ ├── DraftsPage.vue │ │ ├── DetailPage.vue │ │ └── CreatePage.vue │ ├── assets │ │ ├── plus.svg │ │ └── close.svg │ ├── router │ │ └── index.js │ ├── main.js │ └── App.vue ├── .gitignore ├── .babelrc ├── .postcssrc.js ├── .eslintrc.js ├── index.html ├── package.json └── README.md ├── minimal ├── static │ └── .gitkeep ├── server │ ├── .gitignore │ ├── package.json │ ├── src │ │ └── index.js │ └── README.md ├── config │ ├── prod.env.js │ ├── dev.env.js │ └── index.js ├── build │ ├── logo.png │ ├── dev-client.js │ ├── vue-loader.conf.js │ ├── build.js │ ├── check-versions.js │ ├── webpack.base.conf.js │ ├── dev-server.js │ ├── utils.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── .editorconfig ├── .gitignore ├── .babelrc ├── .postcssrc.js ├── .eslintrc.js ├── index.html ├── src │ ├── logo.svg │ ├── main.js │ └── App.vue ├── package.json └── README.md ├── advanced ├── src │ ├── constants.js │ ├── constants │ │ └── index.js │ ├── components │ │ ├── NotFoundPage.vue │ │ ├── Post.vue │ │ ├── FeedPage.vue │ │ ├── DraftsPage.vue │ │ ├── CreatePage.vue │ │ ├── DetailPage.vue │ │ ├── LoginPage.vue │ │ └── SignupPage.vue │ ├── assets │ │ ├── plus.svg │ │ └── close.svg │ ├── utils │ │ └── index.js │ ├── router │ │ └── index.js │ ├── main.js │ └── App.vue ├── static │ └── .gitkeep ├── config │ ├── prod.env.js │ ├── dev.env.js │ └── index.js ├── server │ ├── .gitignore │ ├── .env │ ├── src │ │ ├── resolvers │ │ │ ├── AuthPayload.js │ │ │ ├── index.js │ │ │ ├── Query.js │ │ │ ├── Subscription.js │ │ │ └── Mutation │ │ │ │ ├── auth.js │ │ │ │ └── post.js │ │ ├── utils.js │ │ ├── schema.graphql │ │ ├── index.js │ │ └── generated │ │ │ └── prisma.graphql │ ├── .graphqlconfig.yml │ ├── database │ │ ├── datamodel.prisma │ │ ├── prisma.yml │ │ └── seed.graphql │ ├── package.json │ └── README.md ├── build │ ├── logo.png │ ├── dev-client.js │ ├── vue-loader.conf.js │ ├── build.js │ ├── check-versions.js │ ├── webpack.base.conf.js │ ├── dev-server.js │ ├── utils.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── .install │ ├── package.json │ ├── index.js │ └── yarn.lock ├── .editorconfig ├── .gitignore ├── .babelrc ├── .postcssrc.js ├── index.html ├── package.json └── README.md ├── package.json ├── renovate.json └── README.md /basic/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /minimal/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /advanced/src/constants.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /advanced/static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /minimal/server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package.json.lock -------------------------------------------------------------------------------- /advanced/src/constants/index.js: -------------------------------------------------------------------------------- 1 | export const USER_ID = 'user-id'; 2 | export const AUTH_TOKEN = 'token'; -------------------------------------------------------------------------------- /basic/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /minimal/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "subscriptions-transport-ws": "0.11.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /advanced/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /advanced/server/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | package-lock.json 3 | node_modules 4 | .idea 5 | .vscode 6 | *.log 7 | -------------------------------------------------------------------------------- /basic/server/.gitignore: -------------------------------------------------------------------------------- 1 | .env* 2 | dist 3 | package-lock.json 4 | node_modules 5 | .idea 6 | .vscode 7 | *.log 8 | -------------------------------------------------------------------------------- /basic/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-boilerplates/vue-fullstack-graphql/HEAD/basic/build/logo.png -------------------------------------------------------------------------------- /minimal/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-boilerplates/vue-fullstack-graphql/HEAD/minimal/build/logo.png -------------------------------------------------------------------------------- /advanced/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphql-boilerplates/vue-fullstack-graphql/HEAD/advanced/build/logo.png -------------------------------------------------------------------------------- /advanced/server/.env: -------------------------------------------------------------------------------- 1 | PRISMA_ENDPOINT="__PRISMA_ENDPOINT__" 2 | PRISMA_SECRET="mysecret123" 3 | APP_SECRET="jwtsecret123" 4 | -------------------------------------------------------------------------------- /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/server/database/datamodel.prisma: -------------------------------------------------------------------------------- 1 | type Post { 2 | id: ID! @id 3 | isPublished: Boolean! @default(value: false) 4 | title: String! 5 | text: String! 6 | } 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /basic/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /advanced/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /basic/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /minimal/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /advanced/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /minimal/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":skipStatusChecks" 5 | ], 6 | "ignoreDeps": ["prisma"], 7 | "automerge": true, 8 | "major": { 9 | "automerge": false 10 | } 11 | } -------------------------------------------------------------------------------- /basic/src/components/NotFoundPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /advanced/src/components/NotFoundPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /advanced/server/src/resolvers/AuthPayload.js: -------------------------------------------------------------------------------- 1 | const AuthPayload = { 2 | user: async ({ user: { id } }, args, ctx, info) => { 3 | return ctx.db.query.user({ where: { id } }, info) 4 | }, 5 | } 6 | 7 | module.exports = { AuthPayload } -------------------------------------------------------------------------------- /basic/.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 | -------------------------------------------------------------------------------- /minimal/.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/.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/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /basic/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /minimal/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /basic/server/.graphqlconfig.yml: -------------------------------------------------------------------------------- 1 | 2 | projects: 3 | app: 4 | schemaPath: src/schema.graphql 5 | extensions: 6 | endpoints: 7 | default: http://localhost:4000 8 | database: 9 | schemaPath: src/generated/prisma.graphql 10 | extensions: 11 | prisma: database/prisma.yml -------------------------------------------------------------------------------- /advanced/server/.graphqlconfig.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | app: 3 | schemaPath: "src/schema.graphql" 4 | extensions: 5 | endpoints: 6 | default: "http://localhost:4000" 7 | database: 8 | schemaPath: "src/generated/prisma.graphql" 9 | extensions: 10 | prisma: database/prisma.yml -------------------------------------------------------------------------------- /basic/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /basic/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /minimal/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /minimal/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /advanced/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /advanced/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /basic/server/src/schema.graphql: -------------------------------------------------------------------------------- 1 | # import Post from "./generated/prisma.graphql" 2 | 3 | type Query { 4 | feed: [Post!]! 5 | drafts: [Post!]! 6 | post(id: ID!): Post 7 | } 8 | 9 | type Mutation { 10 | createDraft(title: String!, text: String): Post 11 | deletePost(id: ID!): Post 12 | publish(id: ID!): Post 13 | } 14 | -------------------------------------------------------------------------------- /advanced/server/database/datamodel.prisma: -------------------------------------------------------------------------------- 1 | type Post { 2 | id: ID! @id 3 | createdAt: DateTime! @createdAt 4 | updatedAt: DateTime! @updatedAt 5 | isPublished: Boolean! @default(value: false) 6 | title: String! 7 | text: 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 | } 18 | -------------------------------------------------------------------------------- /advanced/server/src/resolvers/index.js: -------------------------------------------------------------------------------- 1 | const { Query } = require('./Query') 2 | const { Subscription } = require('./Subscription') 3 | const { auth } = require('./Mutation/auth') 4 | const { post } = require('./Mutation/post') 5 | const { AuthPayload } = require('./AuthPayload') 6 | 7 | module.exports = { 8 | Query, 9 | Mutation: { 10 | ...auth, 11 | ...post, 12 | }, 13 | Subscription, 14 | AuthPayload, 15 | } 16 | -------------------------------------------------------------------------------- /basic/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | // add more generic rulesets here, such as: 4 | // 'eslint:recommended', 5 | 'plugin:vue/essential' 6 | ], 7 | parserOptions: { 8 | 'ecmaVersion': 6, 9 | 'sourceType': "module" 10 | }, 11 | rules: { 12 | "extends": "plugin:vue/base" 13 | // override/add rules settings here, such as: 14 | // 'vue/no-unused-vars': 'error' 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /minimal/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | // add more generic rulesets here, such as: 4 | // 'eslint:recommended', 5 | 'plugin:vue/essential' 6 | ], 7 | parserOptions: { 8 | 'ecmaVersion': 6, 9 | 'sourceType': "module" 10 | }, 11 | rules: { 12 | "extends": "plugin:vue/base" 13 | // override/add rules settings here, such as: 14 | // 'vue/no-unused-vars': 'error' 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Instagram Vue.js App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /basic/server/database/prisma.yml: -------------------------------------------------------------------------------- 1 | # the endpoint of your service (this also defines the cluster the service will be deployed to) 2 | endpoint: __PRISMA_ENDPOINT__ 3 | 4 | # to disable authentication: 5 | # disableAuth: true 6 | secret: mysecret123 7 | 8 | # the file path pointing to your data model 9 | datamodel: datamodel.prisma 10 | 11 | # seed your service with initial data based on seed.graphql 12 | seed: 13 | import: seed.graphql 14 | -------------------------------------------------------------------------------- /minimal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Instagram Vue.js App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /advanced/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Instagram Vue.js App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /advanced/server/database/prisma.yml: -------------------------------------------------------------------------------- 1 | # the endpoint of your service (this also defines the cluster the service will be deployed to) 2 | endpoint: ${env:PRISMA_ENDPOINT} 3 | 4 | # to disable authentication: 5 | # disableAuth: true 6 | secret: ${env:PRISMA_SECRET} 7 | 8 | # the file path pointing to your data model 9 | datamodel: datamodel.prisma 10 | 11 | # seed your service with initial data based on seed.graphql 12 | seed: 13 | import: seed.graphql -------------------------------------------------------------------------------- /basic/src/assets/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /advanced/src/assets/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /minimal/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /basic/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-boilerplate", 3 | "scripts": { 4 | "start": "node src/index.js", 5 | "playground": "prisma playground", 6 | "dev": "npm-run-all --parallel start playground", 7 | "prisma": "prisma" 8 | }, 9 | "dependencies": { 10 | "graphql-yoga": "1.18.3", 11 | "prisma-binding": "1.5.19" 12 | }, 13 | "devDependencies": { 14 | "graphql-cli": "2.17.0", 15 | "npm-run-all2": "5.0.2", 16 | "prisma": "1.7.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /advanced/src/assets/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /basic/src/assets/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /minimal/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GraphCool", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon src/index.js" 8 | }, 9 | "keywords": [], 10 | "author": "Manjula Dube", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-cli": "6.26.0", 14 | "babel-core": "6.26.3", 15 | "babel-polyfill": "6.26.0", 16 | "babel-preset-es2015": "6.24.1", 17 | "graphql-yoga": "1.18.3", 18 | "nodemon": "1.19.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /advanced/server/src/utils.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken') 2 | 3 | function getUserId(ctx) { 4 | const Authorization = ctx.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 | } -------------------------------------------------------------------------------- /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 opts = { 10 | port: 4000 //configurable port no 11 | } 12 | 13 | const resolvers = { 14 | Query: { 15 | hello: (_, { name }) => { 16 | const returnValue = !name ? `Hello ${name || 'World!'}` : null 17 | return returnValue 18 | }, 19 | }, 20 | } 21 | 22 | const server = new GraphQLServer({ typeDefs, resolvers, opts }) 23 | server.start(() => console.log(`Server is running at http://localhost:${opts.port}`)) 24 | -------------------------------------------------------------------------------- /basic/server/database/seed.graphql: -------------------------------------------------------------------------------- 1 | mutation { 2 | first: createPost( 3 | data: { 4 | title: "Hello World" 5 | text: "This is my first blog post ever!" 6 | isPublished: true 7 | } 8 | ) { 9 | id 10 | } 11 | 12 | second: createPost( 13 | data: { 14 | title: "My Second Post" 15 | text: "My first post was good, but this one is better!" 16 | isPublished: true 17 | } 18 | ) { 19 | id 20 | } 21 | 22 | third: createPost( 23 | data: { 24 | title: "Solving World Hunger" 25 | text: "This is a draft..." 26 | isPublished: false 27 | } 28 | ) { 29 | id 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /advanced/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /basic/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /minimal/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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 | "playground": "graphql playground", 7 | "dev": "npm-run-all --parallel start playground" 8 | }, 9 | "dependencies": { 10 | "bcryptjs": "2.4.3", 11 | "graphql-yoga": "1.18.3", 12 | "jsonwebtoken": "8.5.1", 13 | "prisma-binding": "1.5.19" 14 | }, 15 | "devDependencies": { 16 | "dotenv": "5.0.1", 17 | "graphql-cli": "2.17.0", 18 | "nodemon": "1.19.4", 19 | "npm-run-all2": "5.0.2", 20 | "prisma": "1.7.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /advanced/server/database/seed.graphql: -------------------------------------------------------------------------------- 1 | mutation { 2 | createUser(data: { 3 | email: "developer@example.com" 4 | password: "$2a$10$hACwQ5/HQI6FhbIISOUVeusy3sKyUDhSq36fF5d/54aAdiygJPFzm" # plaintext password: "nooneknows" 5 | name: "Sarah" 6 | posts: { 7 | create: [{ 8 | title: "Hello World" 9 | text: "This is my first blog post ever!" 10 | isPublished: true 11 | }, { 12 | title: "My Second Post" 13 | text: "My first post was good, but this one is better!" 14 | isPublished: true 15 | }, { 16 | title: "Solving World Hunger" 17 | text: "This is a draft..." 18 | isPublished: false 19 | }] 20 | } 21 | }) { 22 | id 23 | } 24 | } -------------------------------------------------------------------------------- /advanced/server/src/schema.graphql: -------------------------------------------------------------------------------- 1 | # import Post from "./generated/prisma.graphql" 2 | 3 | type Query { 4 | feed: [Post!]! 5 | drafts: [Post!]! 6 | post(id: ID!): Post 7 | me: User 8 | } 9 | 10 | type Mutation { 11 | signup(email: String!, password: String!, name: String!): AuthPayload! 12 | login(email: String!, password: String!): AuthPayload! 13 | createDraft(title: String!, text: String!): Post! 14 | publish(id: ID!): Post! 15 | deletePost(id: ID!): Post! 16 | } 17 | 18 | type Subscription { 19 | feedSubscription: PostSubscriptionPayload! 20 | } 21 | 22 | type AuthPayload { 23 | token: String! 24 | user: User! 25 | } 26 | 27 | type User { 28 | id: ID! 29 | email: String! 30 | name: String! 31 | posts: [Post!]! 32 | } 33 | -------------------------------------------------------------------------------- /advanced/server/src/resolvers/Query.js: -------------------------------------------------------------------------------- 1 | const { getUserId } = require('../utils') 2 | 3 | const Query = { 4 | feed(parent, args, ctx, info) { 5 | return ctx.db.query.posts({ where: { isPublished: true } }, info) 6 | }, 7 | 8 | drafts(parent, args, ctx, info) { 9 | const id = getUserId(ctx) 10 | 11 | const where = { 12 | isPublished: false, 13 | author: { 14 | id 15 | } 16 | } 17 | 18 | return ctx.db.query.posts({ where }, info) 19 | }, 20 | 21 | post(parent, { id }, ctx, info) { 22 | return ctx.db.query.post({ where: { id } }, info) 23 | }, 24 | 25 | me(parent, args, ctx, info) { 26 | const id = getUserId(ctx) 27 | return ctx.db.query.user({ where: { id } }, info) 28 | }, 29 | } 30 | 31 | module.exports = { Query } 32 | -------------------------------------------------------------------------------- /advanced/src/utils/index.js: -------------------------------------------------------------------------------- 1 | import decode from 'jwt-decode' 2 | 3 | export function checkAuth() { 4 | if (localStorage.getItem('token') !== null) { 5 | return true; 6 | } else { 7 | return false; 8 | } 9 | } 10 | 11 | export function getTokenExpirationDate(token) { 12 | const decoded = decode(token); 13 | if (!decoded.exp) { 14 | return null; 15 | } 16 | const date = new Date(0); // The 0 here is the key, which sets the date to the epoch 17 | date.setUTCSeconds(decoded.exp); 18 | return date; 19 | } 20 | 21 | export function isTokenExpired(token) { 22 | const date = getTokenExpirationDate(token); 23 | const offsetSeconds = 0; 24 | if (date === null) { 25 | return false; 26 | } 27 | return !(date.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000))); 28 | } 29 | -------------------------------------------------------------------------------- /minimal/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import { ApolloClient } from 'apollo-client' 4 | import { HttpLink } from 'apollo-link-http' 5 | import { InMemoryCache } from 'apollo-cache-inmemory' 6 | import VueApollo from 'vue-apollo' 7 | 8 | const httpLink = new HttpLink({ uri: 'http://localhost:4000/' }) 9 | 10 | // apollo client setup 11 | const client = new ApolloClient({ 12 | link: httpLink, 13 | cache: new InMemoryCache(), 14 | connectToDevTools: true 15 | }) 16 | 17 | // Install the vue plugin 18 | Vue.use(VueApollo) 19 | 20 | // Apollo provider init 21 | const apolloProvider = new VueApollo({ 22 | defaultClient: client 23 | }) 24 | 25 | // Start the app 26 | new Vue({ 27 | el: '#app', 28 | provide: apolloProvider.provide(), 29 | render: h => h(App) 30 | }) -------------------------------------------------------------------------------- /advanced/server/src/index.js: -------------------------------------------------------------------------------- 1 | const { GraphQLServer } = require('graphql-yoga') 2 | const { Prisma } = require('prisma-binding') 3 | const resolvers = require('./resolvers') 4 | 5 | const server = new GraphQLServer({ 6 | typeDefs: 'src/schema.graphql', 7 | resolvers, 8 | context: req => ({ 9 | ...req, 10 | db: new Prisma({ 11 | typeDefs: 'src/generated/prisma.graphql', // the Prisma DB schema 12 | endpoint: process.env.PRISMA_ENDPOINT, // the endpoint of the Prisma DB service (value is set in .env) 13 | secret: process.env.PRISMA_SECRET, // taken from database/prisma.yml (value is set in .env) 14 | debug: true, // log all GraphQL queries & mutations 15 | }), 16 | }), 17 | }) 18 | 19 | server.start(() => console.log('Server is running on http://localhost:4000')) 20 | -------------------------------------------------------------------------------- /advanced/server/src/resolvers/Subscription.js: -------------------------------------------------------------------------------- 1 | const Subscription = { 2 | feedSubscription: { 3 | subscribe: (parent, args, ctx, info) => { 4 | return ctx.db.subscription.post({}, info) 5 | }, 6 | }, 7 | } 8 | 9 | // This is the same subscription as above but only fires for 10 | // posts that have been published. 11 | // This feature is not yet live due to a gub in Prisma: 12 | // https://github.com/graphcool/prisma/issues/1734 13 | // const Subscription = { 14 | // feedSubscription: { 15 | // subscribe: (parent, args, ctx, info) => { 16 | // return ctx.db.subscription.post( 17 | // { 18 | // where: { 19 | // node: { 20 | // isPublished: true, 21 | // }, 22 | // }, 23 | // }, 24 | // info, 25 | // ) 26 | // }, 27 | // }, 28 | // } 29 | 30 | module.exports = { Subscription } 31 | -------------------------------------------------------------------------------- /basic/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import DetailPage from 'components/DetailPage' 4 | import FeedPage from 'components/FeedPage' 5 | import CreatePage from 'components/CreatePage' 6 | import DraftsPage from 'components/DraftsPage' 7 | import NotFoundPage from 'components/NotFoundPage' 8 | 9 | Vue.use(Router) 10 | 11 | export default new Router({ 12 | mode: 'history', 13 | routes: [ 14 | { 15 | path: '/', 16 | name: 'Feed', 17 | component: FeedPage 18 | }, 19 | { 20 | path: '/detail/:id', 21 | name: 'Detail', 22 | component: DetailPage 23 | }, 24 | { 25 | path: '/create', 26 | name: 'Create', 27 | component: CreatePage 28 | }, 29 | { 30 | path: '/drafts', 31 | name: 'Drafts', 32 | component: DraftsPage 33 | }, 34 | { path: '*', 35 | component: NotFoundPage 36 | } 37 | ] 38 | }) -------------------------------------------------------------------------------- /basic/src/components/Post.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 33 | 36 | -------------------------------------------------------------------------------- /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, ctx, info) { 6 | const password = await bcrypt.hash(args.password, 10) 7 | const user = await ctx.db.mutation.createUser({ 8 | data: { ...args, password }, 9 | }) 10 | 11 | return { 12 | token: jwt.sign({ userId: user.id }, process.env.APP_SECRET), 13 | user, 14 | } 15 | }, 16 | 17 | async login(parent, { email, password }, ctx, info) { 18 | const user = await ctx.db.query.user({ where: { email } }) 19 | if (!user) { 20 | throw new Error(`No such user found for email: ${email}`) 21 | } 22 | 23 | const valid = await bcrypt.compare(password, user.password) 24 | if (!valid) { 25 | throw new Error('Invalid password') 26 | } 27 | 28 | return { 29 | token: jwt.sign({ userId: user.id }, process.env.APP_SECRET), 30 | user, 31 | } 32 | }, 33 | } 34 | 35 | module.exports = { auth } 36 | -------------------------------------------------------------------------------- /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 | 15 | process.chdir('server/') 16 | replaceInFiles( 17 | ['src/index.js', 'package.json', 'database/prisma.yml'], 18 | templateName, 19 | project, 20 | ) 21 | replaceInFiles(['.env'], '__PRISMA_ENDPOINT__', endpoint) 22 | 23 | console.log('Running $ prisma deploy...') 24 | await deploy(false) 25 | process.chdir('../') 26 | 27 | fs.appendFileSync('server/.gitignore', '.env*\n') 28 | 29 | console.log(`\ 30 | Next steps: 31 | 1. Change directory: \`cd ${projectDir}/server\` 32 | 2. Start local server: \`yarn start\` (you can now open a Playground at http://localhost:4000) 33 | 3. Change directory: \`cd ..\` 34 | 4. Start VueJS app: \`yarn start\` 35 | 5. Open browser: http://localhost:3000 36 | `) 37 | } 38 | -------------------------------------------------------------------------------- /advanced/src/components/Post.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 34 | 41 | -------------------------------------------------------------------------------- /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', 'database/prisma.yml'], 18 | templateName, 19 | project, 20 | ) 21 | replaceInFiles(['src/index.js'], '__PRISMA_ENDPOINT__', endpoint) 22 | replaceInFiles(['database/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/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 VueJS app: \`yarn start\` 43 | 5. Open browser: http://localhost:3000 44 | `) 45 | } 46 | -------------------------------------------------------------------------------- /basic/src/components/FeedPage.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 25 | 26 | 62 | -------------------------------------------------------------------------------- /advanced/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /advanced/src/components/FeedPage.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 25 | 26 | 65 | -------------------------------------------------------------------------------- /advanced/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import DetailPage from 'components/DetailPage' 4 | import FeedPage from 'components/FeedPage' 5 | import CreatePage from 'components/CreatePage' 6 | import DraftsPage from 'components/DraftsPage' 7 | import SignupPage from 'components/SignupPage' 8 | import LoginPage from 'components/LoginPage' 9 | import NotFoundPage from 'components/NotFoundPage' 10 | import { checkAuth } from '../utils' 11 | 12 | Vue.use(Router) 13 | 14 | export default new Router({ 15 | mode: 'history', 16 | routes: [ 17 | { 18 | path: '/', 19 | name: 'Feed', 20 | component: FeedPage 21 | },{ 22 | path: '/detail/:id', 23 | name: 'Detail', 24 | component: DetailPage 25 | },{ 26 | path: '/create', 27 | name: 'Create', 28 | secure: true, 29 | component: CreatePage, 30 | },{ 31 | path: '/drafts', 32 | name: 'Drafts', 33 | secure: true, 34 | component: DraftsPage, 35 | },{ 36 | path: '/login', 37 | name: 'Login', 38 | unAuth: true, 39 | component: LoginPage 40 | },{ 41 | path: '/signup', 42 | name: 'Signup', 43 | unAuth: true, 44 | component: SignupPage 45 | },{ path: '*', 46 | component: NotFoundPage 47 | } 48 | ] 49 | }) -------------------------------------------------------------------------------- /basic/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /minimal/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /advanced/server/src/resolvers/Mutation/post.js: -------------------------------------------------------------------------------- 1 | const { getUserId } = require('../../utils') 2 | 3 | const post = { 4 | async createDraft(parent, { title, text }, ctx, info) { 5 | const userId = getUserId(ctx) 6 | return ctx.db.mutation.createPost( 7 | { 8 | data: { 9 | title, 10 | text, 11 | isPublished: false, 12 | author: { 13 | connect: { id: userId }, 14 | }, 15 | }, 16 | }, 17 | info 18 | ) 19 | }, 20 | 21 | async publish(parent, { id }, ctx, info) { 22 | const userId = getUserId(ctx) 23 | const postExists = await ctx.db.exists.Post({ 24 | id, 25 | author: { id: userId }, 26 | }) 27 | if (!postExists) { 28 | throw new Error(`Post not found or you're not the author`) 29 | } 30 | 31 | return ctx.db.mutation.updatePost( 32 | { 33 | where: { id }, 34 | data: { isPublished: true }, 35 | }, 36 | info, 37 | ) 38 | }, 39 | 40 | async deletePost(parent, { id }, ctx, info) { 41 | const userId = getUserId(ctx) 42 | const postExists = await ctx.db.exists.Post({ 43 | id, 44 | author: { id: userId }, 45 | }) 46 | if (!postExists) { 47 | throw new Error(`Post not found or you're not the author`) 48 | } 49 | 50 | return ctx.db.mutation.deletePost({ where: { id } }) 51 | }, 52 | } 53 | 54 | module.exports = { post } 55 | -------------------------------------------------------------------------------- /advanced/src/components/DraftsPage.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 26 | 27 | 66 | -------------------------------------------------------------------------------- /basic/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import { ApolloClient } from 'apollo-client' 4 | import { HttpLink } from 'apollo-link-http' 5 | import { InMemoryCache } from 'apollo-cache-inmemory' 6 | import { WebSocketLink } from 'apollo-link-ws' 7 | import { ApolloLink, split } from 'apollo-link' 8 | import { getMainDefinition } from 'apollo-utilities' 9 | import VueApollo from 'vue-apollo' 10 | import router from './router' 11 | 12 | // Vue production tip config 13 | Vue.config.productionTip = false 14 | 15 | const httpLink = new HttpLink({ uri: 'http://localhost:4000/' }) 16 | 17 | const wsLink = new WebSocketLink({ 18 | uri: `ws://localhost:4000/`, 19 | options: { 20 | reconnect: true, 21 | } 22 | }) 23 | 24 | const link = split( 25 | // split based on operation type 26 | ({ query }) => { 27 | const { kind, operation } = getMainDefinition(query) 28 | return kind === 'OperationDefinition' && operation === 'subscription' 29 | }, 30 | wsLink, 31 | httpLink, 32 | ) 33 | 34 | // apollo client setup 35 | const client = new ApolloClient({ 36 | link: ApolloLink.from([link]), 37 | cache: new InMemoryCache(), 38 | connectToDevTools: true 39 | }) 40 | 41 | // Install the vue plugin 42 | Vue.use(VueApollo) 43 | 44 | // Apollo provider init 45 | const apolloProvider = new VueApollo({ 46 | defaultClient: client 47 | }) 48 | 49 | // Start the app 50 | new Vue({ 51 | el: '#app', 52 | provide: apolloProvider.provide(), 53 | router, 54 | render: h => h(App) 55 | }).$mount('#app') -------------------------------------------------------------------------------- /advanced/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /basic/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /minimal/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /basic/server/src/index.js: -------------------------------------------------------------------------------- 1 | const { GraphQLServer } = require('graphql-yoga') 2 | const { Prisma } = require('prisma-binding') 3 | 4 | const resolvers = { 5 | Query: { 6 | feed(parent, args, ctx, info) { 7 | return ctx.db.query.posts({ where: { isPublished: true } }, info) 8 | }, 9 | drafts(parent, args, ctx, info) { 10 | return ctx.db.query.posts({ where: { isPublished: false } }, info) 11 | }, 12 | post(parent, { id }, ctx, info) { 13 | return ctx.db.query.post({ where: { id: id } }, info) 14 | }, 15 | }, 16 | Mutation: { 17 | createDraft(parent, { title, text }, ctx, info) { 18 | return ctx.db.mutation.createPost( 19 | { data: { title, text, isPublished: false } }, 20 | info, 21 | ) 22 | }, 23 | deletePost(parent, { id }, ctx, info) { 24 | return ctx.db.mutation.deletePost({where: { id } }, info) 25 | }, 26 | publish(parent, { id }, ctx, info) { 27 | return ctx.db.mutation.updatePost( 28 | { 29 | where: { id }, 30 | data: { isPublished: true }, 31 | }, 32 | info, 33 | ) 34 | }, 35 | }, 36 | } 37 | 38 | const server = new GraphQLServer({ 39 | typeDefs: './src/schema.graphql', 40 | resolvers, 41 | context: req => ({ 42 | ...req, 43 | db: new Prisma({ 44 | typeDefs: 'src/generated/prisma.graphql', 45 | endpoint: '__PRISMA_ENDPOINT__', 46 | secret: 'mysecret123', 47 | debug: true, 48 | }), 49 | }), 50 | }) 51 | 52 | server.start(() => console.log('Server is running on http://localhost:4000')) 53 | -------------------------------------------------------------------------------- /minimal/server/README.md: -------------------------------------------------------------------------------- 1 |

Boilerplate for a Minimal GraphQL Server

2 | 3 |
4 | 5 |
🚀 Bootstrap your GraphQL server within seconds
6 |
Basic starter kit for a flexible GraphQL server for Node.js - based on best practices from the GraphQL community.
7 | 8 | ## Features 9 | 10 | - **Scalable GraphQL server:** The server uses [`graphql-yoga`](https://github.com/prisma/graphql-yoga) which is based on Apollo Server & Express 11 | 12 | - **Simple Hello World example:** Where it either returns `Hello !` or `Hello World!` if no name argument is provided. 13 | 14 | ## Getting started 15 | 16 | ```sh 17 | # 1. Navigate to the folder 18 | # 2. Run yarn install or npm install 19 | # 3. Start server using yarn run start or npm start (runs on http://localhost:4000) and open in GraphQL Playground 20 | ``` 21 | ![alt text](https://i.imgur.com/yjkt0mQ.png) ![alt text](https://i.imgur.com/Ym06T2Y.png) 22 | 23 | ## Documentation 24 | 25 | ### Commands 26 | 27 | * `yarn start` or `npm run start` starts GraphQL server on `http://localhost:4000` 28 | 29 | ### Project structure 30 | 31 | ![](https://i.imgur.com/uD2fqZo.png) 32 | 33 | | File name               | Description         

| 34 | | :-- | :-- | 35 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ | 36 | | `  ├── index.js` | The entry point for your GraphQL server | 37 | 38 | 39 | ## Contributing 40 | 41 | 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. 42 | 43 | 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/). 44 | -------------------------------------------------------------------------------- /basic/src/components/DraftsPage.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 54 | 55 | 91 | -------------------------------------------------------------------------------- /advanced/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /basic/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /minimal/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /minimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-apollo-instagram-example", 3 | "version": "0.0.1", 4 | "description": ":camera: Instagram clone built with Vue 2 & Apollo Client", 5 | "private": true, 6 | "scripts": { 7 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 8 | "start": "npm run dev", 9 | "build": "node build/build.js" 10 | }, 11 | "dependencies": { 12 | "apollo-cache-inmemory": "1.6.6", 13 | "apollo-client": "2.6.10", 14 | "apollo-link-http": "1.5.17", 15 | "graphql": "0.13.2", 16 | "graphql-tag": "2.12.6", 17 | "vue": "2.7.16", 18 | "vue-apollo": "3.1.2", 19 | "vue-router": "3.6.5", 20 | "vue-template-compiler": "2.7.16" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "8.6.5", 24 | "babel-core": "6.26.3", 25 | "babel-helper-vue-jsx-merge-props": "2.0.3", 26 | "babel-loader": "7.1.5", 27 | "babel-plugin-syntax-jsx": "6.18.0", 28 | "babel-plugin-transform-runtime": "6.23.0", 29 | "babel-plugin-transform-vue-jsx": "3.7.0", 30 | "babel-preset-env": "1.7.0", 31 | "babel-preset-stage-2": "6.24.1", 32 | "chalk": "2.4.2", 33 | "copy-webpack-plugin": "4.6.0", 34 | "css-loader": "0.28.11", 35 | "eslint": "4.19.1", 36 | "eslint-plugin-vue": "4.7.1", 37 | "extract-text-webpack-plugin": "3.0.2", 38 | "file-loader": "1.1.11", 39 | "friendly-errors-webpack-plugin": "1.7.0", 40 | "html-webpack-plugin": "2.30.1", 41 | "node-notifier": "5.4.5", 42 | "optimize-css-assets-webpack-plugin": "4.0.3", 43 | "ora": "2.1.0", 44 | "portfinder": "1.0.33", 45 | "postcss-import": "11.1.0", 46 | "postcss-loader": "2.1.6", 47 | "postcss-url": "7.3.2", 48 | "rimraf": "2.7.1", 49 | "semver": "5.7.2", 50 | "shelljs": "0.8.5", 51 | "tachyons": "4.12.0", 52 | "uglifyjs-webpack-plugin": "1.3.0", 53 | "url-loader": "0.6.2", 54 | "vue-loader": "14.2.4", 55 | "vue-style-loader": "4.1.3", 56 | "webpack": "3.12.0", 57 | "webpack-bundle-analyzer": "2.13.1", 58 | "webpack-dev-server": "2.11.5", 59 | "webpack-merge": "4.2.2" 60 | }, 61 | "engines": { 62 | "node": ">= 6.0.0", 63 | "npm": ">= 3.0.0" 64 | }, 65 | "browserslist": [ 66 | "> 1%", 67 | "last 2 versions", 68 | "not ie <= 8" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /minimal/src/App.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 55 | 56 | 101 | -------------------------------------------------------------------------------- /basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-apollo-instagram-example", 3 | "version": "0.0.1", 4 | "description": ":camera: Instagram clone built with Vue 2 & Apollo Client", 5 | "private": true, 6 | "scripts": { 7 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 8 | "start": "npm run dev", 9 | "build": "node build/build.js" 10 | }, 11 | "dependencies": { 12 | "apollo-cache-inmemory": "1.6.6", 13 | "apollo-client": "2.6.10", 14 | "apollo-link": "1.2.14", 15 | "apollo-link-http": "1.5.17", 16 | "apollo-link-ws": "1.0.20", 17 | "graphql": "0.13.2", 18 | "graphql-tag": "2.12.6", 19 | "subscriptions-transport-ws": "0.11.0", 20 | "vue": "2.7.16", 21 | "vue-apollo": "3.1.2", 22 | "vue-router": "3.6.5", 23 | "vue-template-compiler": "2.7.16" 24 | }, 25 | "devDependencies": { 26 | "autoprefixer": "8.6.5", 27 | "babel-core": "6.26.3", 28 | "babel-helper-vue-jsx-merge-props": "2.0.3", 29 | "babel-loader": "7.1.5", 30 | "babel-plugin-syntax-jsx": "6.18.0", 31 | "babel-plugin-transform-runtime": "6.23.0", 32 | "babel-plugin-transform-vue-jsx": "3.7.0", 33 | "babel-preset-env": "1.7.0", 34 | "babel-preset-stage-2": "6.24.1", 35 | "chalk": "2.4.2", 36 | "copy-webpack-plugin": "4.6.0", 37 | "css-loader": "0.28.11", 38 | "eslint": "4.19.1", 39 | "eslint-plugin-vue": "4.7.1", 40 | "extract-text-webpack-plugin": "3.0.2", 41 | "file-loader": "1.1.11", 42 | "friendly-errors-webpack-plugin": "1.7.0", 43 | "html-webpack-plugin": "2.30.1", 44 | "node-notifier": "5.4.5", 45 | "optimize-css-assets-webpack-plugin": "4.0.3", 46 | "ora": "2.1.0", 47 | "portfinder": "1.0.33", 48 | "postcss-import": "11.1.0", 49 | "postcss-loader": "2.1.6", 50 | "postcss-url": "7.3.2", 51 | "rimraf": "2.7.1", 52 | "semver": "5.7.2", 53 | "shelljs": "0.8.5", 54 | "tachyons": "4.12.0", 55 | "uglifyjs-webpack-plugin": "1.3.0", 56 | "url-loader": "0.6.2", 57 | "vue-loader": "14.2.4", 58 | "vue-style-loader": "4.1.3", 59 | "webpack": "3.12.0", 60 | "webpack-bundle-analyzer": "2.13.1", 61 | "webpack-dev-server": "2.11.5", 62 | "webpack-merge": "4.2.2" 63 | }, 64 | "engines": { 65 | "node": ">= 6.0.0", 66 | "npm": ">= 3.0.0" 67 | }, 68 | "browserslist": [ 69 | "> 1%", 70 | "last 2 versions", 71 | "not ie <= 8" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /basic/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['*', '.js', '.vue', '.json'], 27 | modules: ['src', 'node_modules'], 28 | alias: { 29 | 'vue$': 'vue/dist/vue.common.js', 30 | '@': resolve('src'), 31 | 'components': path.resolve(__dirname, '../src/components') 32 | } 33 | }, 34 | module: { 35 | rules: [ 36 | { 37 | test: /\.vue$/, 38 | loader: 'vue-loader', 39 | options: vueLoaderConfig 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel-loader', 44 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 45 | }, 46 | { 47 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 48 | loader: 'url-loader', 49 | options: { 50 | limit: 10000, 51 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 52 | } 53 | }, 54 | { 55 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 56 | loader: 'url-loader', 57 | options: { 58 | limit: 10000, 59 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 60 | } 61 | }, 62 | { 63 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 64 | loader: 'url-loader', 65 | options: { 66 | limit: 10000, 67 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 68 | } 69 | } 70 | ] 71 | }, 72 | node: { 73 | // prevent webpack from injecting useless setImmediate polyfill because Vue 74 | // source contains it (although only uses it if it's native). 75 | setImmediate: false, 76 | // prevent webpack from injecting mocks to Node native modules 77 | // that does not make sense for the client 78 | dgram: 'empty', 79 | fs: 'empty', 80 | net: 'empty', 81 | tls: 'empty', 82 | child_process: 'empty' 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /minimal/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['*', '.js', '.vue', '.json'], 27 | modules: ['src', 'node_modules'], 28 | alias: { 29 | 'vue$': 'vue/dist/vue.common.js', 30 | '@': resolve('src'), 31 | 'components': path.resolve(__dirname, '../src/components') 32 | } 33 | }, 34 | module: { 35 | rules: [ 36 | { 37 | test: /\.vue$/, 38 | loader: 'vue-loader', 39 | options: vueLoaderConfig 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel-loader', 44 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 45 | }, 46 | { 47 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 48 | loader: 'url-loader', 49 | options: { 50 | limit: 10000, 51 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 52 | } 53 | }, 54 | { 55 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 56 | loader: 'url-loader', 57 | options: { 58 | limit: 10000, 59 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 60 | } 61 | }, 62 | { 63 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 64 | loader: 'url-loader', 65 | options: { 66 | limit: 10000, 67 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 68 | } 69 | } 70 | ] 71 | }, 72 | node: { 73 | // prevent webpack from injecting useless setImmediate polyfill because Vue 74 | // source contains it (although only uses it if it's native). 75 | setImmediate: false, 76 | // prevent webpack from injecting mocks to Node native modules 77 | // that does not make sense for the client 78 | dgram: 'empty', 79 | fs: 'empty', 80 | net: 'empty', 81 | tls: 'empty', 82 | child_process: 'empty' 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /advanced/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['*', '.js', '.vue', '.json'], 27 | modules: ['src', 'node_modules'], 28 | alias: { 29 | 'vue$': 'vue/dist/vue.common.js', 30 | '@': resolve('src'), 31 | 'components': path.resolve(__dirname, '../src/components') 32 | } 33 | }, 34 | module: { 35 | rules: [ 36 | { 37 | test: /\.vue$/, 38 | loader: 'vue-loader', 39 | options: vueLoaderConfig 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel-loader', 44 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 45 | }, 46 | { 47 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 48 | loader: 'url-loader', 49 | options: { 50 | limit: 10000, 51 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 52 | } 53 | }, 54 | { 55 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 56 | loader: 'url-loader', 57 | options: { 58 | limit: 10000, 59 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 60 | } 61 | }, 62 | { 63 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 64 | loader: 'url-loader', 65 | options: { 66 | limit: 10000, 67 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 68 | } 69 | } 70 | ] 71 | }, 72 | node: { 73 | // prevent webpack from injecting useless setImmediate polyfill because Vue 74 | // source contains it (although only uses it if it's native). 75 | setImmediate: false, 76 | // prevent webpack from injecting mocks to Node native modules 77 | // that does not make sense for the client 78 | dgram: 'empty', 79 | fs: 'empty', 80 | net: 'empty', 81 | tls: 'empty', 82 | child_process: 'empty' 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /advanced/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-apollo-instagram-example", 3 | "version": "0.0.1", 4 | "description": ":camera: Instagram clone built with Vue 2 & Apollo Client", 5 | "private": true, 6 | "scripts": { 7 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 8 | "start": "npm run dev", 9 | "build": "node build/build.js" 10 | }, 11 | "dependencies": { 12 | "apollo-cache-inmemory": "1.6.6", 13 | "apollo-client": "2.6.10", 14 | "apollo-link": "1.2.14", 15 | "apollo-link-context": "1.0.20", 16 | "apollo-link-http": "1.5.17", 17 | "apollo-link-state": "0.4.2", 18 | "apollo-link-ws": "1.0.20", 19 | "apollo-utilities": "1.3.4", 20 | "graphql": "0.13.2", 21 | "graphql-tag": "2.12.6", 22 | "jwt-decode": "2.2.0", 23 | "subscriptions-transport-ws": "0.11.0", 24 | "vue": "2.7.16", 25 | "vue-apollo": "3.1.2", 26 | "vue-router": "3.6.5", 27 | "vue-template-compiler": "2.7.16" 28 | }, 29 | "devDependencies": { 30 | "autoprefixer": "8.6.5", 31 | "babel-core": "6.26.3", 32 | "babel-helper-vue-jsx-merge-props": "2.0.3", 33 | "babel-loader": "7.1.5", 34 | "babel-plugin-syntax-jsx": "6.18.0", 35 | "babel-plugin-transform-runtime": "6.23.0", 36 | "babel-plugin-transform-vue-jsx": "3.7.0", 37 | "babel-preset-env": "1.7.0", 38 | "babel-preset-stage-2": "6.24.1", 39 | "chalk": "2.4.2", 40 | "copy-webpack-plugin": "4.6.0", 41 | "css-loader": "0.28.11", 42 | "extract-text-webpack-plugin": "3.0.2", 43 | "file-loader": "1.1.11", 44 | "friendly-errors-webpack-plugin": "1.7.0", 45 | "html-webpack-plugin": "2.30.1", 46 | "node-notifier": "5.4.5", 47 | "optimize-css-assets-webpack-plugin": "4.0.3", 48 | "ora": "2.1.0", 49 | "portfinder": "1.0.33", 50 | "postcss-import": "11.1.0", 51 | "postcss-loader": "2.1.6", 52 | "postcss-url": "7.3.2", 53 | "rimraf": "2.7.1", 54 | "semver": "5.7.2", 55 | "shelljs": "0.8.5", 56 | "tachyons": "4.12.0", 57 | "uglifyjs-webpack-plugin": "1.3.0", 58 | "url-loader": "0.6.2", 59 | "vue-loader": "14.2.4", 60 | "vue-style-loader": "4.1.3", 61 | "vue-template-compiler": "2.7.16", 62 | "webpack": "3.12.0", 63 | "webpack-bundle-analyzer": "2.13.1", 64 | "webpack-dev-server": "2.11.5", 65 | "webpack-merge": "4.2.2" 66 | }, 67 | "engines": { 68 | "node": ">= 6.0.0", 69 | "npm": ">= 3.0.0" 70 | }, 71 | "browserslist": [ 72 | "> 1%", 73 | "last 2 versions", 74 | "not ie <= 8" 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /basic/src/App.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 123 | -------------------------------------------------------------------------------- /minimal/README.md: -------------------------------------------------------------------------------- 1 |

Boilerplate for a Minimal Fullstack GraphQL App with Vue

2 | 3 |
4 | 5 | ![](https://camo.githubusercontent.com/e78e52aa36ff76ef5e142bfeced3b5f657b3fc26/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a483941414e6f6f664c716a53313058643554775259772e706e67) 6 | 7 |
🚀 Bootstrap your fullstack GraphQL app within seconds
8 |
Basic starter kit for a fullstack GraphQL app with Vue 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 | - **Tooling**: Out-of-the-box support for [GraphQL Playground](https://github.com/prisma/graphql-playground) & [query performance tracing](https://github.com/apollographql/apollo-tracing) 15 | - **Extensible**: Minimal [GraphQL schema](https://blog.graph.cool/graphql-server-basics-the-schema-ac5e2950214e) – easy to extend 16 | - **No configuration overhead**: Preconfigured [`graphql-config`](https://github.com/prisma/graphql-config) setup 17 | 18 | 19 | ## Requirements 20 | 21 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`: 22 | 23 | ```sh 24 | npm install -g graphql-cli 25 | ``` 26 | 27 | ## Getting started 28 | 29 | ```sh 30 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `vue-fullstack-minimal` boilerplate 31 | graphql create my-app --boilerplate vue-fullstack-minimal 32 | 33 | # 2. When prompted, deploy the Prisma service to a _public cluster_ 34 | 35 | # 3. Navigate into the `server` directory of the new project 36 | cd my-app/server 37 | 38 | # 4. Start the server 39 | yarn start # runs server on http://localhost:4000 40 | 41 | # 5. Open a new tab in the terminal and navigate back into my-app; 42 | # then run the app 43 | cd .. 44 | yarn start 45 | ``` 46 | 47 | ## Contributing 48 | 49 | 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. 50 | 51 | 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/). 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Fullstack GraphQL Boilerplates for VueJs & Node.js

2 | 3 |
4 | 5 | ![](https://camo.githubusercontent.com/e78e52aa36ff76ef5e142bfeced3b5f657b3fc26/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a483941414e6f6f664c716a53313058643554775259772e706e67) 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 **VueJs & Apollo tutorial**, visit [How to GraphQL](https://www.howtographql.com/vue-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/build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = require('./webpack.dev.conf') 14 | 15 | // default port where dev server listens for incoming traffic 16 | var port = process.env.PORT || config.dev.port 17 | // automatically open browser, if not set will be false 18 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 19 | // Define HTTP proxies to your custom API backend 20 | // https://github.com/chimurai/http-proxy-middleware 21 | var proxyTable = config.dev.proxyTable 22 | 23 | var app = express() 24 | var compiler = webpack(webpackConfig) 25 | 26 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 27 | publicPath: webpackConfig.output.publicPath, 28 | quiet: true 29 | }) 30 | 31 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 32 | log: () => {} 33 | }) 34 | // force page reload when html-webpack-plugin template changes 35 | compiler.plugin('compilation', function (compilation) { 36 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 37 | hotMiddleware.publish({ action: 'reload' }) 38 | cb() 39 | }) 40 | }) 41 | 42 | // proxy api requests 43 | Object.keys(proxyTable).forEach(function (context) { 44 | var options = proxyTable[context] 45 | if (typeof options === 'string') { 46 | options = { target: options } 47 | } 48 | app.use(proxyMiddleware(options.filter || context, options)) 49 | }) 50 | 51 | // handle fallback for HTML5 history API 52 | app.use(require('connect-history-api-fallback')()) 53 | 54 | // serve webpack bundle output 55 | app.use(devMiddleware) 56 | 57 | // enable hot-reload and state-preserving 58 | // compilation error display 59 | app.use(hotMiddleware) 60 | 61 | // serve pure static assets 62 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 63 | app.use(staticPath, express.static('./static')) 64 | 65 | var uri = 'http://localhost:' + port 66 | 67 | var _resolve 68 | var readyPromise = new Promise(resolve => { 69 | _resolve = resolve 70 | }) 71 | 72 | console.log('> Starting dev server...') 73 | devMiddleware.waitUntilValid(() => { 74 | console.log('> Listening at ' + uri + '\n') 75 | // when env is testing, don't need open it 76 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 77 | opn(uri) 78 | } 79 | _resolve() 80 | }) 81 | 82 | var server = app.listen(port) 83 | 84 | module.exports = { 85 | ready: readyPromise, 86 | close: () => { 87 | server.close() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /basic/build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = require('./webpack.dev.conf') 14 | 15 | // default port where dev server listens for incoming traffic 16 | var port = process.env.PORT || config.dev.port 17 | // automatically open browser, if not set will be false 18 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 19 | // Define HTTP proxies to your custom API backend 20 | // https://github.com/chimurai/http-proxy-middleware 21 | var proxyTable = config.dev.proxyTable 22 | 23 | var app = express() 24 | var compiler = webpack(webpackConfig) 25 | 26 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 27 | publicPath: webpackConfig.output.publicPath, 28 | quiet: true 29 | }) 30 | 31 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 32 | log: () => {} 33 | }) 34 | // force page reload when html-webpack-plugin template changes 35 | compiler.plugin('compilation', function (compilation) { 36 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 37 | hotMiddleware.publish({ action: 'reload' }) 38 | cb() 39 | }) 40 | }) 41 | 42 | // proxy api requests 43 | Object.keys(proxyTable).forEach(function (context) { 44 | var options = proxyTable[context] 45 | if (typeof options === 'string') { 46 | options = { target: options } 47 | } 48 | app.use(proxyMiddleware(options.filter || context, options)) 49 | }) 50 | 51 | // handle fallback for HTML5 history API 52 | app.use(require('connect-history-api-fallback')()) 53 | 54 | // serve webpack bundle output 55 | app.use(devMiddleware) 56 | 57 | // enable hot-reload and state-preserving 58 | // compilation error display 59 | app.use(hotMiddleware) 60 | 61 | // serve pure static assets 62 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 63 | app.use(staticPath, express.static('./static')) 64 | 65 | var uri = 'http://localhost:' + port 66 | 67 | var _resolve 68 | var readyPromise = new Promise(resolve => { 69 | _resolve = resolve 70 | }) 71 | 72 | console.log('> Starting dev server...') 73 | devMiddleware.waitUntilValid(() => { 74 | console.log('> Listening at ' + uri + '\n') 75 | // when env is testing, don't need open it 76 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 77 | opn(uri) 78 | } 79 | _resolve() 80 | }) 81 | 82 | var server = app.listen(port) 83 | 84 | module.exports = { 85 | ready: readyPromise, 86 | close: () => { 87 | server.close() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /minimal/build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = require('./webpack.dev.conf') 14 | 15 | // default port where dev server listens for incoming traffic 16 | var port = process.env.PORT || config.dev.port 17 | // automatically open browser, if not set will be false 18 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 19 | // Define HTTP proxies to your custom API backend 20 | // https://github.com/chimurai/http-proxy-middleware 21 | var proxyTable = config.dev.proxyTable 22 | 23 | var app = express() 24 | var compiler = webpack(webpackConfig) 25 | 26 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 27 | publicPath: webpackConfig.output.publicPath, 28 | quiet: true 29 | }) 30 | 31 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 32 | log: () => {} 33 | }) 34 | // force page reload when html-webpack-plugin template changes 35 | compiler.plugin('compilation', function (compilation) { 36 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 37 | hotMiddleware.publish({ action: 'reload' }) 38 | cb() 39 | }) 40 | }) 41 | 42 | // proxy api requests 43 | Object.keys(proxyTable).forEach(function (context) { 44 | var options = proxyTable[context] 45 | if (typeof options === 'string') { 46 | options = { target: options } 47 | } 48 | app.use(proxyMiddleware(options.filter || context, options)) 49 | }) 50 | 51 | // handle fallback for HTML5 history API 52 | app.use(require('connect-history-api-fallback')()) 53 | 54 | // serve webpack bundle output 55 | app.use(devMiddleware) 56 | 57 | // enable hot-reload and state-preserving 58 | // compilation error display 59 | app.use(hotMiddleware) 60 | 61 | // serve pure static assets 62 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 63 | app.use(staticPath, express.static('./static')) 64 | 65 | var uri = 'http://localhost:' + port 66 | 67 | var _resolve 68 | var readyPromise = new Promise(resolve => { 69 | _resolve = resolve 70 | }) 71 | 72 | console.log('> Starting dev server...') 73 | devMiddleware.waitUntilValid(() => { 74 | console.log('> Listening at ' + uri + '\n') 75 | // when env is testing, don't need open it 76 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 77 | opn(uri) 78 | } 79 | _resolve() 80 | }) 81 | 82 | var server = app.listen(port) 83 | 84 | module.exports = { 85 | ready: readyPromise, 86 | close: () => { 87 | server.close() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /advanced/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /basic/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /minimal/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /advanced/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import { ApolloClient } from 'apollo-client' 4 | import { HttpLink } from 'apollo-link-http' 5 | import { setContext } from 'apollo-link-context' 6 | import { InMemoryCache } from 'apollo-cache-inmemory' 7 | import { WebSocketLink } from 'apollo-link-ws' 8 | import { ApolloLink, split } from 'apollo-link' 9 | import { withClientState } from 'apollo-link-state' 10 | import { getMainDefinition } from 'apollo-utilities' 11 | import VueApollo from 'vue-apollo' 12 | import router from './router' 13 | import { USER_ID, AUTH_TOKEN } from './constants' 14 | 15 | // Vue production tip config 16 | Vue.config.productionTip = false 17 | 18 | const httpLink = new HttpLink({ uri: 'http://localhost:4000/' }) 19 | 20 | const middlewareLink = new ApolloLink((operation, forward) => { 21 | // get the authentication token from local storage if it exists 22 | const token = localStorage.getItem(AUTH_TOKEN) 23 | // return the headers to the context so httpLink can read them 24 | operation.setContext({ 25 | headers: { 26 | Authorization: token ? `Bearer ${token}` : "", 27 | } 28 | }) 29 | return forward(operation) 30 | }) 31 | 32 | // Authenticated httplink 33 | const httpLinkAuth = middlewareLink.concat(httpLink) 34 | 35 | const wsLink = new WebSocketLink({ 36 | uri: `ws://localhost:4000/`, 37 | options: { 38 | reconnect: true, 39 | connectionParams: { 40 | Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN)}` 41 | } 42 | } 43 | }) 44 | 45 | const link = split( 46 | // split based on operation type 47 | ({ query }) => { 48 | const { kind, operation } = getMainDefinition(query) 49 | return kind === 'OperationDefinition' && operation === 'subscription' 50 | }, 51 | wsLink, 52 | httpLinkAuth, 53 | ) 54 | 55 | // apollo client setup 56 | const client = new ApolloClient({ 57 | link: ApolloLink.from([link]), 58 | cache: new InMemoryCache(), 59 | connectToDevTools: true 60 | }) 61 | 62 | // Install the vue plugin 63 | Vue.use(VueApollo) 64 | 65 | // Apollo provider init 66 | const apolloProvider = new VueApollo({ 67 | defaultClient: client 68 | }) 69 | 70 | // get user authentication token saved after login 71 | let token = localStorage.getItem(AUTH_TOKEN) 72 | 73 | router.beforeEach((to, from, next) => { 74 | // Look at all routes 75 | router.options.routes.forEach((route) => { 76 | // If this is the current route and it's secure 77 | if (to.matched[0].path === route.path && route.secure) { 78 | // Verify that the user isn't logged in 79 | if(!token || token === '' || token === null){ 80 | // Route back to the landing 81 | return next('/login'); 82 | } 83 | } 84 | if (to.matched[0].path === route.path && route.unAuth) { 85 | // Verify that the user isn't logged in 86 | if(token){ 87 | // Route back to the landing 88 | return next('/'); 89 | } 90 | } 91 | }); 92 | // Proceed as normal 93 | next(); 94 | }); 95 | 96 | // Start the app 97 | new Vue({ 98 | el: '#app', 99 | provide: apolloProvider.provide(), 100 | router, 101 | data: { 102 | token 103 | }, 104 | render: h => h(App) 105 | }).$mount('#app') 106 | -------------------------------------------------------------------------------- /basic/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /minimal/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /advanced/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /advanced/src/App.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 54 | 55 | 155 | -------------------------------------------------------------------------------- /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.12.2" 7 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" 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 | -------------------------------------------------------------------------------- /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.12.2" 7 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" 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 | -------------------------------------------------------------------------------- /basic/server/src/generated/prisma.graphql: -------------------------------------------------------------------------------- 1 | # THIS FILE HAS BEEN AUTO-GENERATED BY THE "PRISMA DEPLOY" 2 | # DO NOT EDIT THIS FILE DIRECTLY 3 | 4 | # 5 | # Model Types 6 | # 7 | 8 | type Post implements Node { 9 | id: ID! 10 | isPublished: Boolean! 11 | title: String! 12 | text: String! 13 | } 14 | 15 | 16 | # 17 | # Other Types 18 | # 19 | 20 | type BatchPayload { 21 | count: Long! 22 | } 23 | 24 | scalar Long 25 | 26 | type Mutation { 27 | createPost(data: PostCreateInput!): Post! 28 | updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post 29 | deletePost(where: PostWhereUniqueInput!): Post 30 | upsertPost(where: PostWhereUniqueInput!, create: PostCreateInput!, update: PostUpdateInput!): Post! 31 | updateManyPosts(data: PostUpdateInput!, where: PostWhereInput!): BatchPayload! 32 | deleteManyPosts(where: PostWhereInput!): BatchPayload! 33 | resetData: Boolean 34 | } 35 | 36 | enum MutationType { 37 | CREATED 38 | UPDATED 39 | DELETED 40 | } 41 | 42 | interface Node { 43 | id: ID! 44 | } 45 | 46 | type PageInfo { 47 | hasNextPage: Boolean! 48 | hasPreviousPage: Boolean! 49 | startCursor: String 50 | endCursor: String 51 | } 52 | 53 | type PostConnection { 54 | pageInfo: PageInfo! 55 | edges: [PostEdge]! 56 | } 57 | 58 | input PostCreateInput { 59 | isPublished: Boolean! 60 | title: String! 61 | text: String! 62 | } 63 | 64 | type PostEdge { 65 | node: Post! 66 | cursor: String! 67 | } 68 | 69 | enum PostOrderByInput { 70 | id_ASC 71 | id_DESC 72 | isPublished_ASC 73 | isPublished_DESC 74 | title_ASC 75 | title_DESC 76 | text_ASC 77 | text_DESC 78 | updatedAt_ASC 79 | updatedAt_DESC 80 | createdAt_ASC 81 | createdAt_DESC 82 | } 83 | 84 | type PostPreviousValues { 85 | id: ID! 86 | isPublished: Boolean! 87 | title: String! 88 | text: String! 89 | } 90 | 91 | type PostSubscriptionPayload { 92 | mutation: MutationType! 93 | node: Post 94 | updatedFields: [String!] 95 | previousValues: PostPreviousValues 96 | } 97 | 98 | input PostSubscriptionWhereInput { 99 | AND: [PostSubscriptionWhereInput!] 100 | OR: [PostSubscriptionWhereInput!] 101 | mutation_in: [MutationType!] 102 | updatedFields_contains: String 103 | updatedFields_contains_every: [String!] 104 | updatedFields_contains_some: [String!] 105 | node: PostWhereInput 106 | } 107 | 108 | input PostUpdateInput { 109 | isPublished: Boolean 110 | title: String 111 | text: String 112 | } 113 | 114 | input PostWhereInput { 115 | AND: [PostWhereInput!] 116 | OR: [PostWhereInput!] 117 | id: ID 118 | id_not: ID 119 | id_in: [ID!] 120 | id_not_in: [ID!] 121 | id_lt: ID 122 | id_lte: ID 123 | id_gt: ID 124 | id_gte: ID 125 | id_contains: ID 126 | id_not_contains: ID 127 | id_starts_with: ID 128 | id_not_starts_with: ID 129 | id_ends_with: ID 130 | id_not_ends_with: ID 131 | isPublished: Boolean 132 | isPublished_not: Boolean 133 | title: String 134 | title_not: String 135 | title_in: [String!] 136 | title_not_in: [String!] 137 | title_lt: String 138 | title_lte: String 139 | title_gt: String 140 | title_gte: String 141 | title_contains: String 142 | title_not_contains: String 143 | title_starts_with: String 144 | title_not_starts_with: String 145 | title_ends_with: String 146 | title_not_ends_with: String 147 | text: String 148 | text_not: String 149 | text_in: [String!] 150 | text_not_in: [String!] 151 | text_lt: String 152 | text_lte: String 153 | text_gt: String 154 | text_gte: String 155 | text_contains: String 156 | text_not_contains: String 157 | text_starts_with: String 158 | text_not_starts_with: String 159 | text_ends_with: String 160 | text_not_ends_with: String 161 | } 162 | 163 | input PostWhereUniqueInput { 164 | id: ID 165 | } 166 | 167 | type Query { 168 | posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post]! 169 | post(where: PostWhereUniqueInput!): Post 170 | postsConnection(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): PostConnection! 171 | node(id: ID!): Node 172 | } 173 | 174 | type Subscription { 175 | post(where: PostSubscriptionWhereInput): PostSubscriptionPayload 176 | } 177 | -------------------------------------------------------------------------------- /advanced/README.md: -------------------------------------------------------------------------------- 1 |

Boilerplate for a Basic Fullstack GraphQL App with Vue

2 | 3 |
4 | 5 | ![](https://imgur.com/ousyQaC.png) 6 | 7 |
🚀 Bootstrap your fullstack GraphQL app within seconds
8 |
Basic starter kit for a fullstack GraphQL app with Vue 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 | 20 | ## Requirements 21 | 22 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`: 23 | 24 | ```sh 25 | npm install -g graphql-cli 26 | ``` 27 | 28 | ## Getting started 29 | 30 | ```sh 31 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `vue-fullstack-basic` boilerplate 32 | graphql create my-app --boilerplate vue-fullstack-basic 33 | 34 | # 2. When prompted, deploy the Prisma service to a _public cluster_ 35 | 36 | # 3. Navigate into the `server` directory of the new project 37 | cd my-app/server 38 | 39 | # 4. Start the server 40 | yarn dev # runs server on http://localhost:4000, and opens GraphQL PLayground 41 | 42 | # 5. Open a new tab in the terminal and navigate back into my-app; 43 | # then run the app 44 | cd .. 45 | yarn start 46 | ``` 47 | 48 | ## Documentation 49 | 50 | ### Commands 51 | 52 | * `yarn start` starts GraphQL server on `http://localhost:4000` 53 | * `yarn dev` starts GraphQL server on `http://localhost:4000` _and_ opens GraphQL Playground 54 | * `yarn playground` opens the GraphQL Playground for the `projects` from [`.graphqlconfig.yml`](./.graphqlconfig.yml) 55 | * `yarn prisma ` gives access to local version of Prisma CLI (e.g. `yarn prisma deploy`) 56 | 57 | > **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. 58 | 59 | ### Server structure 60 | 61 | ![](https://imgur.com/95faUsa.png) 62 | 63 | | File name               | Description         

| 64 | | :-- | :-- | 65 | | `├── .graphqlconfig.yml` | Configuration file based on [`graphql-config`](https://github.com/prisma/graphql-config) (e.g. used by GraphQL Playground).| 66 | | `└── database ` (_directory_) | _Contains all files that are related to the Prisma database service_ |\ 67 | | `  ├── prisma.yml` | The root configuration file for your Prisma database service ([docs](https://www.prismagraphql.com/docs/reference/prisma.yml/overview-and-example-foatho8aip)) | 68 | | `  └── datamodel.graphql` | Defines your data model (written in [GraphQL SDL](https://blog.graph.cool/graphql-sdl-schema-definition-language-6755bcb9ce51)) | 69 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ | 70 | | `  ├── index.js` | The entry point for your GraphQL server | 71 | | `  ├── schema.graphql` | The **application schema** defining the API exposed to client applications | 72 | | `  └── generated` (_directory_) | _Contains generated files_ | 73 | | `    └── prisma.grapghql` | The **Prisma database schema** defining the Prisma GraphQL API | 74 | 75 | ## Contributing 76 | 77 | 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. 78 | 79 | 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/). 80 | -------------------------------------------------------------------------------- /basic/README.md: -------------------------------------------------------------------------------- 1 |

Boilerplate for a Basic Fullstack GraphQL App with Vue

2 | 3 |
4 | 5 | ![](https://camo.githubusercontent.com/e78e52aa36ff76ef5e142bfeced3b5f657b3fc26/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a483941414e6f6f664c716a53313058643554775259772e706e67) 6 | 7 |
🚀 Bootstrap your fullstack GraphQL app within seconds
8 |
Basic starter kit for a fullstack GraphQL app with Vue 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 | 20 | ## Requirements 21 | 22 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`: 23 | 24 | ```sh 25 | npm install -g graphql-cli 26 | ``` 27 | 28 | ## Getting started 29 | 30 | ```sh 31 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `vue-fullstack-basic` boilerplate 32 | graphql create my-app --boilerplate vue-fullstack-basic 33 | 34 | # 2. When prompted, deploy the Prisma service to a _public cluster_ 35 | 36 | # 3. Navigate into the `server` directory of the new project 37 | cd my-app/server 38 | 39 | # 4. Start the server 40 | yarn start # runs server on http://localhost:4000 41 | 42 | # 5. Open a new tab in the terminal and navigate back into my-app; 43 | # then run the app 44 | cd .. 45 | yarn start 46 | ``` 47 | 48 | ## Server Documentation 49 | 50 | ### Commands 51 | 52 | * `yarn start` starts GraphQL server on `http://localhost:4000` 53 | * `yarn dev` starts GraphQL server on `http://localhost:4000` _and_ opens GraphQL Playground 54 | * `yarn playground` opens the GraphQL Playground for the `projects` from [`.graphqlconfig.yml`](./.graphqlconfig.yml) 55 | * `yarn prisma ` gives access to local version of Prisma CLI (e.g. `yarn prisma deploy`) 56 | 57 | > **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. 58 | 59 | ### Server structure 60 | 61 | ![](https://imgur.com/95faUsa.png) 62 | 63 | | File name               | Description         

| 64 | | :-- | :-- | 65 | | `├── .graphqlconfig.yml` | Configuration file based on [`graphql-config`](https://github.com/prisma/graphql-config) (e.g. used by GraphQL Playground).| 66 | | `└── database ` (_directory_) | _Contains all files that are related to the Prisma database service_ |\ 67 | | `  ├── prisma.yml` | The root configuration file for your Prisma database service ([docs](https://www.prismagraphql.com/docs/reference/prisma.yml/overview-and-example-foatho8aip)) | 68 | | `  └── datamodel.graphql` | Defines your data model (written in [GraphQL SDL](https://blog.graph.cool/graphql-sdl-schema-definition-language-6755bcb9ce51)) | 69 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ | 70 | | `  ├── index.js` | The entry point for your GraphQL server | 71 | | `  ├── schema.graphql` | The **application schema** defining the API exposed to client applications | 72 | | `  └── generated` (_directory_) | _Contains generated files_ | 73 | | `    └── prisma.grapghql` | The **Prisma database schema** defining the Prisma GraphQL API | 74 | 75 | ## Contributing 76 | 77 | 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. 78 | 79 | 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/). 80 | -------------------------------------------------------------------------------- /advanced/server/README.md: -------------------------------------------------------------------------------- 1 |

Boilerplate for an Advanced GraphQL Server

2 | 3 |
4 | 5 | ![](https://imgur.com/lIi4YrZ.png) 6 | 7 |
🚀 Bootstrap your GraphQL server within seconds
8 |
Advanced starter kit for a flexible GraphQL server for 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 | - **GraphQL database:** Includes GraphQL database binding to [Prisma](https://www.prismagraphql.com) (running on MySQL) 14 | - **Authentication**: Signup and login workflows are ready to use for your users 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 | - **Realtime updates**: Support for GraphQL subscriptions (_coming soon_) 19 | 20 | For a fully-fledged **GraphQL & Node.js tutorial**, visit [How to GraphQL](https://www.howtographql.com/graphql-js/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). 21 | 22 | ## Requirements 23 | 24 | You need to have the [GraphQL CLI](https://github.com/graphql-cli/graphql-cli) installed to bootstrap your GraphQL server using `graphql create`: 25 | 26 | ```sh 27 | npm install -g graphql-cli 28 | ``` 29 | 30 | ## Getting started 31 | 32 | ```sh 33 | # 1. Bootstrap GraphQL server in directory `my-app`, based on `node-advanced` boilerplate 34 | graphql create my-app --boilerplate node-advanced 35 | 36 | # 2. When prompted, deploy the Prisma service to a _public cluster_ 37 | 38 | # 3. Navigate to the new project 39 | cd my-app 40 | 41 | # 4. Start server (runs on http://localhost:4000) and open GraphQL Playground 42 | yarn dev 43 | ``` 44 | 45 | ![](https://imgur.com/hElq68i.png) 46 | 47 | ## Documentation 48 | 49 | ### Commands 50 | 51 | * `yarn start` starts GraphQL server on `http://localhost:4000` 52 | * `yarn dev` starts GraphQL server on `http://localhost:4000` _and_ opens GraphQL Playground 53 | * `yarn playground` opens the GraphQL Playground for the `projects` from [`.graphqlconfig.yml`](./.graphqlconfig.yml) 54 | * `yarn prisma ` gives access to local version of Prisma CLI (e.g. `yarn prisma deploy`) 55 | 56 | > **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. 57 | 58 | ### Project structure 59 | 60 | ![](https://imgur.com/95faUsa.png) 61 | 62 | | File name               | Description         

| 63 | | :-- | :-- | 64 | | `├── .env` | Defines environment variables | 65 | | `├── .graphqlconfig.yml` | Configuration file based on [`graphql-config`](https://github.com/prisma/graphql-config) (e.g. used by GraphQL Playground).| 66 | | `└── database ` (_directory_) | _Contains all files that are related to the Prisma database service_ |\ 67 | | `  ├── prisma.yml` | The root configuration file for your Prisma database service ([docs](https://www.prismagraphql.com/docs/reference/prisma.yml/overview-and-example-foatho8aip)) | 68 | | `  └── datamodel.graphql` | Defines your data model (written in [GraphQL SDL](https://blog.graph.cool/graphql-sdl-schema-definition-language-6755bcb9ce51)) | 69 | | `└── src ` (_directory_) | _Contains the source files for your GraphQL server_ | 70 | | `  ├── index.js` | The entry point for your GraphQL server | 71 | | `  ├── schema.graphql` | The **application schema** defining the API exposed to client applications | 72 | | `  ├── resolvers` (_directory_) | _Contains the implementation of the resolvers for the application schema_ | 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/). -------------------------------------------------------------------------------- /basic/src/components/DetailPage.vue: -------------------------------------------------------------------------------- 1 | 29 | 113 | 114 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /basic/src/components/CreatePage.vue: -------------------------------------------------------------------------------- 1 |