├── .DS_Store ├── .circleci └── config.yml ├── .github ├── FUNDING.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── .idea ├── .gitignore ├── 17-ghstats.iml ├── inspectionProfiles │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .travis.yml ├── CONTRIBUTING.md ├── GraphQuery.js ├── LICENSE ├── README.md ├── client ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── github-logo24.png │ ├── github-logo64.ico │ ├── github-logo64.png │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.js │ ├── App.test.js │ ├── common │ └── AppGrid.js │ ├── component │ ├── About.js │ ├── Country.js │ ├── Home.js │ └── Stats.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ ├── setupProxy.js │ └── util │ ├── CountryUtils.js │ └── HomeUtils.js ├── headers.json ├── package-lock.json ├── package.json ├── server.js ├── temp.svg ├── template.svg └── util.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/.DS_Store -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node 8 simple CircleCI 2.0 configuration file 2 | # Eduardo San Martin Morote 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # Put this file in a .circleci/ folder 5 | version: 2 6 | 7 | 8 | jobs: 9 | build: 10 | docker: 11 | # specify the version you desire here 12 | - image: circleci/node:8 13 | 14 | # Specify service dependencies here if necessary 15 | # CircleCI maintains a library of pre-built images 16 | # documented at https://circleci.com/docs/2.0/circleci-images/ 17 | # - image: circleci/mongo:3.4.4 18 | 19 | working_directory: ~/repo 20 | 21 | steps: 22 | - checkout 23 | 24 | # Download and cache dependencies 25 | - restore_cache: 26 | keys: 27 | - v1-dependencies-{{ checksum "package.json" }} 28 | # fallback to using the latest cache if no exact match is found 29 | - v1-dependencies- 30 | 31 | - run: npm install 32 | 33 | - save_cache: 34 | paths: 35 | - node_modules 36 | key: v1-dependencies-{{ checksum "package.json" }} 37 | 38 | # run tests! 39 | - run: npm test 40 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [8.x, 10.x, 12.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: npm install, build, and test 21 | run: | 22 | npm ci 23 | npm run build --if-present 24 | npm test 25 | env: 26 | CI: true 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/17-ghstats.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # GitHub Stats (Contribute) 2 | ### How to become a contributor and submit your own code? 3 | You can contribute to this open-source project by suggestions to the issues of the server and client app. 4 | The project needs to improve it's performance, stability, and user interface of both server scripts and client app. 5 | Adding more countries to the project helps other to discover it's contribution to the GitHub. 6 | 7 | ##### Fork 8 | Getting started the contribution you need to `Fork` the project by your own to make sure you can `Merge` it with a `Pull request` 9 | later to complete the contribution. 10 | 11 | ##### Clone 12 | You can `clone` your `fork` by using `git clone repository` from the command prompt tool or 13 | using an IDE like Web Storm, Visual Code and etc. After you `clone` the repository you can see the files 14 | in the directory. 15 | 16 | --- 17 | #### Add new country 18 | ##### Server 19 | ##### Create new country array object [server.js#L62](https://github.com/gayanvoice/githubstats-github-graphql/blob/d00a177b006cb4d08052f58a9f8415fe504b55f3/server.js#L62). 20 | The array structure is ` {city: ["Country_Name", "CountryName", "City", "City"]}` You can add five most populated cities. These cities should be supported by GitHub (Sometimes the native languages may not work). 21 | 22 | #### After you have done the changes you can create a [Create request](https://github.com/gayanvoice/githubstats/pulls) and name it `Add Country Name` for an example `Add Austria`. After the review, if there are no errors your contribution will be displayed in [GitHubStats](http://www.githubstats.com/) with a link to your GitHub profile. 23 | 24 | --- 25 | ### File system 26 | #### Server 27 | The root directory of the repository contains several folders and files. The server is a Node.js app. 28 | To start the server `node server.js`. 29 |
30 | githubstats/
31 | ├── client/
32 | │   ├── public/
33 | │   └── ...
34 | ├── GraphQuery.js
35 | ├── server.js
36 | └── util.js
37 | 
38 | ##### `GraphQuery.js` 39 | GraphQuery is a class which is used to fetch data from the GitHub GraphQL API. 40 | It fetches 1000 users with most followers based on the locations. 41 | ##### `server.js` 42 | This script is running the server. It calls the API, and requests user data from GitHub based 43 | on the locations of the Javascript arrays. 44 | ##### `util.js` 45 | This contains some basic functions such as `check_file(path)`, `parse(String)`, and `locations(array)`. 46 | 47 | --- 48 | #### Client 49 | The root directory of the client repository contains several folders and files. 50 | The client app is written using React.js. To start the client app, go to client directory `cd client` and `npm run start`. 51 |
52 | githubstats/
53 | ├── client/
54 | │   ├── public/
55 | │   │   ├── favicon.ico
56 | │   │   ├── github-log64.ico
57 | │   │   ├── index.html
58 | │   │   └── ...
59 | │   ├── src/
60 | │   │   ├── components/
61 | │   │   │   ├── About.js
62 | │   │   │   ├── Country.js
63 | │   │   │   └── Home.js
64 | │   │   ├── App.js
65 | │   │   ├── setupProxy.js
66 | │   │   └── ...
67 | │   ├── .gitignore
68 | │   ├── README.md
69 | │   ├── package-lock.json
70 | │   └── package.json
71 | └── ...
72 | 
73 | ##### `public` 74 | The folder contains the `.ico` files, and index.html file. 75 | ##### `src` 76 | The folder contains the `components` folder which contains `Country.js` file. 77 | ##### `components/Country.js` 78 | This React Component fetches the list of users and render the list as a range. 79 | It has several methods like `compare(a, b)`, `check_username(value)`, `limit(value)`, and `renderMyData(param)`. 80 | ##### `components/Home.js` 81 | This React Component fetches the list of countries and render it in a table. 82 | ##### `App.js` 83 | The main React App component which is used to display the content of the React Component and the UI. 84 | ##### `setupProxy.js` 85 | The app connects to the server through the API. 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /GraphQuery.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const util = require('./util'); 3 | var mongo = require('mongodb').MongoClient; 4 | const assert = require('assert'); 5 | 6 | module.exports = class GraphQuery { 7 | 8 | constructor(cities, key, records, url) { 9 | process.stdout.write(cities[0].toLowerCase() + ' '); 10 | this.jsonAr = []; 11 | this.refresh = 0; 12 | this.next = true; 13 | this.cursor = null; 14 | this.cities = cities; 15 | this.country = cities[0].toLowerCase(); 16 | this.key = key; 17 | this.url = url; 18 | this.per = records[0]; 19 | this.num = records[1]; 20 | 21 | this.query = ` 22 | query { 23 | search(type: USER, query:"%s sort:followers-desc", first:%s, after:%s) { 24 | edges { 25 | node { 26 | __typename 27 | ... on User { 28 | login, 29 | avatarUrl(size: 72), 30 | name, 31 | company, 32 | location, 33 | organizations(first: 1) { 34 | nodes { 35 | login 36 | } 37 | } 38 | followers { 39 | totalCount 40 | } 41 | contributionsCollection { 42 | contributionCalendar { 43 | totalContributions 44 | } 45 | restrictedContributionsCount 46 | } 47 | } 48 | } 49 | } 50 | pageInfo { 51 | endCursor 52 | hasNextPage 53 | } 54 | } 55 | }`; 56 | 57 | } 58 | 59 | request() { 60 | if (!(this.refresh < this.num)) { 61 | this.next = false; 62 | } else { 63 | this.refresh = this.refresh + 1; 64 | } 65 | //console.log(this.re); 66 | if (this.next) { 67 | axios 68 | .create({ 69 | baseURL: 'https://api.github.com/graphql', 70 | headers: { 71 | Authorization: `bearer ` + this.key + `` 72 | }, 73 | }) 74 | .post('', { 75 | query: util.parse(this.query, util.locations(this.cities), this.per, this.cursor) 76 | }) 77 | .then(({data}) => { 78 | //console.log(data); 79 | var jsonStr = data.data.search.edges; 80 | var jsonAr = this.jsonAr; 81 | this.cursor = "\"" + data.data.search.pageInfo.endCursor + "\""; 82 | this.next = data.data.search.pageInfo.hasNextPage; 83 | 84 | process.stdout.write(this.refresh + ' '); 85 | Object.keys(jsonStr).forEach(function (index, key) { 86 | if (jsonStr[key].node.__typename === "User") { 87 | // "__typename": "User", 88 | //process.stdout.write(index + ' '); 89 | //console.log(key, jsonStr[key].node.__typename, jsonStr[key].node.login, jsonStr[key].node.name, jsonStr[key].node.followers.totalCount); 90 | var record = { 91 | 'id': key, 92 | 'avatar_url': jsonStr[key].node.avatarUrl, 93 | 'login': jsonStr[key].node.login, 94 | 'name': jsonStr[key].node.name, 95 | 'location': jsonStr[key].node.location, 96 | 'followers': jsonStr[key].node.followers.totalCount, 97 | 'public_contributions': jsonStr[key].node.contributionsCollection.contributionCalendar.totalContributions, 98 | 'private_contributions': jsonStr[key].node.contributionsCollection.restrictedContributionsCount 99 | }; 100 | jsonAr.push(record); 101 | } else { 102 | console.log(jsonStr[key].node.__typename); 103 | } 104 | }); 105 | this.request(); 106 | }) 107 | .catch(function (e) { 108 | console.log(util.getDateTime() + e); 109 | }); 110 | } else { 111 | var data = { 112 | country: this.country, 113 | dataset: this.jsonAr, 114 | modified: util.getDateTime() 115 | }; 116 | mongo.connect(this.url, {useUnifiedTopology: true}, function (err, client) { 117 | assert.equal(null, err); 118 | const collection = client.db("database").collection("countries"); 119 | collection.updateOne( 120 | {_country: data.country}, 121 | {$set: data}, 122 | {upsert: true}) 123 | .then(function () { 124 | // process result 125 | client.close(); 126 | }); 127 | }); 128 | 129 | console.log(util.getDateTime() + " The file is saved!" + util.locations(this.cities)); 130 | } 131 | util.check_file(this.path); 132 | } 133 | }; 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-present Gayan Kuruppu & contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js + Express.js + GraphQL + MongoDB + React 2 | [![CircleCI](https://circleci.com/gh/gayanvoice/most-active-github-users-nodejs/tree/master.svg?style=svg)](https://circleci.com/gh/gayanvoice/most-active-github-users-nodejs/tree/master) 3 | [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/gayanvoice/githubstats.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/gayanvoice/githubstats/context:javascript) 4 | [![Total alerts](https://img.shields.io/lgtm/alerts/g/gayanvoice/githubstats.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/gayanvoice/githubstats/alerts/) 5 | ![GitHub](https://img.shields.io/github/license/gayanvoice/GitHubStats) 6 | ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/gayanvoice/GitHubStats) 7 | [![GitHub Stats](https://githubstats-com.herokuapp.com/get/gayanvoice/most-active-github-users-nodejs)](http://www.githubstats.com/stats) 8 | 9 | Go to HTTP [http://www.githubstats.com/](http://www.githubstats.com/) 10 | Go to HTTP Secured [https://githubstats-com.herokuapp.com/](https://githubstats-com.herokuapp.com/) 11 | 12 | ### The app is experimental and needs review on the code. Please contribute or raise an issue to look in to it. 13 | 14 | ### Frameworks 15 | ![GraphQL, Express.js, Node.js](https://raw.githubusercontent.com/gayanvoice/githubstats-github-graphql/images/github-stats-3.PNG "Frameworks GraphQL, Express.js, Node.js") 16 | 17 | The app is updated at every 24 hours. This React.js app fetches active users from GitHub GraphQL API using Express.js in Node.js. The app uses the number of public and private contributions 18 | you have done in the year. 19 | 20 | ## Images 21 | ### Choose a country 22 | ![Home page](https://raw.githubusercontent.com/b14d35/nodejs-graphql/images/github-stats-1.PNG "githubstats.com screenshots") 23 | ### Active users from Ireland 24 | ![Ireland](https://raw.githubusercontent.com/b14d35/nodejs-graphql/images/github-stats-2.PNG "githubstats.com screenshots") 25 | 26 | ## How it works? 27 | Users need to create a GitHub token to fetch the results from GitHub Graph API. The list of countries and the cities are listed in `server.js` as arrays and `GraphQuery.js` fetches the data from GitHub Graph API. After the fetch was completed, it creates a JSON file in `/client/src/data/` where the React app gets the list of users and the contribution. 28 | 29 | ## Contribute 30 | You can contribute to this open-source project by suggestions to the issues of the server and client app. The project needs to improve it's performance, stability, and user interface of both server scripts and client app. Adding more countries to the project helps other to discover it's contribution to the GitHub. [How to the Contribute](https://github.com/gayanvoice/githubstats/blob/master/CONTRIBUTING.md) 31 | 32 | ## Feature 33 | 1. Inside DevInside Dev (Oct 21st, 2019) https://inside.com/campaigns/inside-dev-2019-10-21-18599 34 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm 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 | ### `npm 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 | ### `npm run 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 | ### `npm run 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 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `npm run build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "bootstrap": "^4.3.1", 7 | "http-proxy-middleware": "^0.20.0", 8 | "prop-types": "^15.7.2", 9 | "react": "^16.10.2", 10 | "react-dom": "^16.10.2", 11 | "react-github-btn": "^1.1.1", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "^3.4.1", 14 | "react-share": "^3.0.1" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/github-logo24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/github-logo24.png -------------------------------------------------------------------------------- /client/public/github-logo64.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/github-logo64.ico -------------------------------------------------------------------------------- /client/public/github-logo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/github-logo64.png -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 30 | 31 | List of most active users in GitHub - GitHubStats 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/logo192.png -------------------------------------------------------------------------------- /client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gayanvoice/most-active-github-users-nodejs/557aad08e6a1733c57c3071064177ddf41c15ec0/client/public/logo512.png -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "GitHub Stats", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /client/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter } from 'react-router-dom'; 3 | import { Route } from 'react-router-dom'; 4 | import { Switch } from 'react-router-dom'; 5 | 6 | import CssBaseline from '@material-ui/core/CssBaseline'; 7 | import Box from '@material-ui/core/Box'; 8 | 9 | import Country from './component/Country'; 10 | import Home from './component/Home'; 11 | import About from './component/About'; 12 | import Stats from "./component/Stats"; 13 | import AppGrid from './common/AppGrid' 14 | 15 | export default function App() { 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {AppGrid} 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /client/src/common/AppGrid.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import GitHubButton from "react-github-btn"; 4 | 5 | import Grid from "@material-ui/core/Grid"; 6 | import Paper from "@material-ui/core/Paper"; 7 | import Typography from "@material-ui/core/Typography"; 8 | import {makeStyles} from "@material-ui/core/styles"; 9 | 10 | const useStyles = makeStyles(theme => ({ 11 | root: { 12 | flexGrow: 1, 13 | position: 'fixed', 14 | bottom: theme.spacing(2), 15 | right: theme.spacing(2), 16 | }, 17 | menuButton: { 18 | marginRight: theme.spacing(2), 19 | }, 20 | title: { 21 | flexGrow: 1, 22 | }, 23 | })); 24 | 25 | export default function AppGrid() { 26 | const classes = useStyles(); 27 | return ( 28 | 29 | 30 | 31 | How it works? 32 | 33 | List of most active GitHub users in the country over the past year based on public contributions 34 | of each user. To contribute, create your pull request and add changes to the project gayanvoice/nodejs-graphql 36 | 37 | 38 | 39 | 40 | 41 | Frameworks 42 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Deploy 71 | 81 | 82 | 83 | 84 | 85 | Contributors 86 | 130 | How to contribute? Add missing countries 132 | 133 | 134 | 135 | 136 |
137 | 138 | Follow @gayanvoice 141 | 142 | 143 | Star 148 | 149 | Like this project? Go to gayanvoice/most-active-github-users-nodejs 151 | This project is not affiliated with the GitHub company in any way 152 |
153 |
154 | 155 |
156 | 157 |
158 | ) 159 | 160 | } -------------------------------------------------------------------------------- /client/src/component/About.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BrowserRouter} from 'react-router-dom'; 3 | 4 | function About() { 5 | return ( 6 | 7 |
8 | About 9 |
10 |
11 | ); 12 | } 13 | 14 | export default About; 15 | -------------------------------------------------------------------------------- /client/src/component/Country.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Component} from 'react'; 3 | import {Link} from "react-router-dom"; 4 | 5 | import LinearProgress from '@material-ui/core/LinearProgress'; 6 | import AppBar from "@material-ui/core/AppBar"; 7 | import Toolbar from "@material-ui/core/Toolbar"; 8 | import Typography from "@material-ui/core/Typography"; 9 | import IconButton from "@material-ui/core/IconButton"; 10 | import Box from "@material-ui/core/Box"; 11 | import Grid from "@material-ui/core/Grid"; 12 | import Paper from "@material-ui/core/Paper"; 13 | import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos'; 14 | 15 | import {check_username, compare, titleCase} from '../util/CountryUtils' 16 | import CircularProgress from "@material-ui/core/CircularProgress"; 17 | 18 | 19 | class Country extends Component { 20 | constructor(props) { 21 | super(props); 22 | this.state = { 23 | data: [], 24 | modified: null, 25 | render: false 26 | }; 27 | 28 | } 29 | 30 | renderCountryData(param) { 31 | console.log(param); 32 | fetch('/contributions/' + param) 33 | .then((response) => response.json()) 34 | .then((responseJson) => { 35 | console.log(responseJson); 36 | try { 37 | this.setState({data: responseJson[0].dataset, modified: responseJson[0].modified, render: true}); 38 | } catch (e) { 39 | console.log(e); 40 | } 41 | }).catch((error) => { 42 | console.error(error); 43 | }); 44 | } 45 | 46 | componentDidMount() { 47 | const param = this.props.match.params.name; 48 | this.renderCountryData(param); 49 | } 50 | 51 | 52 | componentDidUpdate(prevProps) { 53 | const param = this.props.match.params.name; 54 | if (param !== prevProps.match.params.name) 55 | this.renderCountryData(param); 56 | } 57 | 58 | limit = (value) => { 59 | return value.slice((this.props.match.params.from), (this.props.match.params.to)) 60 | }; 61 | 62 | mDate = (date) => { 63 | if (!this.state.render) { 64 | return 65 | } else return new Date(date).toUTCString(); 66 | }; 67 | 68 | 69 | render() { 70 | const isRender = this.state.render; 71 | if (!isRender) { 72 | return ( 73 | <> 74 | 75 | 76 | 77 | 82 | 83 | 84 | 85 | GitHub Stats 86 | 87 | 88 | 89 | 90 | 91 | ); 92 | } else { 93 | return ( 94 | <> 95 | 96 | 97 | 101 | 102 | 103 | 104 | GitHub Stats 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | Active users 115 | from {titleCase(this.props.match.params.name)} 116 |
117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | {this.limit(this.state.data.sort(compare)).map((item, key) => { 131 | return 132 | 133 | 137 | 148 | 149 | 150 | 151 | })} 152 | 153 |
Last modified {this.mDate(this.state.modified)}
#ImageUsernameLocationTotal Contributions
{parseInt(this.props.match.params.from) + key + 1} 134 | {item.login} 136 | 138 | 141 | {check_username(item.name)} 142 | 143 | 144 | @{item.login} ({item.followers}) 145 | 146 | 147 | {item.location}{item.public_contributions}
154 |
155 | 156 | 157 |
158 | 214 |
215 |
216 |
217 |
218 |
219 | 220 | 221 | ); 222 | } 223 | } 224 | } 225 | 226 | export default Country; -------------------------------------------------------------------------------- /client/src/component/Home.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import {Link} from 'react-router-dom'; 5 | import LinearProgress from "@material-ui/core/LinearProgress"; 6 | import {makeStyles} from "@material-ui/core/styles"; 7 | import Toolbar from "@material-ui/core/Toolbar"; 8 | import Fab from "@material-ui/core/Fab"; 9 | import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp"; 10 | import useScrollTrigger from "@material-ui/core/useScrollTrigger"; 11 | import Zoom from "@material-ui/core/Zoom"; 12 | import Grid from "@material-ui/core/Grid"; 13 | import Paper from "@material-ui/core/Paper"; 14 | import List from "@material-ui/core/List"; 15 | import ListItem from "@material-ui/core/ListItem"; 16 | import ListItemAvatar from "@material-ui/core/ListItemAvatar"; 17 | import Avatar from "@material-ui/core/Avatar"; 18 | import ListItemText from "@material-ui/core/ListItemText"; 19 | import ImageIcon from '@material-ui/icons/Image'; 20 | import ChevronRightIcon from '@material-ui/icons/ChevronRight'; 21 | import Box from "@material-ui/core/Box"; 22 | import Slide from "@material-ui/core/Slide"; 23 | 24 | import {getCountry} from "../util/HomeUtils"; 25 | import IconButton from "@material-ui/core/IconButton"; 26 | import HomeIcon from "@material-ui/icons/Home"; 27 | import Typography from "@material-ui/core/Typography"; 28 | import EqualizerIcon from "@material-ui/icons/Equalizer"; 29 | import GitHubIcon from "@material-ui/icons/GitHub"; 30 | import AppBar from "@material-ui/core/AppBar"; 31 | 32 | 33 | const useStyles = makeStyles(theme => ({ 34 | root: { 35 | flexGrow: 1, 36 | position: 'fixed', 37 | bottom: theme.spacing(2), 38 | right: theme.spacing(2), 39 | }, 40 | menuButton: { 41 | marginRight: theme.spacing(2), 42 | }, 43 | title: { 44 | flexGrow: 1, 45 | } 46 | })); 47 | 48 | 49 | function ScrollTop(props) { 50 | const {children, window} = props; 51 | const classes = useStyles(); 52 | const trigger = useScrollTrigger({ 53 | target: window ? window() : undefined, 54 | disableHysteresis: true, 55 | threshold: 100, 56 | }); 57 | 58 | const handleClick = event => { 59 | const anchor = (event.target.ownerDocument || document).querySelector('#back-to-top-anchor'); 60 | 61 | if (anchor) { 62 | anchor.scrollIntoView({behavior: 'smooth', block: 'center'}); 63 | } 64 | }; 65 | 66 | return ( 67 | 68 |
69 | {children} 70 |
71 |
72 | ); 73 | } 74 | 75 | const HideOnScroll = (props) => { 76 | const {children, window} = props; 77 | const trigger = useScrollTrigger({target: window ? window() : undefined}); 78 | 79 | return ( 80 | 81 | {children} 82 | 83 | ); 84 | }; 85 | 86 | 87 | HideOnScroll.propTypes = { 88 | children: PropTypes.element.isRequired, 89 | window: PropTypes.func, 90 | }; 91 | 92 | ScrollTop.propTypes = { 93 | children: PropTypes.element.isRequired, 94 | window: PropTypes.func, 95 | }; 96 | 97 | 98 | export default function Home(props) { 99 | const classes = useStyles(); 100 | const [data, setData] = useState([]); 101 | const [render, setRender] = useState(false); 102 | 103 | useEffect(() => { 104 | fetch('/contributions/all') 105 | .then((response) => response.json()) 106 | .then((responseJson) => { 107 | console.log(responseJson); 108 | try { 109 | setData(responseJson); 110 | setRender(true); 111 | } catch (e) { 112 | console.log(e); 113 | } 114 | }).catch((error) => { 115 | console.error(error); 116 | }); 117 | }, [false]); 118 | 119 | if (!render) { 120 | return ( 121 | <> 122 | 123 | 124 | ); 125 | } else { 126 | return ( 127 | <> 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | GitHub Stats 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | {data.map((item, key) => { 153 | return ( 154 | 156 | 157 | 158 | 159 | 160 | 161 | {/*{getCountry(item.city[0])}*/} 162 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | ) 171 | })} 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | ); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /client/src/component/Stats.js: -------------------------------------------------------------------------------- 1 | import Typography from "@material-ui/core/Typography"; 2 | import Paper from "@material-ui/core/Paper"; 3 | import React from "react"; 4 | import TextField from "@material-ui/core/TextField"; 5 | import Button from "@material-ui/core/Button"; 6 | import AppBar from "@material-ui/core/AppBar"; 7 | import LinearProgress from "@material-ui/core/LinearProgress"; 8 | import Toolbar from "@material-ui/core/Toolbar"; 9 | import IconButton from "@material-ui/core/IconButton"; 10 | import {Link} from "react-router-dom"; 11 | import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; 12 | import Box from "@material-ui/core/Box"; 13 | import Grid from "@material-ui/core/Grid"; 14 | 15 | export default class Stats extends React.Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | username: '', 20 | repository: '', 21 | submit: false, 22 | created: false, 23 | copyText: '', 24 | markDown: '' 25 | }; 26 | 27 | this.handleChange = this.handleChange.bind(this); 28 | this.handleSubmit = this.handleSubmit.bind(this); 29 | } 30 | 31 | handleChange(event) { 32 | const target = event.target; 33 | const value = target.type === 'checkbox' ? target.checked : target.value; 34 | const name = target.name; 35 | this.setState({ 36 | [name]: value 37 | }); 38 | } 39 | 40 | handleSubmit(event) { 41 | this.submitRepository(this.state.username, this.state.repository); 42 | this.setState({ 43 | copyText: "http://www.githubstats.com/get/" + this.state.username + "/" + this.state.repository, 44 | markDown: "[![GitHub Stats](http://www.githubstats.com/get/" + this.state.username + "/" + this.state.repository + ")](http://www.githubstats.com/stats)" 45 | }); 46 | event.preventDefault(); 47 | } 48 | 49 | submitRepository(username, repository){ 50 | console.log(username, repository); 51 | this.setState( { 52 | submit: true 53 | }) 54 | fetch('/set/'+ username + '/' + repository) 55 | .then((response) => response.json()) 56 | .then((responseJson) => { 57 | if(responseJson === true){ 58 | this.setState({ created:true }); 59 | } 60 | this.setState( { 61 | submit: false 62 | }) 63 | 64 | }).catch((error) => { 65 | console.error(error); 66 | }); 67 | } 68 | 69 | render() { 70 | const submit = this.state.submit; 71 | const created = this.state.created; 72 | if (submit){ 73 | return ( 74 | <> 75 | 76 | 77 | 78 | 83 | 84 | 85 | 86 | GitHub Stats 87 | 88 | 89 | 90 | 91 | 92 | ); 93 | } else { 94 | return ( 95 | <> 96 | 97 | 98 | 103 | 104 | 105 | 106 | GitHub Stats 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | Stats? 116 |
117 | 118 | 119 | 122 | 123 |
124 | 125 | 133 | 141 | 142 | 143 |
144 |
145 |
146 | 147 | 148 | 149 | ); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | import 'bootstrap/dist/css/bootstrap.css'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | 10 | // If you want your app to work offline and load faster, you can change 11 | // unregister() to register() below. Note this comes with some pitfalls. 12 | // Learn more about service workers: https://bit.ly/CRA-PWA 13 | serviceWorker.unregister(); 14 | -------------------------------------------------------------------------------- /client/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/serviceWorker.js: -------------------------------------------------------------------------------- 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.1/8 is 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 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /client/src/setupProxy.js: -------------------------------------------------------------------------------- 1 | const proxy = require("http-proxy-middleware"); 2 | 3 | module.exports = app => { 4 | app.use(proxy(["/contributions/*", ], {target: "http://localhost:4000/"})); 5 | app.use(proxy("/set/*/*", {target: "http://localhost:4000/"})); 6 | app.use(proxy("/get/*/*", {target: "http://localhost:4000/"})); 7 | }; -------------------------------------------------------------------------------- /client/src/util/CountryUtils.js: -------------------------------------------------------------------------------- 1 | const compare = (a, b) => { 2 | if (a.public_contributions < b.public_contributions) { 3 | return 1; 4 | } 5 | if (a.public_contributions > b.public_contributions) { 6 | return -1; 7 | } 8 | return 0; 9 | }; 10 | 11 | 12 | const check_username = (value) => { 13 | if (value === null) { 14 | return 'Null' 15 | } else { 16 | return value 17 | } 18 | }; 19 | 20 | const titleCase = (str) => { 21 | str = str.replace(/_/g, ' '); 22 | var splitStr = str.toLowerCase().split(' '); 23 | for (var i = 0; i < splitStr.length; i++) { 24 | splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); 25 | } 26 | return splitStr.join(' '); 27 | }; 28 | 29 | export { compare, check_username, titleCase }; 30 | -------------------------------------------------------------------------------- /client/src/util/HomeUtils.js: -------------------------------------------------------------------------------- 1 | const getCountry = (string) => { 2 | string = string.replace(/_/g, ' '); 3 | const splitStr = string.toLowerCase().split(' '); 4 | for (let i = 0; i < splitStr.length; i++) { 5 | splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); 6 | } 7 | return splitStr.join(' '); 8 | }; 9 | 10 | export { getCountry }; 11 | -------------------------------------------------------------------------------- /headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "Cache-Control": "no-cache, no-store, must-revalidate", 3 | "Pragma": "no-cache", 4 | "Expires": "0", 5 | "Content-Type":"image/svg+xml" 6 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "githubstats-com", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.8.7", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", 10 | "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", 11 | "requires": { 12 | "regenerator-runtime": "^0.13.4" 13 | }, 14 | "dependencies": { 15 | "regenerator-runtime": { 16 | "version": "0.13.4", 17 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz", 18 | "integrity": "sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==" 19 | } 20 | } 21 | }, 22 | "@emotion/hash": { 23 | "version": "0.7.4", 24 | "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.7.4.tgz", 25 | "integrity": "sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A==" 26 | }, 27 | "@material-ui/core": { 28 | "version": "4.9.5", 29 | "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.9.5.tgz", 30 | "integrity": "sha512-hVuUqw6847jcgRsUqzCiYCXcIJYhPUfM3gS9sNehTsbI0SF3tufLNO2B2Cgkuns8uOGy0nicD4p3L7JqhnEElg==", 31 | "requires": { 32 | "@babel/runtime": "^7.4.4", 33 | "@material-ui/styles": "^4.9.0", 34 | "@material-ui/system": "^4.9.3", 35 | "@material-ui/types": "^5.0.0", 36 | "@material-ui/utils": "^4.7.1", 37 | "@types/react-transition-group": "^4.2.0", 38 | "clsx": "^1.0.2", 39 | "hoist-non-react-statics": "^3.3.2", 40 | "popper.js": "^1.14.1", 41 | "prop-types": "^15.7.2", 42 | "react-is": "^16.8.0", 43 | "react-transition-group": "^4.3.0" 44 | } 45 | }, 46 | "@material-ui/icons": { 47 | "version": "4.9.1", 48 | "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.9.1.tgz", 49 | "integrity": "sha512-GBitL3oBWO0hzBhvA9KxqcowRUsA0qzwKkURyC8nppnC3fw54KPKZ+d4V1Eeg/UnDRSzDaI9nGCdel/eh9AQMg==", 50 | "requires": { 51 | "@babel/runtime": "^7.4.4" 52 | } 53 | }, 54 | "@material-ui/styles": { 55 | "version": "4.9.0", 56 | "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.9.0.tgz", 57 | "integrity": "sha512-nJHum4RqYBPWsjL/9JET8Z02FZ9gSizlg/7LWVFpIthNzpK6OQ5OSRR4T4x9/p+wK3t1qNn3b1uI4XpnZaPxOA==", 58 | "requires": { 59 | "@babel/runtime": "^7.4.4", 60 | "@emotion/hash": "^0.7.4", 61 | "@material-ui/types": "^5.0.0", 62 | "@material-ui/utils": "^4.7.1", 63 | "clsx": "^1.0.2", 64 | "csstype": "^2.5.2", 65 | "hoist-non-react-statics": "^3.2.1", 66 | "jss": "^10.0.3", 67 | "jss-plugin-camel-case": "^10.0.3", 68 | "jss-plugin-default-unit": "^10.0.3", 69 | "jss-plugin-global": "^10.0.3", 70 | "jss-plugin-nested": "^10.0.3", 71 | "jss-plugin-props-sort": "^10.0.3", 72 | "jss-plugin-rule-value-function": "^10.0.3", 73 | "jss-plugin-vendor-prefixer": "^10.0.3", 74 | "prop-types": "^15.7.2" 75 | } 76 | }, 77 | "@material-ui/system": { 78 | "version": "4.9.3", 79 | "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.9.3.tgz", 80 | "integrity": "sha512-DBGsTKYrLlFpHG8BUp0X6ZpvaOzef+GhSwn/8DwVTXUdHitphaPQoL9xucrI8X9MTBo//El+7nylko7lo7eJIw==", 81 | "requires": { 82 | "@babel/runtime": "^7.4.4", 83 | "@material-ui/utils": "^4.7.1", 84 | "prop-types": "^15.7.2" 85 | } 86 | }, 87 | "@material-ui/types": { 88 | "version": "5.0.0", 89 | "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.0.0.tgz", 90 | "integrity": "sha512-UeH2BuKkwDndtMSS0qgx1kCzSMw+ydtj0xx/XbFtxNSTlXydKwzs5gVW5ZKsFlAkwoOOQ9TIsyoCC8hq18tOwg==" 91 | }, 92 | "@material-ui/utils": { 93 | "version": "4.7.1", 94 | "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.7.1.tgz", 95 | "integrity": "sha512-+ux0SlLdlehvzCk2zdQ3KiS3/ylWvuo/JwAGhvb8dFVvwR21K28z0PU9OQW2PGogrMEdvX3miEI5tGxTwwWiwQ==", 96 | "requires": { 97 | "@babel/runtime": "^7.4.4", 98 | "prop-types": "^15.7.2", 99 | "react-is": "^16.8.0" 100 | } 101 | }, 102 | "@types/prop-types": { 103 | "version": "15.7.3", 104 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", 105 | "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" 106 | }, 107 | "@types/react": { 108 | "version": "16.9.23", 109 | "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.23.tgz", 110 | "integrity": "sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw==", 111 | "requires": { 112 | "@types/prop-types": "*", 113 | "csstype": "^2.2.0" 114 | } 115 | }, 116 | "@types/react-transition-group": { 117 | "version": "4.2.4", 118 | "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.4.tgz", 119 | "integrity": "sha512-8DMUaDqh0S70TjkqU0DxOu80tFUiiaS9rxkWip/nb7gtvAsbqOXm02UCmR8zdcjWujgeYPiPNTVpVpKzUDotwA==", 120 | "requires": { 121 | "@types/react": "*" 122 | } 123 | }, 124 | "accepts": { 125 | "version": "1.3.7", 126 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 127 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 128 | "requires": { 129 | "mime-types": "~2.1.24", 130 | "negotiator": "0.6.2" 131 | } 132 | }, 133 | "ansi-regex": { 134 | "version": "4.1.0", 135 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 136 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 137 | }, 138 | "ansi-styles": { 139 | "version": "3.2.1", 140 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 141 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 142 | "requires": { 143 | "color-convert": "^1.9.0" 144 | } 145 | }, 146 | "array-flatten": { 147 | "version": "1.1.1", 148 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 149 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 150 | }, 151 | "assert": { 152 | "version": "2.0.0", 153 | "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", 154 | "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", 155 | "requires": { 156 | "es6-object-assign": "^1.1.0", 157 | "is-nan": "^1.2.1", 158 | "object-is": "^1.0.1", 159 | "util": "^0.12.0" 160 | } 161 | }, 162 | "axios": { 163 | "version": "0.19.0", 164 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", 165 | "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", 166 | "requires": { 167 | "follow-redirects": "1.5.10", 168 | "is-buffer": "^2.0.2" 169 | } 170 | }, 171 | "babel-runtime": { 172 | "version": "6.26.0", 173 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 174 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 175 | "requires": { 176 | "core-js": "^2.4.0", 177 | "regenerator-runtime": "^0.11.0" 178 | } 179 | }, 180 | "body-parser": { 181 | "version": "1.19.0", 182 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 183 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 184 | "requires": { 185 | "bytes": "3.1.0", 186 | "content-type": "~1.0.4", 187 | "debug": "2.6.9", 188 | "depd": "~1.1.2", 189 | "http-errors": "1.7.2", 190 | "iconv-lite": "0.4.24", 191 | "on-finished": "~2.3.0", 192 | "qs": "6.7.0", 193 | "raw-body": "2.4.0", 194 | "type-is": "~1.6.17" 195 | }, 196 | "dependencies": { 197 | "debug": { 198 | "version": "2.6.9", 199 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 200 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 201 | "requires": { 202 | "ms": "2.0.0" 203 | } 204 | } 205 | } 206 | }, 207 | "bson": { 208 | "version": "1.1.3", 209 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz", 210 | "integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg==" 211 | }, 212 | "bytes": { 213 | "version": "3.1.0", 214 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 215 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 216 | }, 217 | "camelcase": { 218 | "version": "5.3.1", 219 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 220 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 221 | }, 222 | "chalk": { 223 | "version": "2.4.2", 224 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 225 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 226 | "requires": { 227 | "ansi-styles": "^3.2.1", 228 | "escape-string-regexp": "^1.0.5", 229 | "supports-color": "^5.3.0" 230 | }, 231 | "dependencies": { 232 | "supports-color": { 233 | "version": "5.5.0", 234 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 235 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 236 | "requires": { 237 | "has-flag": "^3.0.0" 238 | } 239 | } 240 | } 241 | }, 242 | "classnames": { 243 | "version": "2.2.6", 244 | "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", 245 | "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" 246 | }, 247 | "cliui": { 248 | "version": "5.0.0", 249 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 250 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 251 | "requires": { 252 | "string-width": "^3.1.0", 253 | "strip-ansi": "^5.2.0", 254 | "wrap-ansi": "^5.1.0" 255 | } 256 | }, 257 | "clsx": { 258 | "version": "1.1.0", 259 | "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", 260 | "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==" 261 | }, 262 | "color-convert": { 263 | "version": "1.9.3", 264 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 265 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 266 | "requires": { 267 | "color-name": "1.1.3" 268 | } 269 | }, 270 | "color-name": { 271 | "version": "1.1.3", 272 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 273 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 274 | }, 275 | "concurrently": { 276 | "version": "5.2.0", 277 | "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.2.0.tgz", 278 | "integrity": "sha512-XxcDbQ4/43d6CxR7+iV8IZXhur4KbmEJk1CetVMUqCy34z9l0DkszbY+/9wvmSnToTej0SYomc2WSRH+L0zVJw==", 279 | "requires": { 280 | "chalk": "^2.4.2", 281 | "date-fns": "^2.0.1", 282 | "lodash": "^4.17.15", 283 | "read-pkg": "^4.0.1", 284 | "rxjs": "^6.5.2", 285 | "spawn-command": "^0.0.2-1", 286 | "supports-color": "^6.1.0", 287 | "tree-kill": "^1.2.2", 288 | "yargs": "^13.3.0" 289 | } 290 | }, 291 | "content-disposition": { 292 | "version": "0.5.3", 293 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 294 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 295 | "requires": { 296 | "safe-buffer": "5.1.2" 297 | } 298 | }, 299 | "content-type": { 300 | "version": "1.0.4", 301 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 302 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 303 | }, 304 | "cookie": { 305 | "version": "0.4.0", 306 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 307 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 308 | }, 309 | "cookie-signature": { 310 | "version": "1.0.6", 311 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 312 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 313 | }, 314 | "core-js": { 315 | "version": "2.6.10", 316 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", 317 | "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" 318 | }, 319 | "css-vendor": { 320 | "version": "2.0.7", 321 | "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.7.tgz", 322 | "integrity": "sha512-VS9Rjt79+p7M0WkPqcAza4Yq1ZHrsHrwf7hPL/bjQB+c1lwmAI+1FXxYTYt818D/50fFVflw0XKleiBN5RITkg==", 323 | "requires": { 324 | "@babel/runtime": "^7.6.2", 325 | "is-in-browser": "^1.0.2" 326 | } 327 | }, 328 | "csstype": { 329 | "version": "2.6.9", 330 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", 331 | "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" 332 | }, 333 | "date-fns": { 334 | "version": "2.14.0", 335 | "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.14.0.tgz", 336 | "integrity": "sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw==" 337 | }, 338 | "debug": { 339 | "version": "3.1.0", 340 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 341 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 342 | "requires": { 343 | "ms": "2.0.0" 344 | } 345 | }, 346 | "decamelize": { 347 | "version": "1.2.0", 348 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 349 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 350 | }, 351 | "define-properties": { 352 | "version": "1.1.3", 353 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 354 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 355 | "requires": { 356 | "object-keys": "^1.0.12" 357 | } 358 | }, 359 | "depd": { 360 | "version": "1.1.2", 361 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 362 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 363 | }, 364 | "destroy": { 365 | "version": "1.0.4", 366 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 367 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 368 | }, 369 | "dom-helpers": { 370 | "version": "5.1.3", 371 | "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.3.tgz", 372 | "integrity": "sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw==", 373 | "requires": { 374 | "@babel/runtime": "^7.6.3", 375 | "csstype": "^2.6.7" 376 | } 377 | }, 378 | "ee-first": { 379 | "version": "1.1.1", 380 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 381 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 382 | }, 383 | "emoji-regex": { 384 | "version": "7.0.3", 385 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 386 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" 387 | }, 388 | "encodeurl": { 389 | "version": "1.0.2", 390 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 391 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 392 | }, 393 | "error-ex": { 394 | "version": "1.3.2", 395 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 396 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 397 | "requires": { 398 | "is-arrayish": "^0.2.1" 399 | } 400 | }, 401 | "es-abstract": { 402 | "version": "1.16.0", 403 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", 404 | "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", 405 | "requires": { 406 | "es-to-primitive": "^1.2.0", 407 | "function-bind": "^1.1.1", 408 | "has": "^1.0.3", 409 | "has-symbols": "^1.0.0", 410 | "is-callable": "^1.1.4", 411 | "is-regex": "^1.0.4", 412 | "object-inspect": "^1.6.0", 413 | "object-keys": "^1.1.1", 414 | "string.prototype.trimleft": "^2.1.0", 415 | "string.prototype.trimright": "^2.1.0" 416 | } 417 | }, 418 | "es-to-primitive": { 419 | "version": "1.2.1", 420 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 421 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 422 | "requires": { 423 | "is-callable": "^1.1.4", 424 | "is-date-object": "^1.0.1", 425 | "is-symbol": "^1.0.2" 426 | } 427 | }, 428 | "es6-object-assign": { 429 | "version": "1.1.0", 430 | "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", 431 | "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" 432 | }, 433 | "escape-html": { 434 | "version": "1.0.3", 435 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 436 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 437 | }, 438 | "escape-string-regexp": { 439 | "version": "1.0.5", 440 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 441 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 442 | }, 443 | "etag": { 444 | "version": "1.8.1", 445 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 446 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 447 | }, 448 | "express": { 449 | "version": "4.17.1", 450 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 451 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 452 | "requires": { 453 | "accepts": "~1.3.7", 454 | "array-flatten": "1.1.1", 455 | "body-parser": "1.19.0", 456 | "content-disposition": "0.5.3", 457 | "content-type": "~1.0.4", 458 | "cookie": "0.4.0", 459 | "cookie-signature": "1.0.6", 460 | "debug": "2.6.9", 461 | "depd": "~1.1.2", 462 | "encodeurl": "~1.0.2", 463 | "escape-html": "~1.0.3", 464 | "etag": "~1.8.1", 465 | "finalhandler": "~1.1.2", 466 | "fresh": "0.5.2", 467 | "merge-descriptors": "1.0.1", 468 | "methods": "~1.1.2", 469 | "on-finished": "~2.3.0", 470 | "parseurl": "~1.3.3", 471 | "path-to-regexp": "0.1.7", 472 | "proxy-addr": "~2.0.5", 473 | "qs": "6.7.0", 474 | "range-parser": "~1.2.1", 475 | "safe-buffer": "5.1.2", 476 | "send": "0.17.1", 477 | "serve-static": "1.14.1", 478 | "setprototypeof": "1.1.1", 479 | "statuses": "~1.5.0", 480 | "type-is": "~1.6.18", 481 | "utils-merge": "1.0.1", 482 | "vary": "~1.1.2" 483 | }, 484 | "dependencies": { 485 | "debug": { 486 | "version": "2.6.9", 487 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 488 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 489 | "requires": { 490 | "ms": "2.0.0" 491 | } 492 | } 493 | } 494 | }, 495 | "express-rate-limit": { 496 | "version": "5.0.0", 497 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.0.0.tgz", 498 | "integrity": "sha512-dhT57wqxfqmkOi4HM7NuT4Gd7gbUgSK2ocG27Y6lwm8lbOAw9XQfeANawGq8wLDtlGPO1ZgDj0HmKsykTxfFAg==" 499 | }, 500 | "finalhandler": { 501 | "version": "1.1.2", 502 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 503 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 504 | "requires": { 505 | "debug": "2.6.9", 506 | "encodeurl": "~1.0.2", 507 | "escape-html": "~1.0.3", 508 | "on-finished": "~2.3.0", 509 | "parseurl": "~1.3.3", 510 | "statuses": "~1.5.0", 511 | "unpipe": "~1.0.0" 512 | }, 513 | "dependencies": { 514 | "debug": { 515 | "version": "2.6.9", 516 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 517 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 518 | "requires": { 519 | "ms": "2.0.0" 520 | } 521 | } 522 | } 523 | }, 524 | "find-up": { 525 | "version": "3.0.0", 526 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 527 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 528 | "requires": { 529 | "locate-path": "^3.0.0" 530 | } 531 | }, 532 | "follow-redirects": { 533 | "version": "1.5.10", 534 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 535 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 536 | "requires": { 537 | "debug": "=3.1.0" 538 | } 539 | }, 540 | "forwarded": { 541 | "version": "0.1.2", 542 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 543 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 544 | }, 545 | "fresh": { 546 | "version": "0.5.2", 547 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 548 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 549 | }, 550 | "function-bind": { 551 | "version": "1.1.1", 552 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 553 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 554 | }, 555 | "get-caller-file": { 556 | "version": "2.0.5", 557 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 558 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 559 | }, 560 | "has": { 561 | "version": "1.0.3", 562 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 563 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 564 | "requires": { 565 | "function-bind": "^1.1.1" 566 | } 567 | }, 568 | "has-flag": { 569 | "version": "3.0.0", 570 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 571 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 572 | }, 573 | "has-symbols": { 574 | "version": "1.0.0", 575 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 576 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" 577 | }, 578 | "hoist-non-react-statics": { 579 | "version": "3.3.2", 580 | "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", 581 | "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", 582 | "requires": { 583 | "react-is": "^16.7.0" 584 | } 585 | }, 586 | "hosted-git-info": { 587 | "version": "2.8.8", 588 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", 589 | "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" 590 | }, 591 | "http-errors": { 592 | "version": "1.7.2", 593 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 594 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 595 | "requires": { 596 | "depd": "~1.1.2", 597 | "inherits": "2.0.3", 598 | "setprototypeof": "1.1.1", 599 | "statuses": ">= 1.5.0 < 2", 600 | "toidentifier": "1.0.0" 601 | } 602 | }, 603 | "hyphenate-style-name": { 604 | "version": "1.0.3", 605 | "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz", 606 | "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==" 607 | }, 608 | "iconv-lite": { 609 | "version": "0.4.24", 610 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 611 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 612 | "requires": { 613 | "safer-buffer": ">= 2.1.2 < 3" 614 | } 615 | }, 616 | "inherits": { 617 | "version": "2.0.3", 618 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 619 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 620 | }, 621 | "ipaddr.js": { 622 | "version": "1.9.0", 623 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 624 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 625 | }, 626 | "is-arguments": { 627 | "version": "1.0.4", 628 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", 629 | "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" 630 | }, 631 | "is-arrayish": { 632 | "version": "0.2.1", 633 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 634 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 635 | }, 636 | "is-buffer": { 637 | "version": "2.0.4", 638 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 639 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" 640 | }, 641 | "is-callable": { 642 | "version": "1.1.4", 643 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 644 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" 645 | }, 646 | "is-date-object": { 647 | "version": "1.0.1", 648 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 649 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" 650 | }, 651 | "is-fullwidth-code-point": { 652 | "version": "2.0.0", 653 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 654 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 655 | }, 656 | "is-generator-function": { 657 | "version": "1.0.7", 658 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", 659 | "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" 660 | }, 661 | "is-in-browser": { 662 | "version": "1.1.3", 663 | "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", 664 | "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" 665 | }, 666 | "is-nan": { 667 | "version": "1.2.1", 668 | "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", 669 | "integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", 670 | "requires": { 671 | "define-properties": "^1.1.1" 672 | } 673 | }, 674 | "is-regex": { 675 | "version": "1.0.4", 676 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 677 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 678 | "requires": { 679 | "has": "^1.0.1" 680 | } 681 | }, 682 | "is-symbol": { 683 | "version": "1.0.2", 684 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", 685 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", 686 | "requires": { 687 | "has-symbols": "^1.0.0" 688 | } 689 | }, 690 | "js-tokens": { 691 | "version": "4.0.0", 692 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 693 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 694 | }, 695 | "json-parse-better-errors": { 696 | "version": "1.0.2", 697 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 698 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" 699 | }, 700 | "jsonp": { 701 | "version": "0.2.1", 702 | "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", 703 | "integrity": "sha1-pltPoPEL2nGaBUQep7lMVfPhW64=", 704 | "requires": { 705 | "debug": "^2.1.3" 706 | }, 707 | "dependencies": { 708 | "debug": { 709 | "version": "2.6.9", 710 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 711 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 712 | "requires": { 713 | "ms": "2.0.0" 714 | } 715 | } 716 | } 717 | }, 718 | "jss": { 719 | "version": "10.0.4", 720 | "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.4.tgz", 721 | "integrity": "sha512-GqHmeDK83qbqMAVjxyPfN1qJVTKZne533a9bdCrllZukUM8npG/k+JumEPI86IIB5ifaZAHG2HAsUziyxOiooQ==", 722 | "requires": { 723 | "@babel/runtime": "^7.3.1", 724 | "csstype": "^2.6.5", 725 | "is-in-browser": "^1.1.3", 726 | "tiny-warning": "^1.0.2" 727 | } 728 | }, 729 | "jss-plugin-camel-case": { 730 | "version": "10.0.4", 731 | "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.4.tgz", 732 | "integrity": "sha512-+wnqxJsyfUnOn0LxVg3GgZBSjfBCrjxwx7LFxwVTUih0ceGaXKZoieheNOaTo5EM4w8bt1nbb8XonpQCj67C6A==", 733 | "requires": { 734 | "@babel/runtime": "^7.3.1", 735 | "hyphenate-style-name": "^1.0.3", 736 | "jss": "10.0.4" 737 | } 738 | }, 739 | "jss-plugin-default-unit": { 740 | "version": "10.0.4", 741 | "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.4.tgz", 742 | "integrity": "sha512-T0mhL/Ogp/quvod/jAHEqKvptLDxq7Cj3a+7zRuqK8HxUYkftptN89wJElZC3rshhNKiogkEYhCWenpJdFvTBg==", 743 | "requires": { 744 | "@babel/runtime": "^7.3.1", 745 | "jss": "10.0.4" 746 | } 747 | }, 748 | "jss-plugin-global": { 749 | "version": "10.0.4", 750 | "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.4.tgz", 751 | "integrity": "sha512-N8n9/GHENZce+sqE4UYiZiJtI+t+erT/BypHOrNYAfIoNEj7OYsOEKfIo2P0GpLB3QyDAYf5eo9XNdZ8veEkUA==", 752 | "requires": { 753 | "@babel/runtime": "^7.3.1", 754 | "jss": "10.0.4" 755 | } 756 | }, 757 | "jss-plugin-nested": { 758 | "version": "10.0.4", 759 | "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.4.tgz", 760 | "integrity": "sha512-QM21BKVt8LDeoRfowvAMh/s+/89VYrreIIE6ch4pvw0oAXDWw1iorUPlqLZ7uCO3UL0uFtQhJq3QMLN6Lr1v0A==", 761 | "requires": { 762 | "@babel/runtime": "^7.3.1", 763 | "jss": "10.0.4", 764 | "tiny-warning": "^1.0.2" 765 | } 766 | }, 767 | "jss-plugin-props-sort": { 768 | "version": "10.0.4", 769 | "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.4.tgz", 770 | "integrity": "sha512-WoETdOCjGskuin/OMt2uEdDPLZF3vfQuHXF+XUHGJrq0BAapoyGQDcv37SeReDlkRAbVXkEZPsIMvYrgHSHFiA==", 771 | "requires": { 772 | "@babel/runtime": "^7.3.1", 773 | "jss": "10.0.4" 774 | } 775 | }, 776 | "jss-plugin-rule-value-function": { 777 | "version": "10.0.4", 778 | "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.4.tgz", 779 | "integrity": "sha512-0hrzOSWRF5ABJGaHrlnHbYZjU877Ofzfh2id3uLtBvemGQLHI+ldoL8/+6iPSRa7M8z8Ngfg2vfYhKjUA5gA0g==", 780 | "requires": { 781 | "@babel/runtime": "^7.3.1", 782 | "jss": "10.0.4" 783 | } 784 | }, 785 | "jss-plugin-vendor-prefixer": { 786 | "version": "10.0.4", 787 | "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.4.tgz", 788 | "integrity": "sha512-4JgEbcrdeMda1qvxTm1CnxFJAWVV++VLpP46HNTrfH7VhVlvUpihnUNs2gAlKuRT/XSBuiWeLAkrTqF4NVrPig==", 789 | "requires": { 790 | "@babel/runtime": "^7.3.1", 791 | "css-vendor": "^2.0.7", 792 | "jss": "10.0.4" 793 | } 794 | }, 795 | "locate-path": { 796 | "version": "3.0.0", 797 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 798 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 799 | "requires": { 800 | "p-locate": "^3.0.0", 801 | "path-exists": "^3.0.0" 802 | } 803 | }, 804 | "lodash": { 805 | "version": "4.17.19", 806 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", 807 | "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" 808 | }, 809 | "loose-envify": { 810 | "version": "1.4.0", 811 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 812 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 813 | "requires": { 814 | "js-tokens": "^3.0.0 || ^4.0.0" 815 | } 816 | }, 817 | "media-typer": { 818 | "version": "0.3.0", 819 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 820 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 821 | }, 822 | "memory-pager": { 823 | "version": "1.5.0", 824 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 825 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 826 | "optional": true 827 | }, 828 | "merge-descriptors": { 829 | "version": "1.0.1", 830 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 831 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 832 | }, 833 | "methods": { 834 | "version": "1.1.2", 835 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 836 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 837 | }, 838 | "mime": { 839 | "version": "1.6.0", 840 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 841 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 842 | }, 843 | "mime-db": { 844 | "version": "1.40.0", 845 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 846 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 847 | }, 848 | "mime-types": { 849 | "version": "2.1.24", 850 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 851 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 852 | "requires": { 853 | "mime-db": "1.40.0" 854 | } 855 | }, 856 | "mongodb": { 857 | "version": "3.3.3", 858 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.3.tgz", 859 | "integrity": "sha512-MdRnoOjstmnrKJsK8PY0PjP6fyF/SBS4R8coxmhsfEU7tQ46/J6j+aSHF2n4c2/H8B+Hc/Klbfp8vggZfI0mmA==", 860 | "requires": { 861 | "bson": "^1.1.1", 862 | "require_optional": "^1.0.1", 863 | "safe-buffer": "^5.1.2", 864 | "saslprep": "^1.0.0" 865 | } 866 | }, 867 | "ms": { 868 | "version": "2.0.0", 869 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 870 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 871 | }, 872 | "negotiator": { 873 | "version": "0.6.2", 874 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 875 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 876 | }, 877 | "normalize-package-data": { 878 | "version": "2.5.0", 879 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 880 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 881 | "requires": { 882 | "hosted-git-info": "^2.1.4", 883 | "resolve": "^1.10.0", 884 | "semver": "2 || 3 || 4 || 5", 885 | "validate-npm-package-license": "^3.0.1" 886 | } 887 | }, 888 | "object-assign": { 889 | "version": "4.1.1", 890 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 891 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 892 | }, 893 | "object-inspect": { 894 | "version": "1.6.0", 895 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", 896 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" 897 | }, 898 | "object-is": { 899 | "version": "1.0.1", 900 | "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", 901 | "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=" 902 | }, 903 | "object-keys": { 904 | "version": "1.1.1", 905 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 906 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 907 | }, 908 | "object.entries": { 909 | "version": "1.1.0", 910 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", 911 | "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", 912 | "requires": { 913 | "define-properties": "^1.1.3", 914 | "es-abstract": "^1.12.0", 915 | "function-bind": "^1.1.1", 916 | "has": "^1.0.3" 917 | } 918 | }, 919 | "on-finished": { 920 | "version": "2.3.0", 921 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 922 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 923 | "requires": { 924 | "ee-first": "1.1.1" 925 | } 926 | }, 927 | "p-limit": { 928 | "version": "2.3.0", 929 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 930 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 931 | "requires": { 932 | "p-try": "^2.0.0" 933 | } 934 | }, 935 | "p-locate": { 936 | "version": "3.0.0", 937 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 938 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 939 | "requires": { 940 | "p-limit": "^2.0.0" 941 | } 942 | }, 943 | "p-try": { 944 | "version": "2.2.0", 945 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 946 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 947 | }, 948 | "parse-json": { 949 | "version": "4.0.0", 950 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 951 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 952 | "requires": { 953 | "error-ex": "^1.3.1", 954 | "json-parse-better-errors": "^1.0.1" 955 | } 956 | }, 957 | "parseurl": { 958 | "version": "1.3.3", 959 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 960 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 961 | }, 962 | "path-exists": { 963 | "version": "3.0.0", 964 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 965 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" 966 | }, 967 | "path-parse": { 968 | "version": "1.0.6", 969 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 970 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 971 | }, 972 | "path-to-regexp": { 973 | "version": "0.1.7", 974 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 975 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 976 | }, 977 | "pify": { 978 | "version": "3.0.0", 979 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 980 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" 981 | }, 982 | "popper.js": { 983 | "version": "1.16.1", 984 | "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", 985 | "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" 986 | }, 987 | "prop-types": { 988 | "version": "15.7.2", 989 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", 990 | "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", 991 | "requires": { 992 | "loose-envify": "^1.4.0", 993 | "object-assign": "^4.1.1", 994 | "react-is": "^16.8.1" 995 | } 996 | }, 997 | "proxy-addr": { 998 | "version": "2.0.5", 999 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 1000 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 1001 | "requires": { 1002 | "forwarded": "~0.1.2", 1003 | "ipaddr.js": "1.9.0" 1004 | } 1005 | }, 1006 | "qs": { 1007 | "version": "6.7.0", 1008 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1009 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1010 | }, 1011 | "range-parser": { 1012 | "version": "1.2.1", 1013 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1014 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1015 | }, 1016 | "raw-body": { 1017 | "version": "2.4.0", 1018 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1019 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1020 | "requires": { 1021 | "bytes": "3.1.0", 1022 | "http-errors": "1.7.2", 1023 | "iconv-lite": "0.4.24", 1024 | "unpipe": "1.0.0" 1025 | } 1026 | }, 1027 | "react-is": { 1028 | "version": "16.10.2", 1029 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.10.2.tgz", 1030 | "integrity": "sha512-INBT1QEgtcCCgvccr5/86CfD71fw9EPmDxgiJX4I2Ddr6ZsV6iFXsuby+qWJPtmNuMY0zByTsG4468P7nHuNWA==" 1031 | }, 1032 | "react-share": { 1033 | "version": "3.0.1", 1034 | "resolved": "https://registry.npmjs.org/react-share/-/react-share-3.0.1.tgz", 1035 | "integrity": "sha512-xo4zjYP78h6zrBN5rlC06bb877js7216KFeZELAZP6sYxVoqmU27ChrfnpKUCL9H8F5PwYXh6DLNdAp+0E17GA==", 1036 | "requires": { 1037 | "babel-runtime": "^6.26.0", 1038 | "classnames": "^2.2.5", 1039 | "jsonp": "^0.2.1", 1040 | "prop-types": "^15.5.8" 1041 | } 1042 | }, 1043 | "react-transition-group": { 1044 | "version": "4.3.0", 1045 | "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz", 1046 | "integrity": "sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==", 1047 | "requires": { 1048 | "@babel/runtime": "^7.5.5", 1049 | "dom-helpers": "^5.0.1", 1050 | "loose-envify": "^1.4.0", 1051 | "prop-types": "^15.6.2" 1052 | } 1053 | }, 1054 | "read-pkg": { 1055 | "version": "4.0.1", 1056 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", 1057 | "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", 1058 | "requires": { 1059 | "normalize-package-data": "^2.3.2", 1060 | "parse-json": "^4.0.0", 1061 | "pify": "^3.0.0" 1062 | } 1063 | }, 1064 | "regenerator-runtime": { 1065 | "version": "0.11.1", 1066 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 1067 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 1068 | }, 1069 | "require-directory": { 1070 | "version": "2.1.1", 1071 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1072 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 1073 | }, 1074 | "require-main-filename": { 1075 | "version": "2.0.0", 1076 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1077 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 1078 | }, 1079 | "require_optional": { 1080 | "version": "1.0.1", 1081 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 1082 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 1083 | "requires": { 1084 | "resolve-from": "^2.0.0", 1085 | "semver": "^5.1.0" 1086 | } 1087 | }, 1088 | "resolve": { 1089 | "version": "1.17.0", 1090 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 1091 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 1092 | "requires": { 1093 | "path-parse": "^1.0.6" 1094 | } 1095 | }, 1096 | "resolve-from": { 1097 | "version": "2.0.0", 1098 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1099 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 1100 | }, 1101 | "rxjs": { 1102 | "version": "6.6.0", 1103 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.0.tgz", 1104 | "integrity": "sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==", 1105 | "requires": { 1106 | "tslib": "^1.9.0" 1107 | } 1108 | }, 1109 | "safe-buffer": { 1110 | "version": "5.1.2", 1111 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1112 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1113 | }, 1114 | "safer-buffer": { 1115 | "version": "2.1.2", 1116 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1117 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1118 | }, 1119 | "saslprep": { 1120 | "version": "1.0.3", 1121 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 1122 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 1123 | "optional": true, 1124 | "requires": { 1125 | "sparse-bitfield": "^3.0.3" 1126 | } 1127 | }, 1128 | "semver": { 1129 | "version": "5.7.1", 1130 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1131 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1132 | }, 1133 | "send": { 1134 | "version": "0.17.1", 1135 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1136 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1137 | "requires": { 1138 | "debug": "2.6.9", 1139 | "depd": "~1.1.2", 1140 | "destroy": "~1.0.4", 1141 | "encodeurl": "~1.0.2", 1142 | "escape-html": "~1.0.3", 1143 | "etag": "~1.8.1", 1144 | "fresh": "0.5.2", 1145 | "http-errors": "~1.7.2", 1146 | "mime": "1.6.0", 1147 | "ms": "2.1.1", 1148 | "on-finished": "~2.3.0", 1149 | "range-parser": "~1.2.1", 1150 | "statuses": "~1.5.0" 1151 | }, 1152 | "dependencies": { 1153 | "debug": { 1154 | "version": "2.6.9", 1155 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1156 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1157 | "requires": { 1158 | "ms": "2.0.0" 1159 | }, 1160 | "dependencies": { 1161 | "ms": { 1162 | "version": "2.0.0", 1163 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1164 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1165 | } 1166 | } 1167 | }, 1168 | "ms": { 1169 | "version": "2.1.1", 1170 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1171 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1172 | } 1173 | } 1174 | }, 1175 | "serve-static": { 1176 | "version": "1.14.1", 1177 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1178 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1179 | "requires": { 1180 | "encodeurl": "~1.0.2", 1181 | "escape-html": "~1.0.3", 1182 | "parseurl": "~1.3.3", 1183 | "send": "0.17.1" 1184 | } 1185 | }, 1186 | "set-blocking": { 1187 | "version": "2.0.0", 1188 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1189 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 1190 | }, 1191 | "setprototypeof": { 1192 | "version": "1.1.1", 1193 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1194 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1195 | }, 1196 | "sparse-bitfield": { 1197 | "version": "3.0.3", 1198 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1199 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", 1200 | "optional": true, 1201 | "requires": { 1202 | "memory-pager": "^1.0.2" 1203 | } 1204 | }, 1205 | "spawn-command": { 1206 | "version": "0.0.2-1", 1207 | "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", 1208 | "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=" 1209 | }, 1210 | "spdx-correct": { 1211 | "version": "3.1.1", 1212 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 1213 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 1214 | "requires": { 1215 | "spdx-expression-parse": "^3.0.0", 1216 | "spdx-license-ids": "^3.0.0" 1217 | } 1218 | }, 1219 | "spdx-exceptions": { 1220 | "version": "2.3.0", 1221 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 1222 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" 1223 | }, 1224 | "spdx-expression-parse": { 1225 | "version": "3.0.1", 1226 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 1227 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 1228 | "requires": { 1229 | "spdx-exceptions": "^2.1.0", 1230 | "spdx-license-ids": "^3.0.0" 1231 | } 1232 | }, 1233 | "spdx-license-ids": { 1234 | "version": "3.0.5", 1235 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 1236 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" 1237 | }, 1238 | "statuses": { 1239 | "version": "1.5.0", 1240 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1241 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1242 | }, 1243 | "string-width": { 1244 | "version": "3.1.0", 1245 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1246 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1247 | "requires": { 1248 | "emoji-regex": "^7.0.1", 1249 | "is-fullwidth-code-point": "^2.0.0", 1250 | "strip-ansi": "^5.1.0" 1251 | } 1252 | }, 1253 | "string.prototype.trimleft": { 1254 | "version": "2.1.0", 1255 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", 1256 | "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", 1257 | "requires": { 1258 | "define-properties": "^1.1.3", 1259 | "function-bind": "^1.1.1" 1260 | } 1261 | }, 1262 | "string.prototype.trimright": { 1263 | "version": "2.1.0", 1264 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", 1265 | "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", 1266 | "requires": { 1267 | "define-properties": "^1.1.3", 1268 | "function-bind": "^1.1.1" 1269 | } 1270 | }, 1271 | "strip-ansi": { 1272 | "version": "5.2.0", 1273 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1274 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1275 | "requires": { 1276 | "ansi-regex": "^4.1.0" 1277 | } 1278 | }, 1279 | "supports-color": { 1280 | "version": "6.1.0", 1281 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", 1282 | "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", 1283 | "requires": { 1284 | "has-flag": "^3.0.0" 1285 | } 1286 | }, 1287 | "tiny-warning": { 1288 | "version": "1.0.3", 1289 | "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", 1290 | "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" 1291 | }, 1292 | "toidentifier": { 1293 | "version": "1.0.0", 1294 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1295 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1296 | }, 1297 | "tree-kill": { 1298 | "version": "1.2.2", 1299 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 1300 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" 1301 | }, 1302 | "tslib": { 1303 | "version": "1.13.0", 1304 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", 1305 | "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" 1306 | }, 1307 | "type-is": { 1308 | "version": "1.6.18", 1309 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1310 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1311 | "requires": { 1312 | "media-typer": "0.3.0", 1313 | "mime-types": "~2.1.24" 1314 | } 1315 | }, 1316 | "unpipe": { 1317 | "version": "1.0.0", 1318 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1319 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1320 | }, 1321 | "util": { 1322 | "version": "0.12.1", 1323 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz", 1324 | "integrity": "sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==", 1325 | "requires": { 1326 | "inherits": "^2.0.3", 1327 | "is-arguments": "^1.0.4", 1328 | "is-generator-function": "^1.0.7", 1329 | "object.entries": "^1.1.0", 1330 | "safe-buffer": "^5.1.2" 1331 | } 1332 | }, 1333 | "utils-merge": { 1334 | "version": "1.0.1", 1335 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1336 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1337 | }, 1338 | "validate-npm-package-license": { 1339 | "version": "3.0.4", 1340 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1341 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1342 | "requires": { 1343 | "spdx-correct": "^3.0.0", 1344 | "spdx-expression-parse": "^3.0.0" 1345 | } 1346 | }, 1347 | "vary": { 1348 | "version": "1.1.2", 1349 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1350 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1351 | }, 1352 | "which-module": { 1353 | "version": "2.0.0", 1354 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1355 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 1356 | }, 1357 | "wrap-ansi": { 1358 | "version": "5.1.0", 1359 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 1360 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 1361 | "requires": { 1362 | "ansi-styles": "^3.2.0", 1363 | "string-width": "^3.0.0", 1364 | "strip-ansi": "^5.0.0" 1365 | } 1366 | }, 1367 | "y18n": { 1368 | "version": "4.0.0", 1369 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1370 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" 1371 | }, 1372 | "yargs": { 1373 | "version": "13.3.2", 1374 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1375 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1376 | "requires": { 1377 | "cliui": "^5.0.0", 1378 | "find-up": "^3.0.0", 1379 | "get-caller-file": "^2.0.1", 1380 | "require-directory": "^2.1.1", 1381 | "require-main-filename": "^2.0.0", 1382 | "set-blocking": "^2.0.0", 1383 | "string-width": "^3.0.0", 1384 | "which-module": "^2.0.0", 1385 | "y18n": "^4.0.0", 1386 | "yargs-parser": "^13.1.2" 1387 | } 1388 | }, 1389 | "yargs-parser": { 1390 | "version": "13.1.2", 1391 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1392 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1393 | "requires": { 1394 | "camelcase": "^5.0.0", 1395 | "decamelize": "^1.2.0" 1396 | } 1397 | } 1398 | } 1399 | } 1400 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "githubstats-com", 3 | "version": "1.0.0", 4 | "description": "List of most active users by country using GitHub", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "heroku-postbuild": "cd client && npm install && npm run build" 9 | }, 10 | "keywords": [ 11 | "github", 12 | "countries", 13 | "githubstats", 14 | "github-users" 15 | ], 16 | "author": { 17 | "name": "Gayan Kuruppu", 18 | "email": "kuruppu.gayan@gmail.com", 19 | "url": "https://gayan.surge.sh/" 20 | }, 21 | "contributors": [ 22 | { 23 | "name": "Srdjan Rakic", 24 | "email": "srgjan.rakic@gmail.com", 25 | "url": "https://github.com/srdjanRakic" 26 | }, 27 | { 28 | "name": "Nikola Lukovic", 29 | "email": "nikola.lukovic@live.com", 30 | "url": "https://github.com/nikolalukovic" 31 | }, 32 | { 33 | "name": "Donghoon Song", 34 | "url": "https://github.com/Donghoon759" 35 | }, 36 | { 37 | "name": "EL HOUCINE AOUASSAR", 38 | "email": "elhd.me@gmail.com", 39 | "url": "https://github.com/AWIXOR" 40 | }, 41 | { 42 | "name": "ronaldaug", 43 | "url": "https://github.com/ronaldaug" 44 | }, 45 | { 46 | "name": "Adem Kouki", 47 | "email": "ademkingnew@gmail.com", 48 | "url": "https://github.com/Ademking" 49 | }, 50 | { 51 | "name": "Shivay Lamba", 52 | "email": "shivaylamba@gmail.com", 53 | "url": "https://github.com/shivaylamba" 54 | }, 55 | { 56 | "name": "Imed Jaberi", 57 | "email": "imed_jebari@hotmail.fr", 58 | "url": "https://github.com/3imed-jaberi" 59 | }, 60 | { 61 | "name": "Habiyaremye Ntwali Janvier", 62 | "email": "janvierntwali@gmail.com", 63 | "url": "https://github.com/RedJanvier" 64 | } 65 | ], 66 | "license": "MIT", 67 | "dependencies": { 68 | "@material-ui/core": "^4.9.5", 69 | "@material-ui/icons": "^4.9.1", 70 | "assert": "^2.0.0", 71 | "axios": "^0.19.0", 72 | "body-parser": "^1.19.0", 73 | "concurrently": "^5.2.0", 74 | "express": "^4.17.1", 75 | "express-rate-limit": "^5.0.0", 76 | "mongodb": "^3.3.3", 77 | "react-share": "^3.0.1" 78 | }, 79 | "engines": { 80 | "node": ">= 8" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const GraphQuery = require('./GraphQuery'); 3 | var mongo = require('mongodb').MongoClient; 4 | const assert = require('assert'); 5 | const path = require('path'); 6 | const http = require("http"); 7 | const RateLimit = require('express-rate-limit'); 8 | const fs = require('fs'); 9 | const template = fs.readFileSync(path.resolve('temp.svg'), 'utf8'); 10 | const HEAD = require('./headers'); // stackoverflow.com/a/2068407/1148249 11 | 12 | // mongo auth 13 | const keys = ['', ' ']; 14 | const url = "mongodb+srv://:@cluster0-vdt7y.mongodb.net/test?retryWrites=true&w=majority"; 15 | const records = [10, 100]; 16 | 17 | const country = [ 18 | {city: ["Albania", "Tirana", "durres", "vlore", "Elbasan", "Shkoder"]}, 19 | {city: ["Algeria", "Algiers"]}, 20 | {city: ["Argentina", "BuenosAires", "Cordoba", "Rosario", "Mendoza", "Tucuman"]}, 21 | {city: ["Australia", "Sydney", "Melbourne", "Brisbane", "Perth", "Adelaide", "Canberra"]}, 22 | {city: ["Austria", "Vienna", "Wien", "Linz", "Salzburg", "Graz", "Innsbruck"]}, 23 | {city: ["Azerbaijan", "Baku"]}, 24 | {city: ["Bangladesh", "Dhaka", "Chittagong", "Khulna", "Rajshahi", "Barisal"]}, 25 | {city: ["Belgium", "Antwerp", "Ghent", "Charleroi", "Liege", "Brussels", "Belgique"]}, 26 | {city: ["Brazil", "Brasil", "SaoPaulo", "Salvador", "Fortaleza", "Recife"]}, 27 | {city: ["Bulgaria", "Sofia", "Plovdiv", "Varna", "Burgas", "Ruse", "Veliko Tarnovo"]}, 28 | {city: ["Canada", "Ottawa", "Winnipeg", "Vancouver", "Toronto", "Quebec"]}, 29 | {city: ["China", "Chengdu", "Shenzen", "Tianjin", "Guangzhou", "Shanghai", "Beijing", "Hangzhou"]}, 30 | {city: ["Croatia", "Hrvatska", "Zagreb", "Split", "Rijeka", "Osijek", "Zadar", "Pula"]}, 31 | {city: ["Czech_Republic", "CzechRepublic", "Czechia", "Prague", "Brno", "Olomouc", "Plzeň", "Ostrava", "Liberec"]}, 32 | {city: ["Denmark", "Copenhagen", "Aarhus", "Odense", "Aalborg"]}, 33 | {city: ["Estonia", "Eesti", "Tallinn", "Tartu", "Narva"]}, 34 | {city: ["Finland", "Suomi", "Helsinki", "Tampere", "Oulu", "Espoo", "Vantaa", "Turku"]}, 35 | {city: ["France", "Paris", "Marseille", "Lyon", "Toulouse", "Nice", "Lille"]}, 36 | {city: ["Germany", "Berlin", "Frankfurt", "Munich", "Hamburg", "Cologne"]}, 37 | {city: ["Greece", "Athens", "Thessaloniki", "Patras", "Heraklion", "Larissa", "Crete"]}, 38 | {city: ["Hong_Kong", "HongKong", "Hong+Kong", "Kowloon"]}, 39 | {city: ["India", "Bangalore", "Mumbai", "Delhi", "Kolkata", "Chennai"]}, 40 | {city: ["Indonesia", "Jakarta", "Surabaya", "Bandung", "Medan"]}, 41 | {city: ["Ireland", "Dublin", "Galway", "Cork", "Limerick", "Belfast", "Waterford", "Londonderry", "Drogheda"]}, 42 | {city: ["Israel", "TelAviv", "Jerusalem", "Beersheva", "Netanya", "Haifa", "Herzliya", "Rishon"]}, 43 | {city: ["Italy", "Italia", "Rome", "Milan", "Naples", "Napoli", "Turin", "Torino", "Palermo", "Genoa", "Genova", "Bologna", "Florence", "Firenze", "Bari", "Catania", "Venice", "Verona"]}, 44 | {city: ["Japan", "Tokyo", "Yokohama", "Osaka", "Nagoya", "Kyoto", "Hiroshima"]}, 45 | {city: ["Latvia", "Latvija", "Riga", "Kuldiga", "Ventspils", "Liepaja"]}, 46 | {city: ["Luxembourg", "Eifferdange", "Dudelange", "Ettelbruck"]}, 47 | {city: ["Macedonia", "Skopje", "Veles", "Ohrid", "Bitola", "Kumanovo", "Strumica", "Tetovo", "Gostivar", "Struga", "Kichevo", "Kavadarci", "Berovo"]}, 48 | {city: ["Malaysia", "KualaLumpur", "Kajang", "Klang", "Subang", "Penang", "Johor"]}, 49 | {city: ["Mexico", "Guadalajara", "Puebla", "Tijuana", "Mexicali", "Monterrey", "Hermosillo"]}, 50 | {city: ["Mongolia", "Mongolia", "Ulaanbaatar", "Erdenet", "Darkhan", "Choibalsan"]}, 51 | {city: ["Morocco", "Morocco", "Casablanca", "Rabat", "Marrakesh", "Agadir"]}, 52 | {city: ["Myanmar", "Yangon", "Mandalay", "Taunggyi"]}, 53 | {city: ["Nepal", "Kathmandu", "Pokhara", "Lalitpur", "Bhaktapur", "Birgunj"]}, 54 | {city: ["Netherlands", "Amsterdam", "Rotterdam", "Hague", "Utrecht", "Holland", "Delft"]}, 55 | {city: ["New_Zealand", "NewZealand", "Auckland", "Wellington", "ChristChurch", "Hamilton", "Tauranga", "Dunedin", "Rotorua"]}, 56 | {city: ["Norway", "Norge", "Oslo", "Bergen"]}, 57 | {city: ["Nigeria", "Lagos", "Abuja", "Ondo", "Oyo", "Ogun"]}, 58 | {city: ["Pakistan", "Karachi", "Lahore", "Faisalabad", "Rawalpindi", "Islamabad"]}, 59 | {city: ["Philippines", "Quezon", "Manila", "Davao", "Caloocan", "Cebu"]}, 60 | {city: ["Poland", "warsaw", "Kraków", "Wrocław", "Gdańsk", "Poznań", "Katowice", "Łódź", "Lublin"]}, 61 | {city: ["Portugal", "Lisbon", "Lisboa", "Braga", "Madeira"]}, 62 | {city: ["Romania", "Bucharest", "Cluj", "Iasi", "Timisoara", "Craiova"]}, 63 | {city: ["Russia", "Moscow", "SaintPetersburg", "Novosibirsk", "Yekaterinburg", "Omsk", "Kazan", "Volgograd"]}, 64 | {city: ["Rwanda", "Kigali"]}, 65 | {city: ["Serbia", "Srbija", "Србија", "Beograd", "NoviSad", "Nis", "Niš", "Kragujevac", "Užice", "Čačak", "Београд", "НовиСад", "Ниш", "Крагујевац", "Ужице", "Чачак"]}, 66 | {city: ["Singapore"]}, 67 | {city: ["South_Korea", "SouthKorea", "Korea", "Seoul", "Busan", "Incheon", "Daegu", "Gwangju", "Suwon", "Ulsan", "Daejeon", "Changwon", "Goyang-si", "Hwaseong", "Bucheon", "Cheongju"]}, 68 | {city: ["Spain", "Madrid", "Barcelona", "Valencia", "Seville", "Sevilla", "Zaragoza", "Malaga"]}, 69 | {city: ["Sri_Lanka", "SriLanka", "Colombo", "Kandy", "Gampaha", "Galle", "Jaffna", "Matara"]}, 70 | {city: ["Sweden", "Sverige", "Stockholm", "Malmo", "Uppsala", "Guteborg", "Gothenburg"]}, 71 | {city: ["Taiwan", "Taipei"]}, 72 | {city: ["Thailand", "bangkok", "Nonthaburi", "Nakhon", "Phuket", "Pattaya"]}, 73 | {city: ["Tunisia", "Tunis"]}, 74 | {city: ["Ukraine", "Kiev", "Kyiv", "Kharkiv", "Dnipro", "Odesa", "Donetsk", "Zaporizhia"]}, 75 | {city: ["United_Arab_Emirates", "UnitedArabEmirates", "UAE", "AbuDhabi", "Dubai", "Sharjah", "Ajman", "Fujairah"]}, 76 | {city: ["United_Kingdom", "UnitedKingdom", "London", "Birmingham", "Glasgow"]}, 77 | {city: ["United_States", "UnitedStates", "USA", "PaloAlto", "NewYork", "California", "Missouri", "SanFrancisco", "SaintLouis"]}, 78 | {city: ["Vietnam", "HoChiMinh", "Hanoi", "Saigon", "DaNang", "NhaTrang", "HaiPhong"]}, 79 | {city: ["Yemen", "Sana'a"]}, 80 | ]; 81 | let start = true; 82 | const app = express(); 83 | 84 | const limiter = new RateLimit({ 85 | windowMs: 60 * 1000, // 1 minute 86 | max: 15 87 | }); 88 | 89 | 90 | // app keep alive 91 | setInterval(function () { 92 | http.get("http://githubstats-com.herokuapp.com/home"); 93 | process.stdout.write('.'); 94 | }, 300000); 95 | 96 | app.get('/admin/start', (req, res) => { 97 | try { 98 | if (start) { 99 | start = false; 100 | (async () => { 101 | var delay = 5000, increment = 0, key = keys[0]; 102 | // Rate limit https://developer.github.com/v4/guides/resource-limitations/ 103 | 104 | const fx = ({city}) => 105 | new Promise(resolve => setTimeout(resolve, delay, city)).then(data => 106 | new GraphQuery(data, key, records, url).request()); 107 | 108 | for (let {city} of country) { 109 | await fx({city}); 110 | if (increment < (country.length / 2)) { 111 | key = keys[0]; 112 | 113 | } else { 114 | key = keys[1]; 115 | } 116 | increment = increment + 1; 117 | delay = 600000; 118 | } 119 | start = true; 120 | })(); 121 | res.send('true'); 122 | } else { 123 | res.send('false'); 124 | } 125 | 126 | //res.send('server.js STARTED REFRESH'); 127 | //console.log("server.js STARTED REFRESH"); 128 | } catch (e) { 129 | res.send("error"); 130 | } 131 | }); 132 | 133 | 134 | app.get('/contributions/:country', (req, res) => { 135 | try { 136 | var filter = req.params.country; 137 | console.log(filter); 138 | if (filter === 'all') { 139 | res.send(country); 140 | } else { 141 | mongo.connect(url, {useUnifiedTopology: true}, function (err, client) { 142 | assert.equal(null, err); 143 | const collection = client.db("database").collection("countries"); 144 | collection.find({ 145 | "country": {$regex: filter} 146 | }).toArray(function (error, doc) { 147 | res.send(doc); 148 | }); 149 | client.close(); 150 | }); 151 | } 152 | } catch (e) { 153 | console.log(e); 154 | // res.send(e.toString()); 155 | } 156 | }); 157 | 158 | app.get('/get/:user/:repository', (req, res) => { 159 | try { 160 | const user = req.params.user; 161 | const repository = req.params.repository; 162 | 163 | mongo.connect(url, {useUnifiedTopology: true}, function (err, client) { 164 | assert.equal(null, err); 165 | const collection = client.db("database").collection("repositories"); 166 | collection.findOneAndUpdate( 167 | { 168 | "user": user, 169 | "repository": repository 170 | }, 171 | { "$inc": { data : 1 }}, 172 | { new: true, setDefaultsOnInsert: true }, 173 | function(err, userUpdate) { 174 | if (err) { 175 | res.send("error"); 176 | } else if (typeof userUpdate == null) { 177 | res.send("null"); 178 | } else if (typeof userUpdate != null) { 179 | if( userUpdate.value.data === undefined){ 180 | res.writeHead(200, HEAD); 181 | res.end(makeSvg(0)); 182 | } else { 183 | res.writeHead(200, HEAD); 184 | res.end(makeSvg(userUpdate.value.data)); 185 | } 186 | 187 | 188 | 189 | 190 | // 191 | // res.send(userUpdate.value); 192 | } 193 | } 194 | ); 195 | client.close(); 196 | }); 197 | } catch (e) { 198 | console.log(e); 199 | } 200 | }); 201 | 202 | const makeSvg = (count) => { 203 | return template.replace('{count}', count); 204 | }; 205 | 206 | app.get('/set/:user/:repository', (req, res) => { 207 | try { 208 | const user = req.params.user; 209 | const repository = req.params.repository; 210 | console.log(user, repository); 211 | const data = { 212 | user: user, 213 | repository: repository, 214 | }; 215 | const response = { 216 | status: true 217 | }; 218 | mongo.connect(url, {useUnifiedTopology: true}, function (err, client, upserted) { 219 | assert.equal(null, err); 220 | const collection = client.db("database").collection("repositories"); 221 | collection.updateOne( 222 | {user: user, repository: repository}, 223 | {$set: data}, 224 | {upsert: true}) 225 | .then(function () { 226 | res.send(response); 227 | }); 228 | client.close(); 229 | }); 230 | 231 | } catch (e) { 232 | console.log(e); 233 | } 234 | }); 235 | 236 | 237 | app.use(limiter, express.static(path.join(__dirname, 'client/build'))); 238 | app.get('*', function (req, res) { 239 | try { 240 | res.sendFile(path.join(__dirname, 'client/build', 'index.html')); 241 | } catch (e) { 242 | console.log(e); 243 | } 244 | 245 | }); 246 | const API_PORT = process.env.PORT || 4000; 247 | app.listen(API_PORT, () => console.log(`PORT ${API_PORT}`)); 248 | -------------------------------------------------------------------------------- /temp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | background 14 | 15 | 16 | 17 | Layer 1 18 | 19 | 20 | 21 | 22 | 23 | 24 | stats 25 | {count} 26 | 27 | 28 | -------------------------------------------------------------------------------- /template.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | stats 11 | {count} 12 | 13 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | module.exports = { 3 | check_file: function (path) { 4 | try { 5 | if (fs.existsSync(path)) { 6 | //console.log('exists'); 7 | } else { 8 | //console.log('does not exist'); 9 | } 10 | } catch (err) { 11 | //console.error(err) 12 | } 13 | }, 14 | 15 | getDateTime: function () { 16 | return date = new Date(); 17 | 18 | }, 19 | 20 | parse: function (str) { 21 | var args = [].slice.call(arguments, 1), 22 | i = 0; 23 | return str.replace(/%s/g, () => args[i++]); 24 | }, 25 | 26 | locations: function (array) { 27 | var value = ''; 28 | array.forEach(function (entry) { 29 | value = value + ' location:' + entry; 30 | }); 31 | return value; 32 | } 33 | 34 | 35 | }; 36 | --------------------------------------------------------------------------------