├── .editorconfig
├── .gitignore
├── .graphqlconfig
├── .travis.yml
├── LICENSE
├── README.adoc
├── build-doc.sh
├── client
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── pom.xml
├── postcss.config.js
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── AlbumCard.vue
│ │ ├── CartNav.vue
│ │ ├── GenreCard.vue
│ │ ├── ReviewCard.vue
│ │ ├── Stars.vue
│ │ └── TrackList.vue
│ ├── main.js
│ ├── main
│ │ └── resources
│ │ │ └── webroot
│ │ │ ├── css
│ │ │ ├── app.4d7df893.css
│ │ │ └── chunk-vendors.a1839bfa.css
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ └── js
│ │ │ ├── app.f5bb45ac.js
│ │ │ ├── app.f5bb45ac.js.map
│ │ │ ├── chunk-vendors.274350e6.js
│ │ │ └── chunk-vendors.274350e6.js.map
│ ├── router
│ │ └── index.js
│ ├── shared
│ │ └── apollo-client.js
│ └── views
│ │ ├── Album.vue
│ │ ├── Cart.vue
│ │ ├── Genre.vue
│ │ └── Home.vue
└── vue.config.js
├── common
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── workshop
│ │ ├── gateway
│ │ ├── EnvironmentUtil.java
│ │ ├── NotLoggedInException.java
│ │ ├── RxDataFetcher.java
│ │ └── WorkshopVerticle.java
│ │ ├── model
│ │ ├── Album.java
│ │ ├── Cart.java
│ │ ├── CartItem.java
│ │ ├── Genre.java
│ │ ├── RatingInfo.java
│ │ ├── Review.java
│ │ ├── ReviewInput.java
│ │ └── Track.java
│ │ └── repository
│ │ ├── AlbumsRepository.java
│ │ ├── CartRepository.java
│ │ ├── GenresRepository.java
│ │ ├── ListOfCodec.java
│ │ ├── RatingRepository.java
│ │ └── TracksRepository.java
│ └── resources
│ ├── vertx-default-jul-logging.properties
│ └── webroot
│ ├── images
│ ├── albums
│ │ ├── achtung-baby.png
│ │ ├── appetite-for-destruction.png
│ │ ├── automatic-for-the-people.png
│ │ ├── back-in-black.png
│ │ ├── dark-side-of-the-moon.png
│ │ ├── enter-the-wu-tang.png
│ │ ├── illmatic.png
│ │ ├── master-of-puppets.png
│ │ ├── ready-to-die.png
│ │ ├── revolver.png
│ │ ├── the-marshall-mathers-lp.png
│ │ └── thriller.png
│ └── genres
│ │ ├── hip-hop.png
│ │ ├── pop.png
│ │ └── rock.png
│ └── login.html
├── deploy-doc.sh
├── gateway
├── pom.xml
├── run.bat
├── run.sh
└── src
│ └── main
│ ├── java
│ └── workshop
│ │ └── gateway
│ │ ├── AddReviewDataFetcher.java
│ │ ├── AddToCartDataFetcher.java
│ │ ├── AlbumDataFetcher.java
│ │ ├── AlbumRatingDataFetcher.java
│ │ ├── AlbumReviewsDataFetcher.java
│ │ ├── AlbumTracksDataFetcher.java
│ │ ├── AlbumsDataFetcher.java
│ │ ├── CartDataFetcher.java
│ │ ├── CartItemAlbumDataFetcher.java
│ │ ├── CurrentUserDataFetcher.java
│ │ ├── GatewayServer.java
│ │ ├── GenresDataFetcher.java
│ │ ├── RemoveFromCartDataFetcher.java
│ │ └── UserUtil.java
│ └── resources
│ ├── musicstore.graphql
│ └── passwordfile
├── inventory
├── pom.xml
├── run.bat
├── run.sh
└── src
│ └── main
│ ├── java
│ └── workshop
│ │ └── inventory
│ │ ├── DataRepository.java
│ │ └── InventoryServer.java
│ └── resources
│ ├── data
│ ├── albums.csv
│ ├── genres.csv
│ └── tracks.csv
│ └── vertx-default-jul-logging.properties
├── pom.xml
├── rating
├── pom.xml
├── run.bat
├── run.sh
└── src
│ └── main
│ ├── java
│ └── workshop
│ │ └── rating
│ │ └── RatingServer.java
│ └── resources
│ └── vertx-default-jul-logging.properties
├── run-postgres.sh
├── steps
├── pom.xml
├── step-0
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── workshop
│ │ │ └── gateway
│ │ │ └── Step0Server.java
│ │ └── solution
│ │ └── java
│ │ └── workshop
│ │ └── gateway
│ │ └── Step0Server.java
├── step-1
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ └── Step1Server.java
│ │ └── resources
│ │ │ └── musicstore.graphql
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── GenresDataFetcher.java
│ │ │ └── Step1Server.java
│ │ └── resources
│ │ └── musicstore.graphql
├── step-2
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── AlbumsDataFetcher.java
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ └── Step2Server.java
│ │ └── resources
│ │ │ └── musicstore.graphql
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ └── Step2Server.java
│ │ └── resources
│ │ └── musicstore.graphql
├── step-3
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── AlbumDataFetcher.java
│ │ │ │ ├── AlbumsDataFetcher.java
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ └── Step3Server.java
│ │ └── resources
│ │ │ └── musicstore.graphql
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AlbumDataFetcher.java
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ └── Step3Server.java
│ │ └── resources
│ │ └── musicstore.graphql
├── step-4
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── AlbumDataFetcher.java
│ │ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ │ ├── AlbumsDataFetcher.java
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ └── Step4Server.java
│ │ └── resources
│ │ │ └── musicstore.graphql
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AlbumDataFetcher.java
│ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ └── Step4Server.java
│ │ └── resources
│ │ └── musicstore.graphql
├── step-5
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── AlbumDataFetcher.java
│ │ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ │ ├── AlbumsDataFetcher.java
│ │ │ │ ├── CurrentUserDataFetcher.java
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ ├── Step5Server.java
│ │ │ │ └── UserUtil.java
│ │ └── resources
│ │ │ ├── musicstore.graphql
│ │ │ └── passwordfile
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AlbumDataFetcher.java
│ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── CurrentUserDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ ├── Step5Server.java
│ │ │ └── UserUtil.java
│ │ └── resources
│ │ ├── musicstore.graphql
│ │ └── passwordfile
├── step-6
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── workshop
│ │ │ │ └── gateway
│ │ │ │ ├── AddReviewDataFetcher.java
│ │ │ │ ├── AlbumDataFetcher.java
│ │ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ │ ├── AlbumsDataFetcher.java
│ │ │ │ ├── CurrentUserDataFetcher.java
│ │ │ │ ├── GenresDataFetcher.java
│ │ │ │ ├── Step6Server.java
│ │ │ │ └── UserUtil.java
│ │ └── resources
│ │ │ ├── musicstore.graphql
│ │ │ └── passwordfile
│ │ └── solution
│ │ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AddReviewDataFetcher.java
│ │ │ ├── AlbumDataFetcher.java
│ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── CurrentUserDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ ├── Step6Server.java
│ │ │ └── UserUtil.java
│ │ └── resources
│ │ ├── musicstore.graphql
│ │ └── passwordfile
└── step-7
│ ├── pom.xml
│ ├── run-solution.bat
│ ├── run-solution.sh
│ ├── run.bat
│ ├── run.sh
│ └── src
│ ├── main
│ ├── java
│ │ └── workshop
│ │ │ └── gateway
│ │ │ ├── AddReviewDataFetcher.java
│ │ │ ├── AddToCartDataFetcher.java
│ │ │ ├── AlbumDataFetcher.java
│ │ │ ├── AlbumRatingDataFetcher.java
│ │ │ ├── AlbumReviewsDataFetcher.java
│ │ │ ├── AlbumTracksDataFetcher.java
│ │ │ ├── AlbumsDataFetcher.java
│ │ │ ├── CartDataFetcher.java
│ │ │ ├── CartItemAlbumDataFetcher.java
│ │ │ ├── CurrentUserDataFetcher.java
│ │ │ ├── GenresDataFetcher.java
│ │ │ ├── RemoveFromCartDataFetcher.java
│ │ │ ├── Step7Server.java
│ │ │ └── UserUtil.java
│ └── resources
│ │ ├── musicstore.graphql
│ │ └── passwordfile
│ └── solution
│ ├── java
│ └── workshop
│ │ └── gateway
│ │ ├── AddReviewDataFetcher.java
│ │ ├── AddToCartDataFetcher.java
│ │ ├── AlbumDataFetcher.java
│ │ ├── AlbumRatingDataFetcher.java
│ │ ├── AlbumReviewsDataFetcher.java
│ │ ├── AlbumTracksDataFetcher.java
│ │ ├── AlbumsDataFetcher.java
│ │ ├── CartDataFetcher.java
│ │ ├── CartItemAlbumDataFetcher.java
│ │ ├── CurrentUserDataFetcher.java
│ │ ├── GenresDataFetcher.java
│ │ ├── RemoveFromCartDataFetcher.java
│ │ ├── Step7Server.java
│ │ └── UserUtil.java
│ └── resources
│ ├── musicstore.graphql
│ └── passwordfile
├── watch-doc.sh
└── workshop.adoc
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 | charset = utf-8
12 | indent_style = space
13 | indent_size = 2
14 |
--------------------------------------------------------------------------------
/.graphqlconfig:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Music Store GraphQL Schema",
3 | "schemaPath": "gateway/src/main/resources/musicstore.graphql",
4 | "extensions": {
5 | "endpoints": {
6 | "Default GraphQL Endpoint": {
7 | "url": "http://localhost:8080/graphql"
8 | }
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | services:
3 | - docker
4 | branches:
5 | only:
6 | - master
7 | cache:
8 | directories:
9 | - $HOME/.m2
10 | env:
11 | global:
12 | - INPUT_FILE=workshop.adoc
13 | - OUTPUT_FILE=index.html
14 | - DEPLOY_LOCAL_DIR=gh-pages
15 | install: true
16 | jobs:
17 | include:
18 | - stage: build
19 | name: "Build - OpenJDK 8"
20 | script:
21 | - mvn -B clean verify
22 | - mvn -B clean verify -Psolution
23 | jdk: openjdk8
24 | - stage: build
25 | name: "Build - OpenJDK 11"
26 | script:
27 | - mvn -B clean verify
28 | - mvn -B clean verify -Psolution
29 | jdk: openjdk11
30 | - stage: deploy
31 | name: "Deploy doc"
32 | if: type != pull_request AND branch = master
33 | script:
34 | - mkdir ${DEPLOY_LOCAL_DIR}
35 | - docker run -u $(id -u):$(id -g) -v ${PWD}:/documents/ -v ${PWD}/${DEPLOY_LOCAL_DIR}:/output/ asciidoctor/docker-asciidoctor asciidoctor -r asciidoctor-diagram /documents/${INPUT_FILE} -D /output -o ${OUTPUT_FILE}
36 | - rm -rf ${PWD}/${DEPLOY_LOCAL_DIR}/.asciidoctor
37 | deploy:
38 | provider: pages
39 | github_token: ${GITHUB_TOKEN}
40 | skip_cleanup: true
41 | local_dir: ${DEPLOY_LOCAL_DIR}
42 | keep_history: true
43 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | = Implementing the API Gateway pattern with GraphQL
2 |
3 | image:https://travis-ci.org/tsegismont/graphql-api-gateway-workshop.svg?branch=master["Build Status", link="https://travis-ci.org/tsegismont/graphql-api-gateway-workshop"]
4 |
5 | Take the workshop online: https://tsegismont.github.io/graphql-api-gateway-workshop/
6 |
--------------------------------------------------------------------------------
/build-doc.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e -x
4 |
5 | INPUT_FILE=workshop.adoc
6 | OUTPUT_DIR="${PWD}/target/workshop-doc"
7 | OUTPUT_FILE=index.html
8 |
9 | mkdir -p "${OUTPUT_DIR}"
10 | docker run -u $(id -u):$(id -g) -v "${PWD}":/documents/ -v "${OUTPUT_DIR}":/output/ asciidoctor/docker-asciidoctor asciidoctor -r asciidoctor-diagram /documents/${INPUT_FILE} -D /output -o ${OUTPUT_FILE}
11 |
--------------------------------------------------------------------------------
/client/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/client/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended'
9 | ],
10 | rules: {
11 | 'no-console': 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
13 | },
14 | parserOptions: {
15 | parser: 'babel-eslint'
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/client/README.md:
--------------------------------------------------------------------------------
1 | # client
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/client/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | };
6 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build && mkdir -p src/main/resources/webroot/ && cp -TR dist/ src/main/resources/webroot/",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@fortawesome/fontawesome-svg-core": "1.2.25",
12 | "@fortawesome/free-regular-svg-icons": "5.11.2",
13 | "@fortawesome/free-solid-svg-icons": "5.11.2",
14 | "@fortawesome/vue-fontawesome": "0.1.7",
15 | "apollo-cache-inmemory": "1.6.3",
16 | "apollo-client": "2.6.4",
17 | "apollo-link-http": "1.5.16",
18 | "bootstrap": "^4.3.1",
19 | "core-js": "^3.1.2",
20 | "graphql": "^14.5.8",
21 | "graphql-tag": "2.10.1",
22 | "jquery": "^3.5.1",
23 | "popper.js": "^1.16.0",
24 | "vue": "^3.0.0",
25 | "vue-router": "^3.0.6"
26 | },
27 | "devDependencies": {
28 | "@vue/cli-plugin-babel": "^5.0.8",
29 | "@vue/cli-plugin-eslint": "^5.0.8",
30 | "@vue/cli-plugin-router": "^5.0.8",
31 | "@vue/cli-service": "^5.0.8",
32 | "babel-eslint": "^10.0.1",
33 | "eslint": "^5.16.0",
34 | "eslint-plugin-vue": "^5.0.0",
35 | "vue-template-compiler": "^2.6.10"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | graphql-api-gateway-workshop
9 | parent
10 | 1.0-SNAPSHOT
11 |
12 |
13 | client
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 |
21 | true
22 |
23 |
24 |
25 | org.apache.maven.plugins
26 | maven-surefire-plugin
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/client/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tsegismont/graphql-api-gateway-workshop/2ace19297d69e21a8044e89acbcecbebf6e0ea23/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Music Store
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/client/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tsegismont/graphql-api-gateway-workshop/2ace19297d69e21a8044e89acbcecbebf6e0ea23/client/src/assets/logo.png
--------------------------------------------------------------------------------
/client/src/components/AlbumCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
{{album.name}}
6 |
7 |
8 |
9 |
Explore
10 |
11 |
12 |
13 |
14 |
25 |
--------------------------------------------------------------------------------
/client/src/components/CartNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ cartTotal }}
6 |
7 |
8 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/client/src/components/GenreCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
{{genre.name}}
6 | Explore
7 |
8 |
9 |
10 |
11 |
19 |
--------------------------------------------------------------------------------
/client/src/components/ReviewCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ review.name }}
8 |
9 |
{{ review.comment }}
10 |
11 |
12 |
13 |
14 |
27 |
--------------------------------------------------------------------------------
/client/src/components/Stars.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{rating}} / 5
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
--------------------------------------------------------------------------------
/client/src/components/TrackList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Tracks
4 |
5 |
6 |
7 | # |
8 | Name |
9 |
10 |
11 |
12 |
13 | {{ track.number }} |
14 | {{ track.name }} |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
29 |
--------------------------------------------------------------------------------
/client/src/main.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap'
2 | import 'bootstrap/dist/css/bootstrap.min.css'
3 | import Vue from 'vue'
4 | import App from './App.vue'
5 | import router from './router'
6 |
7 | import {library} from '@fortawesome/fontawesome-svg-core'
8 | import {faStar as farStar} from '@fortawesome/free-regular-svg-icons'
9 | import {faShoppingCart, faStar as fasStar, faUserCircle} from '@fortawesome/free-solid-svg-icons'
10 | import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
11 |
12 | library.add(faUserCircle, farStar, fasStar, faShoppingCart);
13 |
14 | Vue.component('font-awesome-icon', FontAwesomeIcon);
15 |
16 | Vue.config.productionTip = false;
17 |
18 | new Vue({
19 | router,
20 | render: h => h(App)
21 | }).$mount('#app');
22 |
--------------------------------------------------------------------------------
/client/src/main/resources/webroot/css/app.4d7df893.css:
--------------------------------------------------------------------------------
1 | nav{margin-bottom:2em}div.row{margin-top:2em}div.card{margin:0 2em 2em 0}img.cart-album[data-v-b2f30ea6]{max-width:100px;height:auto}
--------------------------------------------------------------------------------
/client/src/main/resources/webroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tsegismont/graphql-api-gateway-workshop/2ace19297d69e21a8044e89acbcecbebf6e0ea23/client/src/main/resources/webroot/favicon.ico
--------------------------------------------------------------------------------
/client/src/main/resources/webroot/index.html:
--------------------------------------------------------------------------------
1 | Music Store
--------------------------------------------------------------------------------
/client/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import Home from '../views/Home.vue'
4 | import Genre from '../views/Genre.vue'
5 | import Album from '../views/Album.vue'
6 | import Cart from "../views/Cart";
7 |
8 | Vue.use(VueRouter);
9 |
10 | const routes = [
11 | {
12 | path: '/',
13 | name: 'home',
14 | component: Home
15 | },
16 | {
17 | path: '/genre/:id',
18 | name: 'genre',
19 | component: Genre,
20 | },
21 | {
22 | path: '/album/:id',
23 | name: 'album',
24 | component: Album,
25 | }, {
26 | path: '/cart',
27 | name: 'cart',
28 | component: Cart,
29 | }
30 | ];
31 |
32 | const router = new VueRouter({
33 | mode: 'history',
34 | routes: routes
35 | });
36 |
37 | export default router;
38 |
--------------------------------------------------------------------------------
/client/src/shared/apollo-client.js:
--------------------------------------------------------------------------------
1 | import {ApolloClient} from 'apollo-client';
2 | import {createHttpLink} from 'apollo-link-http';
3 | import {InMemoryCache} from 'apollo-cache-inmemory';
4 |
5 | const defaultOptions = {
6 | query: {
7 | fetchPolicy: 'no-cache',
8 | errorPolicy: 'all',
9 | },
10 | };
11 |
12 | const link = createHttpLink({
13 | uri: '/graphql',
14 | credentials: 'same-origin'
15 | });
16 |
17 | const apolloClient = new ApolloClient({
18 | cache: new InMemoryCache(),
19 | link,
20 | defaultOptions,
21 | });
22 |
23 | export default apolloClient;
24 |
--------------------------------------------------------------------------------
/client/src/views/Genre.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Albums
4 |
5 | Loading...
6 |
7 |
8 | {{ error }}
9 |
10 |
18 |
19 |
20 |
21 |
75 |
--------------------------------------------------------------------------------
/client/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
All genres
4 |
5 | Loading...
6 |
7 |
8 | {{ error }}
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
72 |
--------------------------------------------------------------------------------
/client/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | devServer: {
3 | port: 3000,
4 | proxy: {
5 | '^/login.html$': {
6 | target: 'http://localhost:8080',
7 | },
8 | '^/logout$': {
9 | target: 'http://localhost:8080',
10 | },
11 | '^/images/*': {
12 | target: 'http://localhost:8080',
13 | },
14 | '^/graphql$': {
15 | target: 'http://localhost:8080'
16 |
17 | }
18 | }
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | graphql-api-gateway-workshop
9 | parent
10 | 1.0-SNAPSHOT
11 |
12 |
13 | common
14 |
15 |
16 |
17 |
18 | io.vertx
19 | vertx-stack-depchain
20 | ${vertx.version}
21 | pom
22 | import
23 |
24 |
25 |
26 |
27 |
28 |
29 | io.vertx
30 | vertx-rx-java2
31 |
32 |
33 | com.github.akarnokd
34 | rxjava2-jdk8-interop
35 |
36 |
37 | io.vertx
38 | vertx-web-graphql
39 |
40 |
41 | io.vertx
42 | vertx-web-client
43 |
44 |
45 | io.vertx
46 | vertx-pg-client
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/common/src/main/java/workshop/gateway/EnvironmentUtil.java:
--------------------------------------------------------------------------------
1 | package workshop.gateway;
2 |
3 | import graphql.schema.DataFetchingEnvironment;
4 | import io.vertx.core.json.JsonObject;
5 |
6 | import java.util.Map;
7 |
8 | public class EnvironmentUtil {
9 |
10 | public static T getInputArgument(DataFetchingEnvironment env, String name, Class inputType) {
11 | Map argument = env.getArgument(name);
12 | return new JsonObject(argument).mapTo(inputType);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/common/src/main/java/workshop/gateway/NotLoggedInException.java:
--------------------------------------------------------------------------------
1 | package workshop.gateway;
2 |
3 | public class NotLoggedInException extends Exception {
4 |
5 | public NotLoggedInException() {
6 | super("Not logged in", null, false, false);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/common/src/main/java/workshop/gateway/RxDataFetcher.java:
--------------------------------------------------------------------------------
1 | package workshop.gateway;
2 |
3 | import graphql.schema.DataFetcher;
4 | import graphql.schema.DataFetchingEnvironment;
5 | import hu.akarnokd.rxjava2.interop.SingleInterop;
6 | import io.reactivex.Single;
7 |
8 | import java.util.concurrent.CompletionStage;
9 |
10 | public interface RxDataFetcher extends DataFetcher> {
11 |
12 | @Override
13 | default CompletionStage get(DataFetchingEnvironment environment) throws Exception {
14 | Single single = rxGet(environment);
15 | return single==null ? null:single.to(SingleInterop.get());
16 | }
17 |
18 | Single rxGet(DataFetchingEnvironment env) throws Exception;
19 | }
20 |
--------------------------------------------------------------------------------
/common/src/main/java/workshop/model/Album.java:
--------------------------------------------------------------------------------
1 | package workshop.model;
2 |
3 | import java.util.List;
4 |
5 | public class Album {
6 |
7 | private Integer id;
8 | private String name;
9 | private Genre genre;
10 | private String artist;
11 | private String image;
12 | private List