`
16 | display: flex;
17 | min-height: ${({ margin }) =>
18 | typeof margin === "string" ? margin : `${margin}px`};
19 | `;
20 |
21 | function Marginer(props: IMarginerProps) {
22 | const { direction } = props;
23 |
24 | if (direction === "horizontal") return ;
25 | else {
26 | return ;
27 | }
28 | }
29 |
30 | Marginer.defaultProps = {
31 | direction: "horizontal",
32 | };
33 |
34 | export { Marginer };
35 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/navbar/menuStyles.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | bmBurgerButton: {
3 | position: "absolute",
4 | width: "20px",
5 | height: "20px",
6 | right: "20px",
7 | top: "20px",
8 | },
9 | bmBurgerBars: {
10 | background: "#373a47",
11 | },
12 | bmBurgerBarsHover: {
13 | background: "#a90000",
14 | },
15 | bmCrossButton: {
16 | height: "24px",
17 | width: "24px",
18 | },
19 | bmCross: {
20 | background: "#bdc3c7",
21 | },
22 | bmMenuWrap: {
23 | position: "fixed",
24 | width: "60%",
25 | height: "100%",
26 | top: "0px",
27 | },
28 | bmMenu: {
29 | background: "#373a47",
30 | padding: "2.5em 1.5em 0",
31 | fontSize: "1.15em",
32 | },
33 | bmMorphShape: {
34 | fill: "#373a47",
35 | },
36 | bmItemList: {
37 | color: "#b8b7ad",
38 | padding: "0.8em",
39 | },
40 | bmItem: {
41 | display: "inline-block",
42 | },
43 | bmOverlay: {
44 | background: "rgba(0, 0, 0, 0.3)",
45 | },
46 | };
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Full Web App React Nodejs w/ GraphQL Tailwind and Docker From Zero To Deployment | Master MERN STACK
2 |
3 | ## Full Video Course on CoderOne channel
4 | https://youtu.be/4ELH8CT4J0A
5 |
6 | ## About the Video and What you'll Learn
7 | This is a Full Video Course going from Zero to Hero on creating an amazingly looking Reactjs website with Tailwind CSS, styled-components, and Apollo GraphQL alongside its Node.js/Express.js Server Side app or putting together a full dedicated Car Models GraphQL API built on top of Nest.js Framework. The final steps are Dockerizing the whole Stack with MySQL Docker image and using the Nginx Rever proxy to serve the running Nodejs applications on the server. We will take the whole dockerized MERN stack application and Deploy it on a Dedicated VPS from Hostinger and this is all in one video for you to master Web Development with React.js, Apollo GraphQL, Typescript, Tailwind, Responsive Design, Node.js, Express.js, Nest.js, TypeORM, Docker, Docker Compose and VPS.
8 |
9 |
10 | ### Infrastructure model
11 |
12 | 
--------------------------------------------------------------------------------
/react-cars-app/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/containers/HomePage/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 | import { BookCard } from "../../components/bookCard";
5 | import { Footer } from "../../components/footer";
6 | import { Marginer } from "../../components/marginer";
7 | import { Navbar } from "../../components/navbar";
8 | import { AboutUs } from "./aboutUs";
9 | import { BookingSteps } from "./bookingSteps";
10 | import { TopCars } from "./topCars";
11 | import { TopSection } from "./topSection";
12 |
13 | const PageContainer = styled.div`
14 | ${tw`
15 | flex
16 | flex-col
17 | w-full
18 | h-full
19 | items-center
20 | overflow-x-hidden
21 | `}
22 | `;
23 |
24 | export function HomePage() {
25 | return (
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/logo/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 |
5 | import CarLogoImg from "../../../assets/images/car-logo.png";
6 | import CarLogoDarkImg from "../../../assets/images/car-logo-dark.png";
7 |
8 | interface ILogoProps {
9 | color?: "white" | "dark";
10 | bgColor?: "white" | "dark";
11 | }
12 |
13 | const LogoContainer = styled.div`
14 | ${tw`
15 | flex
16 | items-center
17 | `};
18 | `;
19 |
20 | const LogoText = styled.div`
21 | ${tw`
22 | text-xl
23 | md:text-2xl
24 | font-bold
25 | text-black
26 | m-1
27 | `};
28 | ${({ color }: any) => (color === "white" ? tw`text-white` : tw`text-black`)}
29 | ` as any;
30 |
31 | const Image = styled.div`
32 | width: auto;
33 | ${tw`h-6 md:h-9`};
34 |
35 | img {
36 | width: auto;
37 | height: 100%;
38 | }
39 | `;
40 |
41 | export function Logo(props: ILogoProps) {
42 | const { color, bgColor } = props;
43 |
44 | return (
45 |
46 |
47 |
48 |
49 | Yourcar.
50 |
51 | );
52 | }
53 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/button/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 |
5 | interface IButtonProps {
6 | theme?: "filled" | "outlined";
7 | text: string;
8 | className?: string;
9 | }
10 |
11 | const BaseButton = styled.button`
12 | ${tw`
13 | pl-5
14 | pr-5
15 | pt-3
16 | pb-3
17 | outline-none
18 | rounded-md
19 | text-white
20 | text-xs
21 | font-semibold
22 | border-transparent
23 | border-2
24 | border-solid
25 | focus:outline-none
26 | transition-all
27 | duration-200
28 | ease-in-out
29 | m-1
30 | `};
31 | `;
32 |
33 | const OutlinedButton = styled(BaseButton)`
34 | ${tw`
35 | bg-red-500
36 | hover:bg-transparent
37 | hover:text-red-500
38 | hover:border-red-500
39 | `};
40 | `;
41 |
42 | const FilledButton = styled(BaseButton)`
43 | ${tw`
44 | border-red-500
45 | text-red-500
46 | bg-transparent
47 | hover:bg-red-500
48 | hover:text-white
49 | hover:border-transparent
50 | `};
51 | `;
52 |
53 | export function Button(props: IButtonProps) {
54 | const { theme, text, className } = props;
55 |
56 | if (theme === "filled")
57 | return {text};
58 | else return {text};
59 | }
60 |
--------------------------------------------------------------------------------
/react-cars-app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React Redux App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | mysqldb:
5 | image: mysql
6 | environment:
7 | - MYSQL_ROOT_PASSWORD=pass123
8 | - MYSQL_DATABASE=yourcar
9 | ports:
10 | - 3306:3306
11 | command: --default-authentication-plugin=mysql_native_password
12 | networks:
13 | - shared-network
14 | volumes:
15 | - db-config:/etc/mysql
16 | - db-data:/var/lib/mysql
17 | - ./db/backup/files:/data_backup/data
18 |
19 | nginx:
20 | image: nginx:latest
21 | container_name: nginx-prod
22 | volumes:
23 | - ./nginx/nginx.conf:/etc/nginx/nginx.conf
24 | ports:
25 | - 80:80
26 | command: /bin/sh -c "nginx -g 'daemon off;'"
27 | depends_on:
28 | api-prod:
29 | condition: service_healthy
30 | app-prod:
31 | condition: service_started
32 | networks:
33 | - shared-network
34 |
35 | api-prod:
36 | container_name: nestjs_api_prod
37 | image: nestjs-api-prod:1.0.0
38 | build:
39 | context: nestjs-cars-app
40 | target: production
41 | dockerfile: Dockerfile
42 | command: sh -c './bin/wait-for -t 0 mysqldb:3306 -- yarn start:prod'
43 | depends_on:
44 | - mysqldb
45 | networks:
46 | - shared-network
47 | ports:
48 | - 9000:9000
49 | restart: unless-stopped
50 | healthcheck:
51 | test: ["CMD", "curl", "http://api-prod:9000"]
52 | interval: 5s
53 | timeout: 3s
54 | retries: 6
55 |
56 | app-prod:
57 | container_name: react_app_prod
58 | image: react-app-prod:1.0.0
59 | build:
60 | context: react-cars-app
61 | target: production
62 | dockerfile: Dockerfile
63 | command: yarn run start:prod
64 | ports:
65 | - 3000:3000
66 | networks:
67 | - shared-network
68 | restart: unless-stopped
69 |
70 | networks:
71 | shared-network:
72 |
73 | volumes:
74 | db-config:
75 | db-data:
76 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/navbar/navItems.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled, { css } from "styled-components";
3 | import tw from "twin.macro";
4 | import { slide as Menu } from "react-burger-menu";
5 | import { useMediaQuery } from "react-responsive";
6 | import { SCREENS } from "../responsive";
7 | import menuStyles from "./menuStyles";
8 |
9 | const ListContainer = styled.ul`
10 | ${tw`
11 | flex
12 | list-none
13 | `};
14 | `;
15 |
16 | const NavItem = styled.li<{ menu?: any }>`
17 | ${tw`
18 | text-sm
19 | md:text-base
20 | text-black
21 | font-medium
22 | mr-1
23 | md:mr-5
24 | cursor-pointer
25 | transition
26 | duration-300
27 | ease-in-out
28 | hover:text-gray-700
29 | `};
30 |
31 | ${({ menu }) =>
32 | menu &&
33 | css`
34 | ${tw`
35 | text-white
36 | text-xl
37 | mb-3
38 | focus:text-white
39 | `};
40 | `};
41 | `;
42 |
43 | export function NavItems() {
44 | const isMobile = useMediaQuery({ maxWidth: SCREENS.sm });
45 |
46 | if (isMobile)
47 | return (
48 |
64 | );
65 |
66 | return (
67 |
68 |
69 | Home
70 |
71 |
72 | Cars
73 |
74 |
75 | Services
76 |
77 |
78 | Contact Us
79 |
80 |
81 | );
82 | }
83 |
--------------------------------------------------------------------------------
/react-cars-app/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app), using the [Redux](https://redux.js.org/) and [Redux Toolkit](https://redux-toolkit.js.org/) template.
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `yarn start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `yarn test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `yarn build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `yarn eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
--------------------------------------------------------------------------------
/react-cars-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-cars-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@apollo/client": "^3.3.19",
7 | "@brainhubeu/react-carousel": "^2.0.3",
8 | "@craco/craco": "^6.1.2",
9 | "@fortawesome/fontawesome-svg-core": "^1.2.35",
10 | "@fortawesome/free-brands-svg-icons": "^5.15.3",
11 | "@fortawesome/free-solid-svg-icons": "^5.15.3",
12 | "@fortawesome/react-fontawesome": "^0.1.14",
13 | "@reduxjs/toolkit": "^1.5.1",
14 | "@testing-library/jest-dom": "^4.2.4",
15 | "@testing-library/react": "^9.3.2",
16 | "@testing-library/user-event": "^7.1.2",
17 | "@types/jest": "^24.0.0",
18 | "@types/node": "^12.0.0",
19 | "@types/react": "^16.9.0",
20 | "@types/react-dom": "^16.9.0",
21 | "@types/react-redux": "^7.1.7",
22 | "@types/react-responsive": "^8.0.2",
23 | "express": "^4.17.1",
24 | "graphql": "^15.5.0",
25 | "react": "^17.0.2",
26 | "react-burger-menu": "^3.0.6",
27 | "react-calendar": "^3.4.0",
28 | "react-dom": "^17.0.2",
29 | "react-redux": "^7.2.0",
30 | "react-responsive": "^8.2.0",
31 | "react-scripts": "4.0.3",
32 | "react-spinners": "^0.11.0",
33 | "redux-logger": "^3.0.6",
34 | "reselect": "^4.0.0",
35 | "styled-components": "^5.3.0",
36 | "twin.macro": "^2.4.1",
37 | "typescript": "~4.1.5"
38 | },
39 | "scripts": {
40 | "start": "craco start",
41 | "build": "craco build",
42 | "test": "craco test",
43 | "eject": "react-scripts eject",
44 | "schema:download": "npx apollo service:download --endpoint=http://localhost:9000/graphql ./src/app/graphql-schema.json",
45 | "schema:generate-watch": "npx apollo codegen:generate --localSchemaFile=./src/app/graphql-schema.json --target=typescript --tagName=gql --watch",
46 | "start:prod": "node ./server.js"
47 | },
48 | "eslintConfig": {
49 | "extends": "react-app"
50 | },
51 | "browserslist": {
52 | "production": [
53 | ">0.2%",
54 | "not dead",
55 | "not op_mini all"
56 | ],
57 | "development": [
58 | "last 1 chrome version",
59 | "last 1 firefox version",
60 | "last 1 safari version"
61 | ]
62 | },
63 | "devDependencies": {
64 | "@types/react-calendar": "^3.1.6",
65 | "@types/redux-logger": "^3.0.8",
66 | "@types/styled-components": "^5.1.9",
67 | "autoprefixer": "^9",
68 | "postcss": "^7",
69 | "tailwindcss": "npm:@tailwindcss/postcss7-compat"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/nestjs-cars-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nestjs-cars-app",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "cross-env NODE_ENV=production node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^7.6.15",
25 | "@nestjs/config": "^0.6.3",
26 | "@nestjs/core": "^7.6.15",
27 | "@nestjs/graphql": "^7.10.6",
28 | "@nestjs/platform-express": "^7.6.15",
29 | "@nestjs/typeorm": "^7.1.5",
30 | "apollo-server-express": "^2.24.1",
31 | "class-transformer": "^0.4.0",
32 | "class-validator": "^0.13.1",
33 | "cross-env": "^7.0.3",
34 | "graphql": "^15.5.0",
35 | "graphql-tools": "^7.0.5",
36 | "mysql2": "^2.2.5",
37 | "reflect-metadata": "^0.1.13",
38 | "rimraf": "^3.0.2",
39 | "rxjs": "^6.6.6",
40 | "typeorm": "^0.2.32"
41 | },
42 | "devDependencies": {
43 | "@nestjs/cli": "^7.6.0",
44 | "@nestjs/schematics": "^7.3.0",
45 | "@nestjs/testing": "^7.6.15",
46 | "@types/express": "^4.17.11",
47 | "@types/jest": "^26.0.22",
48 | "@types/node": "^14.14.36",
49 | "@types/supertest": "^2.0.10",
50 | "@typescript-eslint/eslint-plugin": "^4.19.0",
51 | "@typescript-eslint/parser": "^4.19.0",
52 | "eslint": "^7.22.0",
53 | "eslint-config-prettier": "^8.1.0",
54 | "eslint-plugin-prettier": "^3.3.1",
55 | "jest": "^26.6.3",
56 | "prettier": "^2.2.1",
57 | "supertest": "^6.1.3",
58 | "ts-jest": "^26.5.4",
59 | "ts-loader": "^8.0.18",
60 | "ts-node": "^9.1.1",
61 | "tsconfig-paths": "^3.9.0",
62 | "typescript": "^4.2.3"
63 | },
64 | "jest": {
65 | "moduleFileExtensions": [
66 | "js",
67 | "json",
68 | "ts"
69 | ],
70 | "rootDir": "src",
71 | "testRegex": ".*\\.spec\\.ts$",
72 | "transform": {
73 | "^.+\\.(t|j)s$": "ts-jest"
74 | },
75 | "collectCoverageFrom": [
76 | "**/*.(t|j)s"
77 | ],
78 | "coverageDirectory": "../coverage",
79 | "testEnvironment": "node"
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/containers/HomePage/aboutUs.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 | import { SCREENS } from "../../components/responsive";
5 |
6 | import JeepImg from "../../../assets/images/jeep.png";
7 |
8 | const AboutUsContainer = styled.div`
9 | ${tw`
10 | w-full
11 | flex
12 | flex-wrap
13 | items-center
14 | justify-center
15 | pt-4
16 | pb-4
17 | pr-7
18 | pl-7
19 | md:pl-0
20 | md:pr-0
21 | bg-white
22 | `};
23 | `;
24 |
25 | const CarContainer = styled.div`
26 | width: auto;
27 | height: 15em;
28 | margin-left: -50px;
29 |
30 | img {
31 | width: auto;
32 | height: 100%;
33 | }
34 |
35 | @media (min-width: ${SCREENS.md}) {
36 | height: 28em;
37 | }
38 |
39 | @media (min-width: ${SCREENS.lg}) {
40 | height: 30em;
41 | }
42 |
43 | @media (min-width: ${SCREENS["2xl"]}) {
44 | height: 35em;
45 | margin-left: 0;
46 | }
47 | `;
48 |
49 | const InfoContainer = styled.div`
50 | ${tw`
51 | md:w-1/2
52 | flex
53 | flex-col
54 | md:ml-6
55 | 2xl:ml-16
56 | `};
57 | `;
58 |
59 | const Title = styled.h1`
60 | ${tw`
61 | text-black
62 | text-2xl
63 | md:text-5xl
64 | font-extrabold
65 | md:font-black
66 | md:leading-normal
67 | `};
68 | `;
69 |
70 | const InfoText = styled.p`
71 | ${tw`
72 | md:max-w-2xl
73 | text-sm
74 | md:text-base
75 | text-gray-500
76 | font-normal
77 | mt-4
78 | `};
79 | `;
80 |
81 | export function AboutUs() {
82 | return (
83 |
84 |
85 |
86 |
87 |
88 | Feel The Best Experience With Our Rental Deals
89 |
90 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
91 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
92 | minim veniam, quis nostrud exercitation ullamco laboris nisi ut
93 | aliquip ex ea commodo consequat. Duis aute irure dolor in
94 | reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
95 | pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
96 | culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum
97 | dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
98 | culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum
99 | dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
100 |
101 |
102 |
103 | );
104 | }
105 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/containers/HomePage/bookingSteps.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | faCalendarAlt,
3 | faCarSide,
4 | faMapMarkedAlt,
5 | } from "@fortawesome/free-solid-svg-icons";
6 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7 | import React from "react";
8 | import styled from "styled-components";
9 | import tw from "twin.macro";
10 |
11 | const Container = styled.div`
12 | ${tw`
13 | w-full
14 | flex
15 | flex-col
16 | items-center
17 | pt-3
18 | pb-3
19 | lg:pt-6
20 | lg:pb-6
21 | `};
22 | `;
23 |
24 | const Title = styled.h2`
25 | ${tw`
26 | text-3xl
27 | lg:text-5xl
28 | text-black
29 | font-extrabold
30 | `};
31 | `;
32 |
33 | const StepsContainer = styled.div`
34 | ${tw`
35 | flex
36 | justify-evenly
37 | flex-wrap
38 | mt-7
39 | lg:mt-16
40 | `};
41 | `;
42 |
43 | const StepContainer = styled.div`
44 | ${tw`
45 | flex
46 | flex-col
47 | md:w-96
48 | items-center
49 | transition-colors
50 | hover:text-red-500
51 | m-3
52 | `};
53 | `;
54 |
55 | const Step = styled.div`
56 | box-shadow: 0 1.3px 12px -3px rgba(0, 0, 0, 0.4);
57 | ${tw`
58 | flex
59 | rounded-lg
60 | items-center
61 | justify-center
62 | p-6
63 | `};
64 | `;
65 |
66 | const StepTitle = styled.h4`
67 | ${tw`
68 | text-black
69 | text-lg
70 | font-semibold
71 | mt-4
72 | `};
73 | `;
74 |
75 | const StepDescription = styled.p`
76 | ${tw`
77 | w-10/12
78 | text-xs
79 | md:text-sm
80 | text-center
81 | text-gray-600
82 | `};
83 | `;
84 |
85 | const StepIcon = styled.span`
86 | ${tw`
87 | text-red-500
88 | text-3xl
89 | `};
90 | `;
91 |
92 | export function BookingSteps() {
93 | return (
94 |
95 | Our Working Steps
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Choose Location
104 |
105 | Find the nearest Yourcar point and book your car.
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Pick-Up Date
115 |
116 | Pickup the Best Date to rent a car for you.
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Book Your Car
126 |
127 | Book your nice car with ease in one single click
128 |
129 |
130 |
131 |
132 | );
133 | }
134 |
--------------------------------------------------------------------------------
/nestjs-cars-app/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/car/index.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | faEllipsisH,
3 | faFillDrip,
4 | faTachometerAlt,
5 | } from "@fortawesome/free-solid-svg-icons";
6 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7 | import React from "react";
8 | import styled from "styled-components";
9 | import tw from "twin.macro";
10 | import { ICar } from "../../../typings/car";
11 | import { Button } from "../button";
12 |
13 | interface ICarProps extends ICar {}
14 |
15 | const CarContainer = styled.div`
16 | width: 16.5em;
17 | min-height: 23em;
18 | max-height: 23em;
19 | box-shadow: 0 1.3px 17px -2px rgba(0, 0, 0, 0.4);
20 | ${tw`
21 | flex
22 | flex-col
23 | items-center
24 | p-3
25 | pb-4
26 | bg-white
27 | rounded-md
28 | m-1
29 | sm:m-3
30 | md:m-6
31 | `};
32 | `;
33 |
34 | const CarThumbnail = styled.div`
35 | width: 100%;
36 | height: auto;
37 |
38 | img {
39 | width: 100%;
40 | height: 100%;
41 | }
42 | `;
43 |
44 | const CarName = styled.h3`
45 | ${tw`
46 | text-base
47 | font-bold
48 | text-black
49 | mt-1
50 | mb-1
51 | `};
52 | `;
53 |
54 | const PricesContainer = styled.div`
55 | ${tw`
56 | w-full
57 | flex
58 | justify-start
59 | mt-3
60 | `};
61 | `;
62 |
63 | const SmallText = styled.p`
64 | color: inherit;
65 | ${tw`
66 | inline-flex
67 | text-xs
68 | font-thin
69 | `};
70 | `;
71 |
72 | const DailyPrice = styled.h5`
73 | ${tw`
74 | text-red-500
75 | font-bold
76 | text-sm
77 | mr-3
78 | `};
79 | `;
80 |
81 | const MonthlyPrice = styled.h5`
82 | ${tw`
83 | text-gray-500
84 | font-bold
85 | text-sm
86 | `};
87 | `;
88 |
89 | const SmallIcon = styled.span`
90 | ${tw`
91 | text-gray-400
92 | text-sm
93 | mr-1
94 | `};
95 | `;
96 |
97 | const CarDetailsContainer = styled.div`
98 | ${tw`
99 | flex
100 | w-full
101 | justify-between
102 | `};
103 | `;
104 |
105 | const CarDetail = styled.span`
106 | ${tw`
107 | flex
108 | items-center
109 | `};
110 | `;
111 |
112 | const CarInfo = styled.h6`
113 | ${tw`
114 | text-gray-400
115 | text-xs
116 | `};
117 | `;
118 |
119 | const Seperator = styled.div`
120 | min-width: 100%;
121 | min-height: 1px;
122 | ${tw`
123 | flex
124 | bg-gray-300
125 | mt-2
126 | mb-2
127 | `};
128 | `;
129 |
130 | const RentButton = styled(Button)`
131 | ${tw`
132 | min-w-full
133 | mt-5
134 | `};
135 | `;
136 |
137 | export function Car(props: ICarProps) {
138 | const {
139 | name,
140 | thumbnailSrc,
141 | dailyPrice,
142 | monthlyPrice,
143 | mileage,
144 | gearType,
145 | gas,
146 | } = props;
147 |
148 | return (
149 |
150 |
151 |
152 |
153 | {name}
154 |
155 |
156 | ${dailyPrice}
157 | /Day
158 |
159 |
160 | ${monthlyPrice}
161 | /Month
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | {mileage}
171 |
172 |
173 |
174 |
175 |
176 | {gearType}
177 |
178 |
179 |
180 |
181 |
182 | {gas}
183 |
184 |
185 |
186 |
187 | );
188 | }
189 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/containers/HomePage/topSection.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 |
5 | import MclarenCarImg from "../../../assets/images/mclaren-orange-big.png";
6 | import BlobImg from "../../../assets/images/blob.svg";
7 | import { SCREENS } from "../../components/responsive";
8 | import { Button } from "../../components/button";
9 |
10 | const TopSectionContainer = styled.div`
11 | min-height: 400px;
12 | margin-top: 6em;
13 | ${tw`
14 | w-full
15 | max-w-screen-2xl
16 | flex
17 | justify-between
18 | pl-3
19 | pr-3
20 | lg:pl-12
21 | lg:pr-12
22 | `};
23 | `;
24 |
25 | const LeftContainer = styled.div`
26 | ${tw`
27 | w-1/2
28 | flex
29 | flex-col
30 | `};
31 | `;
32 |
33 | const RightContainer = styled.div`
34 | ${tw`
35 | w-1/2
36 | flex
37 | flex-col
38 | relative
39 | mt-20
40 | `};
41 | `;
42 |
43 | const Slogan = styled.h1`
44 | ${tw`
45 | font-bold
46 | text-2xl
47 | xl:text-6xl
48 | sm:text-3xl
49 | md:text-5xl
50 | lg:font-black
51 | md:font-extrabold
52 | text-black
53 | mb-4
54 | sm:leading-snug
55 | lg:leading-normal
56 | xl:leading-relaxed
57 | `};
58 | `;
59 |
60 | const Description = styled.p`
61 | ${tw`
62 | text-xs
63 | lg:text-sm
64 | xl:text-lg
65 | sm:max-h-full
66 | overflow-hidden
67 | max-h-12
68 | text-gray-800
69 | `};
70 | `;
71 |
72 | const BlobContainer = styled.div`
73 | width: 20em;
74 | height: 10em;
75 | position: absolute;
76 | right: -5em;
77 | top: -9em;
78 | z-index: -1;
79 | transform: rotate(-30deg);
80 |
81 | img {
82 | width: 100%;
83 | height: auto;
84 | max-height: max-content;
85 | }
86 |
87 | @media (min-width: ${SCREENS.sm}) {
88 | width: 40em;
89 | max-height: 10em;
90 | right: -9em;
91 | top: -16em;
92 | transform: rotate(-25deg);
93 | }
94 |
95 | @media (min-width: ${SCREENS.lg}) {
96 | width: 50em;
97 | max-height: 30em;
98 | right: -7em;
99 | top: -15em;
100 | transform: rotate(-30deg);
101 | }
102 |
103 | @media (min-width: ${SCREENS.xl}) {
104 | width: 70em;
105 | max-height: 30em;
106 | right: -15em;
107 | top: -25em;
108 | transform: rotate(-20deg);
109 | }
110 | `;
111 |
112 | const StandaloneCar = styled.div`
113 | width: auto;
114 | height: 10em;
115 | right: -6em;
116 | top: -5em;
117 | position: absolute;
118 |
119 | img {
120 | width: auto;
121 | height: 100%;
122 | max-width: fit-content;
123 | }
124 |
125 | @media (min-width: ${SCREENS.sm}) {
126 | height: 16em;
127 | right: -6em;
128 | top: -6em;
129 | }
130 |
131 | @media (min-width: ${SCREENS.lg}) {
132 | height: 21em;
133 | right: -8em;
134 | top: -5em;
135 | }
136 |
137 | @media (min-width: ${SCREENS.xl}) {
138 | height: 30em;
139 | right: -13em;
140 | top: -9em;
141 | }
142 | `;
143 |
144 | const ButtonsContainer = styled.div`
145 | ${tw`
146 | flex
147 | flex-wrap
148 | mt-4
149 | `};
150 | `;
151 |
152 | export function TopSection() {
153 | return (
154 |
155 |
156 | Rent The Best Qulity Car's With Us
157 |
158 | Always choose the best car from our local stores or order it remotely
159 | at the best price for you and get the best quality cars for as long as
160 | you like
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | );
177 | }
178 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/bookCard/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | faCalendarAlt,
4 | faCaretDown,
5 | faCaretUp,
6 | } from "@fortawesome/free-solid-svg-icons";
7 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
8 | import styled, { css } from "styled-components";
9 | import tw from "twin.macro";
10 | import { Button } from "../button";
11 | import { Marginer } from "../marginer";
12 |
13 | import Calendar from "react-calendar";
14 | import "react-calendar/dist/Calendar.css";
15 | import { SCREENS } from "../responsive";
16 |
17 | const CardContainer = styled.div`
18 | min-height: 4.3em;
19 | box-shadow: 0 1.3px 12px -3px rgba(0, 0, 0, 0.4);
20 | ${tw`
21 | flex
22 | justify-center
23 | items-center
24 | rounded-md
25 | bg-white
26 | pt-1
27 | pb-1
28 | pr-2
29 | pl-2
30 | md:pt-2
31 | md:pb-2
32 | md:pl-9
33 | md:pr-9
34 | `};
35 | `;
36 |
37 | const ItemContainer = styled.div`
38 | ${tw`flex relative`};
39 | `;
40 |
41 | const Icon = styled.span`
42 | ${tw`
43 | text-red-500
44 | fill-current
45 | text-xs
46 | md:text-base
47 | mr-1
48 | md:mr-3
49 | `};
50 | `;
51 |
52 | const SmallIcon = styled.span`
53 | ${tw`
54 | text-gray-500
55 | fill-current
56 | text-xs
57 | md:text-base
58 | ml-1
59 | `};
60 | `;
61 |
62 | const Name = styled.span`
63 | ${tw`
64 | text-gray-600
65 | text-xs
66 | md:text-sm
67 | cursor-pointer
68 | select-none
69 | `};
70 | `;
71 |
72 | const LineSeperator = styled.span`
73 | width: 2px;
74 | height: 45%;
75 | ${tw`
76 | bg-gray-300
77 | mr-2
78 | ml-2
79 | md:mr-5
80 | md:ml-5
81 | `};
82 | `;
83 |
84 | const DateCalendar = styled(Calendar)`
85 | position: absolute;
86 | max-width: none;
87 | user-select: none;
88 | top: 2em;
89 | left: 0;
90 |
91 | ${({ offset }: any) =>
92 | offset &&
93 | css`
94 | left: -6em;
95 | `};
96 |
97 | @media (min-width: ${SCREENS.md}) {
98 | top: 3.5em;
99 | left: -2em;
100 | }
101 | ` as any;
102 |
103 | export function BookCard() {
104 | const [startDate, setStartDate] = useState(new Date());
105 | const [isStartCalendarOpen, setStartCalendarOpen] = useState(false);
106 | const [returnDate, setReturnDate] = useState(new Date());
107 | const [isReturnCalendarOpen, setReturnCalendarOpen] = useState(false);
108 |
109 | const toggleStartDateCalendar = () => {
110 | setStartCalendarOpen(!isStartCalendarOpen);
111 | if (isReturnCalendarOpen) setReturnCalendarOpen(false);
112 | };
113 |
114 | const toggleReturnDateCalendar = () => {
115 | setReturnCalendarOpen(!isReturnCalendarOpen);
116 | if (isStartCalendarOpen) setStartCalendarOpen(false);
117 | };
118 |
119 | return (
120 |
121 |
122 |
123 |
124 |
125 | Pick Up Date
126 |
127 |
130 |
131 | {isStartCalendarOpen && (
132 |
133 | )}
134 |
135 |
136 |
137 |
138 |
139 |
140 | Return Date
141 |
142 |
145 |
146 | {isReturnCalendarOpen && (
147 |
152 | )}
153 |
154 |
155 |
156 |
157 | );
158 | }
159 |
--------------------------------------------------------------------------------
/nestjs-cars-app/bin/wait-for:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2017 Eficode Oy
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 | set -- "$@" -- "$TIMEOUT" "$QUIET" "$PROTOCOL" "$HOST" "$PORT" "$result"
26 | TIMEOUT=15
27 | QUIET=0
28 | # The protocol to make the request with, either "tcp" or "http"
29 | PROTOCOL="tcp"
30 |
31 | echoerr() {
32 | if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
33 | }
34 |
35 | usage() {
36 | exitcode="$1"
37 | cat << USAGE >&2
38 | Usage:
39 | $0 host:port|url [-t timeout] [-- command args]
40 | -q | --quiet Do not output any status messages
41 | -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
42 | -- COMMAND ARGS Execute command with args after the test finishes
43 | USAGE
44 | exit "$exitcode"
45 | }
46 |
47 | wait_for() {
48 | case "$PROTOCOL" in
49 | tcp)
50 | if ! command -v nc >/dev/null; then
51 | echoerr 'nc command is missing!'
52 | exit 1
53 | fi
54 | ;;
55 | wget)
56 | if ! command -v wget >/dev/null; then
57 | echoerr 'nc command is missing!'
58 | exit 1
59 | fi
60 | ;;
61 | esac
62 |
63 | while :; do
64 | case "$PROTOCOL" in
65 | tcp)
66 | nc -w 1 -z "$HOST" "$PORT" > /dev/null 2>&1
67 | ;;
68 | http)
69 | wget --timeout=1 -q "$HOST" -O /dev/null > /dev/null 2>&1
70 | ;;
71 | *)
72 | echoerr "Unknown protocol '$PROTOCOL'"
73 | exit 1
74 | ;;
75 | esac
76 |
77 | result=$?
78 |
79 | if [ $result -eq 0 ] ; then
80 | if [ $# -gt 7 ] ; then
81 | for result in $(seq $(($# - 7))); do
82 | result=$1
83 | shift
84 | set -- "$@" "$result"
85 | done
86 |
87 | TIMEOUT=$2 QUIET=$3 PROTOCOL=$4 HOST=$5 PORT=$6 result=$7
88 | shift 7
89 | exec "$@"
90 | fi
91 | exit 0
92 | fi
93 |
94 | if [ "$TIMEOUT" -le 0 ]; then
95 | break
96 | fi
97 | TIMEOUT=$((TIMEOUT - 1))
98 |
99 | sleep 1
100 | done
101 | echo "Operation timed out" >&2
102 | exit 1
103 | }
104 |
105 | while :; do
106 | case "$1" in
107 | http://*|https://*)
108 | HOST="$1"
109 | PROTOCOL="http"
110 | shift 1
111 | ;;
112 | *:* )
113 | HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
114 | PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
115 | shift 1
116 | ;;
117 | -q | --quiet)
118 | QUIET=1
119 | shift 1
120 | ;;
121 | -q-*)
122 | QUIET=0
123 | echoerr "Unknown option: $1"
124 | usage 1
125 | ;;
126 | -q*)
127 | QUIET=1
128 | result=$1
129 | shift 1
130 | set -- -"${result#-q}" "$@"
131 | ;;
132 | -t | --timeout)
133 | TIMEOUT="$2"
134 | shift 2
135 | ;;
136 | -t*)
137 | TIMEOUT="${1#-t}"
138 | shift 1
139 | ;;
140 | --timeout=*)
141 | TIMEOUT="${1#*=}"
142 | shift 1
143 | ;;
144 | --)
145 | shift
146 | break
147 | ;;
148 | --help)
149 | usage 0
150 | ;;
151 | -*)
152 | QUIET=0
153 | echoerr "Unknown option: $1"
154 | usage 1
155 | ;;
156 | *)
157 | QUIET=0
158 | echoerr "Unknown argument: $1"
159 | usage 1
160 | ;;
161 | esac
162 | done
163 |
164 | if ! [ "$TIMEOUT" -ge 0 ] 2>/dev/null; then
165 | echoerr "Error: invalid timeout '$TIMEOUT'"
166 | usage 3
167 | fi
168 |
169 | case "$PROTOCOL" in
170 | tcp)
171 | if [ "$HOST" = "" ] || [ "$PORT" = "" ]; then
172 | echoerr "Error: you need to provide a host and port to test."
173 | usage 2
174 | fi
175 | ;;
176 | http)
177 | if [ "$HOST" = "" ]; then
178 | echoerr "Error: you need to provide a host to test."
179 | usage 2
180 | fi
181 | ;;
182 | esac
183 |
184 | wait_for "$@"
185 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/components/footer/index.tsx:
--------------------------------------------------------------------------------
1 | import { faEnvelope, faPhoneAlt } from "@fortawesome/free-solid-svg-icons";
2 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3 | import React from "react";
4 | import styled from "styled-components";
5 | import tw from "twin.macro";
6 | import { Logo } from "../logo";
7 |
8 | const FooterContainer = styled.div`
9 | //min-height: 24em;
10 | background-color: #1d2124;
11 | ${tw`
12 | flex
13 | flex-col
14 | min-w-full
15 | pt-10
16 | md:pt-16
17 | items-center
18 | justify-center
19 | `};
20 | `;
21 |
22 | const InnerContainer = styled.div`
23 | ${tw`
24 | flex
25 | w-full
26 | h-full
27 | max-w-screen-2xl
28 | flex-wrap
29 | `};
30 | `;
31 |
32 | const BottomContainer = styled.div`
33 | ${tw`
34 | w-full
35 | flex
36 | max-w-screen-2xl
37 | justify-center
38 | md:justify-start
39 | mt-7
40 | md:mt-1
41 | `};
42 | `;
43 |
44 | const CopyrightText = styled.small`
45 | font-size: 12px;
46 | ${tw`
47 | text-gray-300
48 | `}
49 | `;
50 |
51 | const AboutContainer = styled.div`
52 | ${tw`
53 | flex
54 | flex-col
55 | mr-2
56 | md:mr-16
57 | pl-10
58 | pr-10
59 | md:pl-3
60 | md:pr-3
61 | `};
62 | `;
63 |
64 | const AboutText = styled.p`
65 | ${tw`
66 | text-white
67 | text-sm
68 | font-normal
69 | max-w-xs
70 | leading-5
71 | mt-2
72 | `};
73 | `;
74 |
75 | const SectionContainer = styled.div`
76 | ${tw`
77 | w-full
78 | md:w-auto
79 | flex
80 | flex-col
81 | mr-2
82 | md:mr-16
83 | pl-10
84 | pr-10
85 | md:pl-3
86 | md:pr-3
87 | mt-7
88 | md:mt-0
89 | `};
90 | `;
91 |
92 | const LinksList = styled.ul`
93 | ${tw`
94 | outline-none
95 | list-none
96 | flex
97 | flex-col
98 | `};
99 | `;
100 |
101 | const ListItem = styled.li`
102 | ${tw`
103 | mb-3
104 | `};
105 |
106 | & > a {
107 | ${tw`
108 | text-sm
109 | text-white
110 | transition-all
111 | hover:text-gray-200
112 | `};
113 | }
114 | `;
115 |
116 | const HeaderTitle = styled.h3`
117 | ${tw`
118 | text-2xl
119 | font-bold
120 | text-white
121 | mb-3
122 | `};
123 | `;
124 |
125 | const HorizontalContainer = styled.div`
126 | ${tw`
127 | flex
128 | items-center
129 | `};
130 | `;
131 |
132 | const RedIcon = styled.span`
133 | ${tw`
134 | w-9
135 | h-9
136 | rounded-full
137 | bg-red-500
138 | flex
139 | items-center
140 | justify-center
141 | text-white
142 | text-base
143 | mr-2
144 | `};
145 | `;
146 |
147 | const SmallText = styled.h6`
148 | ${tw`
149 | text-sm
150 | text-white
151 | `};
152 | `;
153 |
154 | export function Footer() {
155 | return (
156 |
157 |
158 |
159 |
160 |
161 | Yourcar is a Car renting and selling company located in many
162 | countries across the world which has high quality cars and top rated
163 | service.
164 |
165 |
166 |
167 | Our Links
168 |
169 |
170 | Home
171 |
172 |
173 | About Us
174 |
175 |
176 | Services
177 |
178 |
179 | Models
180 |
181 |
182 | Blog
183 |
184 |
185 |
186 |
187 | Other Links
188 |
189 |
190 | FAQ
191 |
192 |
193 | Contact Us
194 |
195 |
196 | Support
197 |
198 |
199 | Privacy Policy
200 |
201 |
202 | Terms & Conditions
203 |
204 |
205 |
206 |
207 | Call Now
208 |
209 |
210 |
211 |
212 | +91 555-234-8469
213 |
214 |
215 |
216 | Mail
217 |
218 |
219 |
220 |
221 | info@yourcar.com
222 |
223 |
224 |
225 |
226 |
227 | Copyright © {new Date().getFullYear()} Yourcar. All rights
228 | reserved.
229 |
230 |
231 |
232 | );
233 | }
234 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/containers/HomePage/topCars.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import styled from "styled-components";
3 | import tw from "twin.macro";
4 | import { ICar } from "../../../typings/car";
5 | import { Car } from "../../components/car";
6 | import Carousel, { Dots, slidesToShowPlugin } from "@brainhubeu/react-carousel";
7 | import "@brainhubeu/react-carousel/lib/style.css";
8 | import { useMediaQuery } from "react-responsive";
9 | import { SCREENS } from "../../components/responsive";
10 | import carService from "../../services/carService";
11 | import { Dispatch } from "redux";
12 | import { GetCars_cars } from "../../services/carService/__generated__/GetCars";
13 | import { setTopCars } from "./slice";
14 | import { useDispatch, useSelector } from "react-redux";
15 | import { createSelector } from "reselect";
16 | import { makeSelectTopCars } from "./selectors";
17 | import MoonLoader from "react-spinners/MoonLoader";
18 |
19 | const TopCarsContainer = styled.div`
20 | ${tw`
21 | max-w-screen-lg
22 | w-full
23 | flex
24 | flex-col
25 | items-center
26 | justify-center
27 | pr-4
28 | pl-4
29 | md:pl-0
30 | md:pr-0
31 | mb-10
32 | `};
33 | `;
34 |
35 | const Title = styled.h2`
36 | ${tw`
37 | text-3xl
38 | lg:text-5xl
39 | text-black
40 | font-extrabold
41 | `};
42 | `;
43 |
44 | const CarsContainer = styled.div`
45 | ${tw`
46 | w-full
47 | flex
48 | flex-wrap
49 | justify-center
50 | mt-7
51 | md:mt-10
52 | `};
53 | `;
54 |
55 | const EmptyCars = styled.div`
56 | ${tw`
57 | w-full
58 | flex
59 | justify-center
60 | items-center
61 | text-sm
62 | text-gray-500
63 | `};
64 | `;
65 |
66 | const LoadingContainer = styled.div`
67 | ${tw`
68 | w-full
69 | mt-9
70 | flex
71 | justify-center
72 | items-center
73 | text-base
74 | text-black
75 | `};
76 | `;
77 |
78 | const actionDispatch = (dispatch: Dispatch) => ({
79 | setTopCars: (cars: GetCars_cars[]) => dispatch(setTopCars(cars)),
80 | });
81 |
82 | const stateSelector = createSelector(makeSelectTopCars, (topCars) => ({
83 | topCars,
84 | }));
85 |
86 | const wait = (timeout: number) => new Promise((rs) => setTimeout(rs, timeout));
87 |
88 | export function TopCars() {
89 | const [current, setCurrent] = useState(0);
90 | const [isLoading, setLoading] = useState(false);
91 |
92 | const isMobile = useMediaQuery({ maxWidth: SCREENS.sm });
93 |
94 | const { topCars } = useSelector(stateSelector);
95 | const { setTopCars } = actionDispatch(useDispatch());
96 |
97 | console.log("Cars", topCars);
98 |
99 | const fetchTopCars = async () => {
100 | setLoading(true);
101 | const cars = await carService.getCars().catch((err) => {
102 | console.log("Error: ", err);
103 | });
104 |
105 | console.log("Cars: ", cars);
106 | if (cars) setTopCars(cars);
107 | setLoading(false);
108 | };
109 |
110 | const testCar: ICar = {
111 | name: "Audi S3 Car",
112 | mileage: "10k",
113 | thumbnailSrc:
114 | "https://cdn.jdpower.com/Models/640x480/2017-Audi-S3-PremiumPlus.jpg",
115 | dailyPrice: 70,
116 | monthlyPrice: 1600,
117 | gearType: "Auto",
118 | gas: "Petrol",
119 | };
120 |
121 | const testCar2: ICar = {
122 | name: "HONDA cITY 5 Seater Car",
123 | mileage: "20k",
124 | thumbnailSrc:
125 | "https://shinewiki.com/wp-content/uploads/2019/11/honda-city.jpg",
126 | dailyPrice: 50,
127 | monthlyPrice: 1500,
128 | gearType: "Auto",
129 | gas: "Petrol",
130 | };
131 |
132 | useEffect(() => {
133 | fetchTopCars();
134 | }, []);
135 |
136 | const isEmptyTopCars = !topCars || topCars.length === 0;
137 |
138 | const cars =
139 | (!isEmptyTopCars &&
140 | topCars.map((car) => )) ||
141 | [];
142 |
143 | const numberOfDots = isMobile ? cars.length : Math.ceil(cars.length / 3);
144 |
145 | return (
146 |
147 | Explore Our Top Deals
148 | {isLoading && (
149 |
150 |
151 |
152 | )}
153 | {isEmptyTopCars && !isLoading && No Cars To Show!}
154 | {!isEmptyTopCars && !isLoading && (
155 |
156 |
192 |
193 |
194 | )}
195 |
196 | );
197 | }
198 |
--------------------------------------------------------------------------------
/react-cars-app/src/serviceWorker.ts:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.0/8 are considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | type Config = {
24 | onSuccess?: (registration: ServiceWorkerRegistration) => void;
25 | onUpdate?: (registration: ServiceWorkerRegistration) => void;
26 | };
27 |
28 | export function register(config?: Config) {
29 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
30 | // The URL constructor is available in all browsers that support SW.
31 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
32 | if (publicUrl.origin !== window.location.origin) {
33 | // Our service worker won't work if PUBLIC_URL is on a different origin
34 | // from what our page is served on. This might happen if a CDN is used to
35 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
36 | return;
37 | }
38 |
39 | window.addEventListener('load', () => {
40 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
41 |
42 | if (isLocalhost) {
43 | // This is running on localhost. Let's check if a service worker still exists or not.
44 | checkValidServiceWorker(swUrl, config);
45 |
46 | // Add some additional logging to localhost, pointing developers to the
47 | // service worker/PWA documentation.
48 | navigator.serviceWorker.ready.then(() => {
49 | console.log(
50 | 'This web app is being served cache-first by a service ' +
51 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
52 | );
53 | });
54 | } else {
55 | // Is not localhost. Just register service worker
56 | registerValidSW(swUrl, config);
57 | }
58 | });
59 | }
60 | }
61 |
62 | function registerValidSW(swUrl: string, config?: Config) {
63 | navigator.serviceWorker
64 | .register(swUrl)
65 | .then((registration) => {
66 | registration.onupdatefound = () => {
67 | const installingWorker = registration.installing;
68 | if (installingWorker == null) {
69 | return;
70 | }
71 | installingWorker.onstatechange = () => {
72 | if (installingWorker.state === 'installed') {
73 | if (navigator.serviceWorker.controller) {
74 | // At this point, the updated precached content has been fetched,
75 | // but the previous service worker will still serve the older
76 | // content until all client tabs are closed.
77 | console.log(
78 | 'New content is available and will be used when all ' +
79 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
80 | );
81 |
82 | // Execute callback
83 | if (config && config.onUpdate) {
84 | config.onUpdate(registration);
85 | }
86 | } else {
87 | // At this point, everything has been precached.
88 | // It's the perfect time to display a
89 | // "Content is cached for offline use." message.
90 | console.log('Content is cached for offline use.');
91 |
92 | // Execute callback
93 | if (config && config.onSuccess) {
94 | config.onSuccess(registration);
95 | }
96 | }
97 | }
98 | };
99 | };
100 | })
101 | .catch((error) => {
102 | console.error('Error during service worker registration:', error);
103 | });
104 | }
105 |
106 | function checkValidServiceWorker(swUrl: string, config?: Config) {
107 | // Check if the service worker can be found. If it can't reload the page.
108 | fetch(swUrl, {
109 | headers: { 'Service-Worker': 'script' },
110 | })
111 | .then((response) => {
112 | // Ensure service worker exists, and that we really are getting a JS file.
113 | const contentType = response.headers.get('content-type');
114 | if (
115 | response.status === 404 ||
116 | (contentType != null && contentType.indexOf('javascript') === -1)
117 | ) {
118 | // No service worker found. Probably a different app. Reload the page.
119 | navigator.serviceWorker.ready.then((registration) => {
120 | registration.unregister().then(() => {
121 | window.location.reload();
122 | });
123 | });
124 | } else {
125 | // Service worker found. Proceed as normal.
126 | registerValidSW(swUrl, config);
127 | }
128 | })
129 | .catch(() => {
130 | console.log(
131 | 'No internet connection found. App is running in offline mode.'
132 | );
133 | });
134 | }
135 |
136 | export function unregister() {
137 | if ('serviceWorker' in navigator) {
138 | navigator.serviceWorker.ready
139 | .then((registration) => {
140 | registration.unregister();
141 | })
142 | .catch((error) => {
143 | console.error(error.message);
144 | });
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/react-cars-app/src/app/graphql-schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "__schema": {
3 | "description": null,
4 | "queryType": {
5 | "name": "Query"
6 | },
7 | "mutationType": {
8 | "name": "Mutation"
9 | },
10 | "subscriptionType": null,
11 | "types": [
12 | {
13 | "kind": "OBJECT",
14 | "name": "Car",
15 | "description": null,
16 | "specifiedByUrl": null,
17 | "fields": [
18 | {
19 | "name": "id",
20 | "description": null,
21 | "args": [],
22 | "type": {
23 | "kind": "NON_NULL",
24 | "name": null,
25 | "ofType": {
26 | "kind": "SCALAR",
27 | "name": "String",
28 | "ofType": null
29 | }
30 | },
31 | "isDeprecated": false,
32 | "deprecationReason": null
33 | },
34 | {
35 | "name": "name",
36 | "description": null,
37 | "args": [],
38 | "type": {
39 | "kind": "NON_NULL",
40 | "name": null,
41 | "ofType": {
42 | "kind": "SCALAR",
43 | "name": "String",
44 | "ofType": null
45 | }
46 | },
47 | "isDeprecated": false,
48 | "deprecationReason": null
49 | },
50 | {
51 | "name": "dailyPrice",
52 | "description": null,
53 | "args": [],
54 | "type": {
55 | "kind": "NON_NULL",
56 | "name": null,
57 | "ofType": {
58 | "kind": "SCALAR",
59 | "name": "Float",
60 | "ofType": null
61 | }
62 | },
63 | "isDeprecated": false,
64 | "deprecationReason": null
65 | },
66 | {
67 | "name": "monthlyPrice",
68 | "description": null,
69 | "args": [],
70 | "type": {
71 | "kind": "NON_NULL",
72 | "name": null,
73 | "ofType": {
74 | "kind": "SCALAR",
75 | "name": "Float",
76 | "ofType": null
77 | }
78 | },
79 | "isDeprecated": false,
80 | "deprecationReason": null
81 | },
82 | {
83 | "name": "mileage",
84 | "description": null,
85 | "args": [],
86 | "type": {
87 | "kind": "NON_NULL",
88 | "name": null,
89 | "ofType": {
90 | "kind": "SCALAR",
91 | "name": "String",
92 | "ofType": null
93 | }
94 | },
95 | "isDeprecated": false,
96 | "deprecationReason": null
97 | },
98 | {
99 | "name": "gas",
100 | "description": null,
101 | "args": [],
102 | "type": {
103 | "kind": "NON_NULL",
104 | "name": null,
105 | "ofType": {
106 | "kind": "SCALAR",
107 | "name": "String",
108 | "ofType": null
109 | }
110 | },
111 | "isDeprecated": false,
112 | "deprecationReason": null
113 | },
114 | {
115 | "name": "gearType",
116 | "description": null,
117 | "args": [],
118 | "type": {
119 | "kind": "NON_NULL",
120 | "name": null,
121 | "ofType": {
122 | "kind": "SCALAR",
123 | "name": "String",
124 | "ofType": null
125 | }
126 | },
127 | "isDeprecated": false,
128 | "deprecationReason": null
129 | },
130 | {
131 | "name": "thumbnailUrl",
132 | "description": null,
133 | "args": [],
134 | "type": {
135 | "kind": "NON_NULL",
136 | "name": null,
137 | "ofType": {
138 | "kind": "SCALAR",
139 | "name": "String",
140 | "ofType": null
141 | }
142 | },
143 | "isDeprecated": false,
144 | "deprecationReason": null
145 | }
146 | ],
147 | "inputFields": null,
148 | "interfaces": [],
149 | "enumValues": null,
150 | "possibleTypes": null
151 | },
152 | {
153 | "kind": "SCALAR",
154 | "name": "String",
155 | "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.",
156 | "specifiedByUrl": null,
157 | "fields": null,
158 | "inputFields": null,
159 | "interfaces": null,
160 | "enumValues": null,
161 | "possibleTypes": null
162 | },
163 | {
164 | "kind": "SCALAR",
165 | "name": "Float",
166 | "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).",
167 | "specifiedByUrl": null,
168 | "fields": null,
169 | "inputFields": null,
170 | "interfaces": null,
171 | "enumValues": null,
172 | "possibleTypes": null
173 | },
174 | {
175 | "kind": "OBJECT",
176 | "name": "Query",
177 | "description": null,
178 | "specifiedByUrl": null,
179 | "fields": [
180 | {
181 | "name": "cars",
182 | "description": null,
183 | "args": [],
184 | "type": {
185 | "kind": "NON_NULL",
186 | "name": null,
187 | "ofType": {
188 | "kind": "LIST",
189 | "name": null,
190 | "ofType": {
191 | "kind": "NON_NULL",
192 | "name": null,
193 | "ofType": {
194 | "kind": "OBJECT",
195 | "name": "Car",
196 | "ofType": null
197 | }
198 | }
199 | }
200 | },
201 | "isDeprecated": false,
202 | "deprecationReason": null
203 | }
204 | ],
205 | "inputFields": null,
206 | "interfaces": [],
207 | "enumValues": null,
208 | "possibleTypes": null
209 | },
210 | {
211 | "kind": "OBJECT",
212 | "name": "Mutation",
213 | "description": null,
214 | "specifiedByUrl": null,
215 | "fields": [
216 | {
217 | "name": "addNewCar",
218 | "description": null,
219 | "args": [
220 | {
221 | "name": "newCarData",
222 | "description": null,
223 | "type": {
224 | "kind": "NON_NULL",
225 | "name": null,
226 | "ofType": {
227 | "kind": "INPUT_OBJECT",
228 | "name": "NewCarInput",
229 | "ofType": null
230 | }
231 | },
232 | "defaultValue": null,
233 | "isDeprecated": false,
234 | "deprecationReason": null
235 | }
236 | ],
237 | "type": {
238 | "kind": "NON_NULL",
239 | "name": null,
240 | "ofType": {
241 | "kind": "OBJECT",
242 | "name": "Car",
243 | "ofType": null
244 | }
245 | },
246 | "isDeprecated": false,
247 | "deprecationReason": null
248 | }
249 | ],
250 | "inputFields": null,
251 | "interfaces": [],
252 | "enumValues": null,
253 | "possibleTypes": null
254 | },
255 | {
256 | "kind": "INPUT_OBJECT",
257 | "name": "NewCarInput",
258 | "description": null,
259 | "specifiedByUrl": null,
260 | "fields": null,
261 | "inputFields": [
262 | {
263 | "name": "name",
264 | "description": null,
265 | "type": {
266 | "kind": "NON_NULL",
267 | "name": null,
268 | "ofType": {
269 | "kind": "SCALAR",
270 | "name": "String",
271 | "ofType": null
272 | }
273 | },
274 | "defaultValue": null,
275 | "isDeprecated": false,
276 | "deprecationReason": null
277 | },
278 | {
279 | "name": "monthlyPrice",
280 | "description": null,
281 | "type": {
282 | "kind": "NON_NULL",
283 | "name": null,
284 | "ofType": {
285 | "kind": "SCALAR",
286 | "name": "Int",
287 | "ofType": null
288 | }
289 | },
290 | "defaultValue": null,
291 | "isDeprecated": false,
292 | "deprecationReason": null
293 | },
294 | {
295 | "name": "dailyPrice",
296 | "description": null,
297 | "type": {
298 | "kind": "NON_NULL",
299 | "name": null,
300 | "ofType": {
301 | "kind": "SCALAR",
302 | "name": "Int",
303 | "ofType": null
304 | }
305 | },
306 | "defaultValue": null,
307 | "isDeprecated": false,
308 | "deprecationReason": null
309 | },
310 | {
311 | "name": "mileage",
312 | "description": null,
313 | "type": {
314 | "kind": "NON_NULL",
315 | "name": null,
316 | "ofType": {
317 | "kind": "SCALAR",
318 | "name": "String",
319 | "ofType": null
320 | }
321 | },
322 | "defaultValue": null,
323 | "isDeprecated": false,
324 | "deprecationReason": null
325 | },
326 | {
327 | "name": "gas",
328 | "description": null,
329 | "type": {
330 | "kind": "NON_NULL",
331 | "name": null,
332 | "ofType": {
333 | "kind": "SCALAR",
334 | "name": "String",
335 | "ofType": null
336 | }
337 | },
338 | "defaultValue": null,
339 | "isDeprecated": false,
340 | "deprecationReason": null
341 | },
342 | {
343 | "name": "gearType",
344 | "description": null,
345 | "type": {
346 | "kind": "NON_NULL",
347 | "name": null,
348 | "ofType": {
349 | "kind": "SCALAR",
350 | "name": "String",
351 | "ofType": null
352 | }
353 | },
354 | "defaultValue": null,
355 | "isDeprecated": false,
356 | "deprecationReason": null
357 | },
358 | {
359 | "name": "thumbnailUrl",
360 | "description": null,
361 | "type": {
362 | "kind": "NON_NULL",
363 | "name": null,
364 | "ofType": {
365 | "kind": "SCALAR",
366 | "name": "String",
367 | "ofType": null
368 | }
369 | },
370 | "defaultValue": null,
371 | "isDeprecated": false,
372 | "deprecationReason": null
373 | }
374 | ],
375 | "interfaces": null,
376 | "enumValues": null,
377 | "possibleTypes": null
378 | },
379 | {
380 | "kind": "SCALAR",
381 | "name": "Int",
382 | "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",
383 | "specifiedByUrl": null,
384 | "fields": null,
385 | "inputFields": null,
386 | "interfaces": null,
387 | "enumValues": null,
388 | "possibleTypes": null
389 | },
390 | {
391 | "kind": "SCALAR",
392 | "name": "Boolean",
393 | "description": "The `Boolean` scalar type represents `true` or `false`.",
394 | "specifiedByUrl": null,
395 | "fields": null,
396 | "inputFields": null,
397 | "interfaces": null,
398 | "enumValues": null,
399 | "possibleTypes": null
400 | },
401 | {
402 | "kind": "OBJECT",
403 | "name": "__Schema",
404 | "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",
405 | "specifiedByUrl": null,
406 | "fields": [
407 | {
408 | "name": "description",
409 | "description": null,
410 | "args": [],
411 | "type": {
412 | "kind": "SCALAR",
413 | "name": "String",
414 | "ofType": null
415 | },
416 | "isDeprecated": false,
417 | "deprecationReason": null
418 | },
419 | {
420 | "name": "types",
421 | "description": "A list of all types supported by this server.",
422 | "args": [],
423 | "type": {
424 | "kind": "NON_NULL",
425 | "name": null,
426 | "ofType": {
427 | "kind": "LIST",
428 | "name": null,
429 | "ofType": {
430 | "kind": "NON_NULL",
431 | "name": null,
432 | "ofType": {
433 | "kind": "OBJECT",
434 | "name": "__Type",
435 | "ofType": null
436 | }
437 | }
438 | }
439 | },
440 | "isDeprecated": false,
441 | "deprecationReason": null
442 | },
443 | {
444 | "name": "queryType",
445 | "description": "The type that query operations will be rooted at.",
446 | "args": [],
447 | "type": {
448 | "kind": "NON_NULL",
449 | "name": null,
450 | "ofType": {
451 | "kind": "OBJECT",
452 | "name": "__Type",
453 | "ofType": null
454 | }
455 | },
456 | "isDeprecated": false,
457 | "deprecationReason": null
458 | },
459 | {
460 | "name": "mutationType",
461 | "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
462 | "args": [],
463 | "type": {
464 | "kind": "OBJECT",
465 | "name": "__Type",
466 | "ofType": null
467 | },
468 | "isDeprecated": false,
469 | "deprecationReason": null
470 | },
471 | {
472 | "name": "subscriptionType",
473 | "description": "If this server support subscription, the type that subscription operations will be rooted at.",
474 | "args": [],
475 | "type": {
476 | "kind": "OBJECT",
477 | "name": "__Type",
478 | "ofType": null
479 | },
480 | "isDeprecated": false,
481 | "deprecationReason": null
482 | },
483 | {
484 | "name": "directives",
485 | "description": "A list of all directives supported by this server.",
486 | "args": [],
487 | "type": {
488 | "kind": "NON_NULL",
489 | "name": null,
490 | "ofType": {
491 | "kind": "LIST",
492 | "name": null,
493 | "ofType": {
494 | "kind": "NON_NULL",
495 | "name": null,
496 | "ofType": {
497 | "kind": "OBJECT",
498 | "name": "__Directive",
499 | "ofType": null
500 | }
501 | }
502 | }
503 | },
504 | "isDeprecated": false,
505 | "deprecationReason": null
506 | }
507 | ],
508 | "inputFields": null,
509 | "interfaces": [],
510 | "enumValues": null,
511 | "possibleTypes": null
512 | },
513 | {
514 | "kind": "OBJECT",
515 | "name": "__Type",
516 | "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name, description and optional `specifiedByUrl`, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",
517 | "specifiedByUrl": null,
518 | "fields": [
519 | {
520 | "name": "kind",
521 | "description": null,
522 | "args": [],
523 | "type": {
524 | "kind": "NON_NULL",
525 | "name": null,
526 | "ofType": {
527 | "kind": "ENUM",
528 | "name": "__TypeKind",
529 | "ofType": null
530 | }
531 | },
532 | "isDeprecated": false,
533 | "deprecationReason": null
534 | },
535 | {
536 | "name": "name",
537 | "description": null,
538 | "args": [],
539 | "type": {
540 | "kind": "SCALAR",
541 | "name": "String",
542 | "ofType": null
543 | },
544 | "isDeprecated": false,
545 | "deprecationReason": null
546 | },
547 | {
548 | "name": "description",
549 | "description": null,
550 | "args": [],
551 | "type": {
552 | "kind": "SCALAR",
553 | "name": "String",
554 | "ofType": null
555 | },
556 | "isDeprecated": false,
557 | "deprecationReason": null
558 | },
559 | {
560 | "name": "specifiedByUrl",
561 | "description": null,
562 | "args": [],
563 | "type": {
564 | "kind": "SCALAR",
565 | "name": "String",
566 | "ofType": null
567 | },
568 | "isDeprecated": false,
569 | "deprecationReason": null
570 | },
571 | {
572 | "name": "fields",
573 | "description": null,
574 | "args": [
575 | {
576 | "name": "includeDeprecated",
577 | "description": null,
578 | "type": {
579 | "kind": "SCALAR",
580 | "name": "Boolean",
581 | "ofType": null
582 | },
583 | "defaultValue": "false",
584 | "isDeprecated": false,
585 | "deprecationReason": null
586 | }
587 | ],
588 | "type": {
589 | "kind": "LIST",
590 | "name": null,
591 | "ofType": {
592 | "kind": "NON_NULL",
593 | "name": null,
594 | "ofType": {
595 | "kind": "OBJECT",
596 | "name": "__Field",
597 | "ofType": null
598 | }
599 | }
600 | },
601 | "isDeprecated": false,
602 | "deprecationReason": null
603 | },
604 | {
605 | "name": "interfaces",
606 | "description": null,
607 | "args": [],
608 | "type": {
609 | "kind": "LIST",
610 | "name": null,
611 | "ofType": {
612 | "kind": "NON_NULL",
613 | "name": null,
614 | "ofType": {
615 | "kind": "OBJECT",
616 | "name": "__Type",
617 | "ofType": null
618 | }
619 | }
620 | },
621 | "isDeprecated": false,
622 | "deprecationReason": null
623 | },
624 | {
625 | "name": "possibleTypes",
626 | "description": null,
627 | "args": [],
628 | "type": {
629 | "kind": "LIST",
630 | "name": null,
631 | "ofType": {
632 | "kind": "NON_NULL",
633 | "name": null,
634 | "ofType": {
635 | "kind": "OBJECT",
636 | "name": "__Type",
637 | "ofType": null
638 | }
639 | }
640 | },
641 | "isDeprecated": false,
642 | "deprecationReason": null
643 | },
644 | {
645 | "name": "enumValues",
646 | "description": null,
647 | "args": [
648 | {
649 | "name": "includeDeprecated",
650 | "description": null,
651 | "type": {
652 | "kind": "SCALAR",
653 | "name": "Boolean",
654 | "ofType": null
655 | },
656 | "defaultValue": "false",
657 | "isDeprecated": false,
658 | "deprecationReason": null
659 | }
660 | ],
661 | "type": {
662 | "kind": "LIST",
663 | "name": null,
664 | "ofType": {
665 | "kind": "NON_NULL",
666 | "name": null,
667 | "ofType": {
668 | "kind": "OBJECT",
669 | "name": "__EnumValue",
670 | "ofType": null
671 | }
672 | }
673 | },
674 | "isDeprecated": false,
675 | "deprecationReason": null
676 | },
677 | {
678 | "name": "inputFields",
679 | "description": null,
680 | "args": [
681 | {
682 | "name": "includeDeprecated",
683 | "description": null,
684 | "type": {
685 | "kind": "SCALAR",
686 | "name": "Boolean",
687 | "ofType": null
688 | },
689 | "defaultValue": "false",
690 | "isDeprecated": false,
691 | "deprecationReason": null
692 | }
693 | ],
694 | "type": {
695 | "kind": "LIST",
696 | "name": null,
697 | "ofType": {
698 | "kind": "NON_NULL",
699 | "name": null,
700 | "ofType": {
701 | "kind": "OBJECT",
702 | "name": "__InputValue",
703 | "ofType": null
704 | }
705 | }
706 | },
707 | "isDeprecated": false,
708 | "deprecationReason": null
709 | },
710 | {
711 | "name": "ofType",
712 | "description": null,
713 | "args": [],
714 | "type": {
715 | "kind": "OBJECT",
716 | "name": "__Type",
717 | "ofType": null
718 | },
719 | "isDeprecated": false,
720 | "deprecationReason": null
721 | }
722 | ],
723 | "inputFields": null,
724 | "interfaces": [],
725 | "enumValues": null,
726 | "possibleTypes": null
727 | },
728 | {
729 | "kind": "ENUM",
730 | "name": "__TypeKind",
731 | "description": "An enum describing what kind of type a given `__Type` is.",
732 | "specifiedByUrl": null,
733 | "fields": null,
734 | "inputFields": null,
735 | "interfaces": null,
736 | "enumValues": [
737 | {
738 | "name": "SCALAR",
739 | "description": "Indicates this type is a scalar.",
740 | "isDeprecated": false,
741 | "deprecationReason": null
742 | },
743 | {
744 | "name": "OBJECT",
745 | "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
746 | "isDeprecated": false,
747 | "deprecationReason": null
748 | },
749 | {
750 | "name": "INTERFACE",
751 | "description": "Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields.",
752 | "isDeprecated": false,
753 | "deprecationReason": null
754 | },
755 | {
756 | "name": "UNION",
757 | "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
758 | "isDeprecated": false,
759 | "deprecationReason": null
760 | },
761 | {
762 | "name": "ENUM",
763 | "description": "Indicates this type is an enum. `enumValues` is a valid field.",
764 | "isDeprecated": false,
765 | "deprecationReason": null
766 | },
767 | {
768 | "name": "INPUT_OBJECT",
769 | "description": "Indicates this type is an input object. `inputFields` is a valid field.",
770 | "isDeprecated": false,
771 | "deprecationReason": null
772 | },
773 | {
774 | "name": "LIST",
775 | "description": "Indicates this type is a list. `ofType` is a valid field.",
776 | "isDeprecated": false,
777 | "deprecationReason": null
778 | },
779 | {
780 | "name": "NON_NULL",
781 | "description": "Indicates this type is a non-null. `ofType` is a valid field.",
782 | "isDeprecated": false,
783 | "deprecationReason": null
784 | }
785 | ],
786 | "possibleTypes": null
787 | },
788 | {
789 | "kind": "OBJECT",
790 | "name": "__Field",
791 | "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",
792 | "specifiedByUrl": null,
793 | "fields": [
794 | {
795 | "name": "name",
796 | "description": null,
797 | "args": [],
798 | "type": {
799 | "kind": "NON_NULL",
800 | "name": null,
801 | "ofType": {
802 | "kind": "SCALAR",
803 | "name": "String",
804 | "ofType": null
805 | }
806 | },
807 | "isDeprecated": false,
808 | "deprecationReason": null
809 | },
810 | {
811 | "name": "description",
812 | "description": null,
813 | "args": [],
814 | "type": {
815 | "kind": "SCALAR",
816 | "name": "String",
817 | "ofType": null
818 | },
819 | "isDeprecated": false,
820 | "deprecationReason": null
821 | },
822 | {
823 | "name": "args",
824 | "description": null,
825 | "args": [
826 | {
827 | "name": "includeDeprecated",
828 | "description": null,
829 | "type": {
830 | "kind": "SCALAR",
831 | "name": "Boolean",
832 | "ofType": null
833 | },
834 | "defaultValue": "false",
835 | "isDeprecated": false,
836 | "deprecationReason": null
837 | }
838 | ],
839 | "type": {
840 | "kind": "NON_NULL",
841 | "name": null,
842 | "ofType": {
843 | "kind": "LIST",
844 | "name": null,
845 | "ofType": {
846 | "kind": "NON_NULL",
847 | "name": null,
848 | "ofType": {
849 | "kind": "OBJECT",
850 | "name": "__InputValue",
851 | "ofType": null
852 | }
853 | }
854 | }
855 | },
856 | "isDeprecated": false,
857 | "deprecationReason": null
858 | },
859 | {
860 | "name": "type",
861 | "description": null,
862 | "args": [],
863 | "type": {
864 | "kind": "NON_NULL",
865 | "name": null,
866 | "ofType": {
867 | "kind": "OBJECT",
868 | "name": "__Type",
869 | "ofType": null
870 | }
871 | },
872 | "isDeprecated": false,
873 | "deprecationReason": null
874 | },
875 | {
876 | "name": "isDeprecated",
877 | "description": null,
878 | "args": [],
879 | "type": {
880 | "kind": "NON_NULL",
881 | "name": null,
882 | "ofType": {
883 | "kind": "SCALAR",
884 | "name": "Boolean",
885 | "ofType": null
886 | }
887 | },
888 | "isDeprecated": false,
889 | "deprecationReason": null
890 | },
891 | {
892 | "name": "deprecationReason",
893 | "description": null,
894 | "args": [],
895 | "type": {
896 | "kind": "SCALAR",
897 | "name": "String",
898 | "ofType": null
899 | },
900 | "isDeprecated": false,
901 | "deprecationReason": null
902 | }
903 | ],
904 | "inputFields": null,
905 | "interfaces": [],
906 | "enumValues": null,
907 | "possibleTypes": null
908 | },
909 | {
910 | "kind": "OBJECT",
911 | "name": "__InputValue",
912 | "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",
913 | "specifiedByUrl": null,
914 | "fields": [
915 | {
916 | "name": "name",
917 | "description": null,
918 | "args": [],
919 | "type": {
920 | "kind": "NON_NULL",
921 | "name": null,
922 | "ofType": {
923 | "kind": "SCALAR",
924 | "name": "String",
925 | "ofType": null
926 | }
927 | },
928 | "isDeprecated": false,
929 | "deprecationReason": null
930 | },
931 | {
932 | "name": "description",
933 | "description": null,
934 | "args": [],
935 | "type": {
936 | "kind": "SCALAR",
937 | "name": "String",
938 | "ofType": null
939 | },
940 | "isDeprecated": false,
941 | "deprecationReason": null
942 | },
943 | {
944 | "name": "type",
945 | "description": null,
946 | "args": [],
947 | "type": {
948 | "kind": "NON_NULL",
949 | "name": null,
950 | "ofType": {
951 | "kind": "OBJECT",
952 | "name": "__Type",
953 | "ofType": null
954 | }
955 | },
956 | "isDeprecated": false,
957 | "deprecationReason": null
958 | },
959 | {
960 | "name": "defaultValue",
961 | "description": "A GraphQL-formatted string representing the default value for this input value.",
962 | "args": [],
963 | "type": {
964 | "kind": "SCALAR",
965 | "name": "String",
966 | "ofType": null
967 | },
968 | "isDeprecated": false,
969 | "deprecationReason": null
970 | },
971 | {
972 | "name": "isDeprecated",
973 | "description": null,
974 | "args": [],
975 | "type": {
976 | "kind": "NON_NULL",
977 | "name": null,
978 | "ofType": {
979 | "kind": "SCALAR",
980 | "name": "Boolean",
981 | "ofType": null
982 | }
983 | },
984 | "isDeprecated": false,
985 | "deprecationReason": null
986 | },
987 | {
988 | "name": "deprecationReason",
989 | "description": null,
990 | "args": [],
991 | "type": {
992 | "kind": "SCALAR",
993 | "name": "String",
994 | "ofType": null
995 | },
996 | "isDeprecated": false,
997 | "deprecationReason": null
998 | }
999 | ],
1000 | "inputFields": null,
1001 | "interfaces": [],
1002 | "enumValues": null,
1003 | "possibleTypes": null
1004 | },
1005 | {
1006 | "kind": "OBJECT",
1007 | "name": "__EnumValue",
1008 | "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",
1009 | "specifiedByUrl": null,
1010 | "fields": [
1011 | {
1012 | "name": "name",
1013 | "description": null,
1014 | "args": [],
1015 | "type": {
1016 | "kind": "NON_NULL",
1017 | "name": null,
1018 | "ofType": {
1019 | "kind": "SCALAR",
1020 | "name": "String",
1021 | "ofType": null
1022 | }
1023 | },
1024 | "isDeprecated": false,
1025 | "deprecationReason": null
1026 | },
1027 | {
1028 | "name": "description",
1029 | "description": null,
1030 | "args": [],
1031 | "type": {
1032 | "kind": "SCALAR",
1033 | "name": "String",
1034 | "ofType": null
1035 | },
1036 | "isDeprecated": false,
1037 | "deprecationReason": null
1038 | },
1039 | {
1040 | "name": "isDeprecated",
1041 | "description": null,
1042 | "args": [],
1043 | "type": {
1044 | "kind": "NON_NULL",
1045 | "name": null,
1046 | "ofType": {
1047 | "kind": "SCALAR",
1048 | "name": "Boolean",
1049 | "ofType": null
1050 | }
1051 | },
1052 | "isDeprecated": false,
1053 | "deprecationReason": null
1054 | },
1055 | {
1056 | "name": "deprecationReason",
1057 | "description": null,
1058 | "args": [],
1059 | "type": {
1060 | "kind": "SCALAR",
1061 | "name": "String",
1062 | "ofType": null
1063 | },
1064 | "isDeprecated": false,
1065 | "deprecationReason": null
1066 | }
1067 | ],
1068 | "inputFields": null,
1069 | "interfaces": [],
1070 | "enumValues": null,
1071 | "possibleTypes": null
1072 | },
1073 | {
1074 | "kind": "OBJECT",
1075 | "name": "__Directive",
1076 | "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",
1077 | "specifiedByUrl": null,
1078 | "fields": [
1079 | {
1080 | "name": "name",
1081 | "description": null,
1082 | "args": [],
1083 | "type": {
1084 | "kind": "NON_NULL",
1085 | "name": null,
1086 | "ofType": {
1087 | "kind": "SCALAR",
1088 | "name": "String",
1089 | "ofType": null
1090 | }
1091 | },
1092 | "isDeprecated": false,
1093 | "deprecationReason": null
1094 | },
1095 | {
1096 | "name": "description",
1097 | "description": null,
1098 | "args": [],
1099 | "type": {
1100 | "kind": "SCALAR",
1101 | "name": "String",
1102 | "ofType": null
1103 | },
1104 | "isDeprecated": false,
1105 | "deprecationReason": null
1106 | },
1107 | {
1108 | "name": "isRepeatable",
1109 | "description": null,
1110 | "args": [],
1111 | "type": {
1112 | "kind": "NON_NULL",
1113 | "name": null,
1114 | "ofType": {
1115 | "kind": "SCALAR",
1116 | "name": "Boolean",
1117 | "ofType": null
1118 | }
1119 | },
1120 | "isDeprecated": false,
1121 | "deprecationReason": null
1122 | },
1123 | {
1124 | "name": "locations",
1125 | "description": null,
1126 | "args": [],
1127 | "type": {
1128 | "kind": "NON_NULL",
1129 | "name": null,
1130 | "ofType": {
1131 | "kind": "LIST",
1132 | "name": null,
1133 | "ofType": {
1134 | "kind": "NON_NULL",
1135 | "name": null,
1136 | "ofType": {
1137 | "kind": "ENUM",
1138 | "name": "__DirectiveLocation",
1139 | "ofType": null
1140 | }
1141 | }
1142 | }
1143 | },
1144 | "isDeprecated": false,
1145 | "deprecationReason": null
1146 | },
1147 | {
1148 | "name": "args",
1149 | "description": null,
1150 | "args": [],
1151 | "type": {
1152 | "kind": "NON_NULL",
1153 | "name": null,
1154 | "ofType": {
1155 | "kind": "LIST",
1156 | "name": null,
1157 | "ofType": {
1158 | "kind": "NON_NULL",
1159 | "name": null,
1160 | "ofType": {
1161 | "kind": "OBJECT",
1162 | "name": "__InputValue",
1163 | "ofType": null
1164 | }
1165 | }
1166 | }
1167 | },
1168 | "isDeprecated": false,
1169 | "deprecationReason": null
1170 | }
1171 | ],
1172 | "inputFields": null,
1173 | "interfaces": [],
1174 | "enumValues": null,
1175 | "possibleTypes": null
1176 | },
1177 | {
1178 | "kind": "ENUM",
1179 | "name": "__DirectiveLocation",
1180 | "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",
1181 | "specifiedByUrl": null,
1182 | "fields": null,
1183 | "inputFields": null,
1184 | "interfaces": null,
1185 | "enumValues": [
1186 | {
1187 | "name": "QUERY",
1188 | "description": "Location adjacent to a query operation.",
1189 | "isDeprecated": false,
1190 | "deprecationReason": null
1191 | },
1192 | {
1193 | "name": "MUTATION",
1194 | "description": "Location adjacent to a mutation operation.",
1195 | "isDeprecated": false,
1196 | "deprecationReason": null
1197 | },
1198 | {
1199 | "name": "SUBSCRIPTION",
1200 | "description": "Location adjacent to a subscription operation.",
1201 | "isDeprecated": false,
1202 | "deprecationReason": null
1203 | },
1204 | {
1205 | "name": "FIELD",
1206 | "description": "Location adjacent to a field.",
1207 | "isDeprecated": false,
1208 | "deprecationReason": null
1209 | },
1210 | {
1211 | "name": "FRAGMENT_DEFINITION",
1212 | "description": "Location adjacent to a fragment definition.",
1213 | "isDeprecated": false,
1214 | "deprecationReason": null
1215 | },
1216 | {
1217 | "name": "FRAGMENT_SPREAD",
1218 | "description": "Location adjacent to a fragment spread.",
1219 | "isDeprecated": false,
1220 | "deprecationReason": null
1221 | },
1222 | {
1223 | "name": "INLINE_FRAGMENT",
1224 | "description": "Location adjacent to an inline fragment.",
1225 | "isDeprecated": false,
1226 | "deprecationReason": null
1227 | },
1228 | {
1229 | "name": "VARIABLE_DEFINITION",
1230 | "description": "Location adjacent to a variable definition.",
1231 | "isDeprecated": false,
1232 | "deprecationReason": null
1233 | },
1234 | {
1235 | "name": "SCHEMA",
1236 | "description": "Location adjacent to a schema definition.",
1237 | "isDeprecated": false,
1238 | "deprecationReason": null
1239 | },
1240 | {
1241 | "name": "SCALAR",
1242 | "description": "Location adjacent to a scalar definition.",
1243 | "isDeprecated": false,
1244 | "deprecationReason": null
1245 | },
1246 | {
1247 | "name": "OBJECT",
1248 | "description": "Location adjacent to an object type definition.",
1249 | "isDeprecated": false,
1250 | "deprecationReason": null
1251 | },
1252 | {
1253 | "name": "FIELD_DEFINITION",
1254 | "description": "Location adjacent to a field definition.",
1255 | "isDeprecated": false,
1256 | "deprecationReason": null
1257 | },
1258 | {
1259 | "name": "ARGUMENT_DEFINITION",
1260 | "description": "Location adjacent to an argument definition.",
1261 | "isDeprecated": false,
1262 | "deprecationReason": null
1263 | },
1264 | {
1265 | "name": "INTERFACE",
1266 | "description": "Location adjacent to an interface definition.",
1267 | "isDeprecated": false,
1268 | "deprecationReason": null
1269 | },
1270 | {
1271 | "name": "UNION",
1272 | "description": "Location adjacent to a union definition.",
1273 | "isDeprecated": false,
1274 | "deprecationReason": null
1275 | },
1276 | {
1277 | "name": "ENUM",
1278 | "description": "Location adjacent to an enum definition.",
1279 | "isDeprecated": false,
1280 | "deprecationReason": null
1281 | },
1282 | {
1283 | "name": "ENUM_VALUE",
1284 | "description": "Location adjacent to an enum value definition.",
1285 | "isDeprecated": false,
1286 | "deprecationReason": null
1287 | },
1288 | {
1289 | "name": "INPUT_OBJECT",
1290 | "description": "Location adjacent to an input object type definition.",
1291 | "isDeprecated": false,
1292 | "deprecationReason": null
1293 | },
1294 | {
1295 | "name": "INPUT_FIELD_DEFINITION",
1296 | "description": "Location adjacent to an input object field definition.",
1297 | "isDeprecated": false,
1298 | "deprecationReason": null
1299 | }
1300 | ],
1301 | "possibleTypes": null
1302 | }
1303 | ],
1304 | "directives": [
1305 | {
1306 | "name": "include",
1307 | "description": "Directs the executor to include this field or fragment only when the `if` argument is true.",
1308 | "isRepeatable": false,
1309 | "locations": [
1310 | "FIELD",
1311 | "FRAGMENT_SPREAD",
1312 | "INLINE_FRAGMENT"
1313 | ],
1314 | "args": [
1315 | {
1316 | "name": "if",
1317 | "description": "Included when true.",
1318 | "type": {
1319 | "kind": "NON_NULL",
1320 | "name": null,
1321 | "ofType": {
1322 | "kind": "SCALAR",
1323 | "name": "Boolean",
1324 | "ofType": null
1325 | }
1326 | },
1327 | "defaultValue": null,
1328 | "isDeprecated": false,
1329 | "deprecationReason": null
1330 | }
1331 | ]
1332 | },
1333 | {
1334 | "name": "skip",
1335 | "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
1336 | "isRepeatable": false,
1337 | "locations": [
1338 | "FIELD",
1339 | "FRAGMENT_SPREAD",
1340 | "INLINE_FRAGMENT"
1341 | ],
1342 | "args": [
1343 | {
1344 | "name": "if",
1345 | "description": "Skipped when true.",
1346 | "type": {
1347 | "kind": "NON_NULL",
1348 | "name": null,
1349 | "ofType": {
1350 | "kind": "SCALAR",
1351 | "name": "Boolean",
1352 | "ofType": null
1353 | }
1354 | },
1355 | "defaultValue": null,
1356 | "isDeprecated": false,
1357 | "deprecationReason": null
1358 | }
1359 | ]
1360 | },
1361 | {
1362 | "name": "deprecated",
1363 | "description": "Marks an element of a GraphQL schema as no longer supported.",
1364 | "isRepeatable": false,
1365 | "locations": [
1366 | "FIELD_DEFINITION",
1367 | "ARGUMENT_DEFINITION",
1368 | "INPUT_FIELD_DEFINITION",
1369 | "ENUM_VALUE"
1370 | ],
1371 | "args": [
1372 | {
1373 | "name": "reason",
1374 | "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/).",
1375 | "type": {
1376 | "kind": "SCALAR",
1377 | "name": "String",
1378 | "ofType": null
1379 | },
1380 | "defaultValue": "\"No longer supported\"",
1381 | "isDeprecated": false,
1382 | "deprecationReason": null
1383 | }
1384 | ]
1385 | },
1386 | {
1387 | "name": "specifiedBy",
1388 | "description": "Exposes a URL that specifies the behaviour of this scalar.",
1389 | "isRepeatable": false,
1390 | "locations": [
1391 | "SCALAR"
1392 | ],
1393 | "args": [
1394 | {
1395 | "name": "url",
1396 | "description": "The URL that specifies the behaviour of this scalar.",
1397 | "type": {
1398 | "kind": "NON_NULL",
1399 | "name": null,
1400 | "ofType": {
1401 | "kind": "SCALAR",
1402 | "name": "String",
1403 | "ofType": null
1404 | }
1405 | },
1406 | "defaultValue": null,
1407 | "isDeprecated": false,
1408 | "deprecationReason": null
1409 | }
1410 | ]
1411 | }
1412 | ]
1413 | }
1414 | }
--------------------------------------------------------------------------------