diff --git a/common/store.js b/common/store.js index c3780096..cdb8c961 100644 --- a/common/store.js +++ b/common/store.js @@ -5,8 +5,8 @@ import data from '../build/data.json'; const topics = {}; const all = [...data.incompatible, ...data.expo]; -all.forEach(repo => { - repo.topics.forEach(topic => { +all.forEach(project => { + project.github.topics.forEach(topic => { if (!topics[topic]) { topics[topic] = 1; return; diff --git a/components/List.js b/components/List.js index 313f85af..6238aa74 100644 --- a/components/List.js +++ b/components/List.js @@ -186,22 +186,22 @@ export default class List extends React.PureComponent { } else { elements = this.props.data.map(item => { return renderItem({ - name: item.name, + name: item.github.name, column1: { top: ( - - {item.name} + + {item.github.name} ), - bottom: item.urls.homepage - ? + bottom: item.github.urls.homepage + ? homepage : undefined, }, column2: { - top: item.description, - bottom: item.topics.map(each => + top: item.github.description, + bottom: item.github.topics.map(each => @@ -210,8 +210,8 @@ export default class List extends React.PureComponent { ), }, column3: { - top: getTimeSinceToday(item.stats.pushedAt), - bottom: `${item.score}/100 — ${item.stats.stars} stars`, + top: getTimeSinceToday(item.github.stats.pushedAt), + bottom: `${item.score}/100 — ${item.github.stats.stars} stars`, }, }); }); diff --git a/debug-github-repos.json b/debug-github-repos.json index 62272c90..2d22ab59 100644 --- a/debug-github-repos.json +++ b/debug-github-repos.json @@ -1,10 +1,9 @@ -{ - "expo": [ - {"github": "https://github.com/expo/react-native-action-sheet", "pkg": "@expo/react-native-action-sheet"}, - "https://github.com/react-community/react-navigation", - "https://github.com/gre/gl-react" - ], - "incompatible": [ - "https://github.com/PeelTechnologies/react-native-tcp" - ] -} +[ + { + "githubUrl": "https://github.com/react-community/react-navigation", + "expo": true + }, + { "githubUrl": "https://github.com/gre/gl-react", "expo": true }, + { "githubUrl": "https://github.com/n4kz/react-native-pages", "expo": true }, + { "githubUrl": "https://github.com/airbnb/lottie-react-native", "expo": true } +] \ No newline at end of file diff --git a/github-repos.json b/github-repos.json index 02e1502b..ebe73b9c 100644 --- a/github-repos.json +++ b/github-repos.json @@ -1,42 +1,90 @@ -{ - "expo": [ - "https://github.com/react-community/react-navigation", - "https://github.com/gre/gl-react", - "https://github.com/n4kz/react-native-pages", - "https://github.com/airbnb/lottie-react-native", - "https://github.com/airbnb/react-native-maps", - "https://github.com/oblador/react-native-animatable", - "https://github.com/wix/react-native-calendars", - "https://github.com/oblador/react-native-vector-icons", - "https://github.com/idibidiart/react-native-responsive-grid", - "https://github.com/24ark/react-native-step-indicator", - "https://github.com/jacklam718/react-native-popup-dialog", - "https://github.com/react-native-community/react-native-drawer-layout", - "https://github.com/n4kz/react-native-material-textfield", - "https://github.com/maxs15/react-native-modalbox", - "https://github.com/react-native-community/react-native-modal", - "https://github.com/react-native-training/react-native-elements", - "https://github.com/FaridSafi/react-native-gifted-chat", - "https://github.com/react-native-community/react-native-tab-view", - "https://github.com/bgryszko/react-native-circular-slider", - "https://github.com/archriss/react-native-snap-carousel", - "https://github.com/mmazzarolo/react-native-modal-datetime-picker", - "https://github.com/magicismight/react-native-root-siblings", - {"github": "https://github.com/expo/react-native-action-sheet", "pkg": "@expo/react-native-action-sheet"} - ], - "incompatible": [ - "https://github.com/PeelTechnologies/react-native-tcp", - "https://github.com/naoufal/react-native-speech", - "https://github.com/EstebanFuentealba/react-native-share", - "https://github.com/aakashns/react-native-dialogs", - "https://github.com/oblador/react-native-keychain", - "https://github.com/joeferraro/react-native-cookies", - "https://github.com/doefler/react-native-social-share", - "https://github.com/innoveit/react-native-ble-manager", - "https://github.com/chirag04/react-native-mail", - "https://github.com/cnjon/react-native-pdf-view", - "https://github.com/kayla-tech/react-native-card-io", - "https://github.com/Kerumen/react-native-awesome-card-io", - "https://github.com/tolu360/react-native-google-places" - ] -} +[ + { + "githubUrl": "https://github.com/react-community/react-navigation", + "expo": true + }, + { "githubUrl": "https://github.com/gre/gl-react", "expo": true }, + { "githubUrl": "https://github.com/n4kz/react-native-pages", "expo": true }, + { "githubUrl": "https://github.com/airbnb/lottie-react-native", "expo": true }, + { "githubUrl": "https://github.com/airbnb/react-native-maps", "expo": true }, + { + "githubUrl": "https://github.com/oblador/react-native-animatable", + "expo": true + }, + { "githubUrl": "https://github.com/wix/react-native-calendars", "expo": true }, + { + "githubUrl": "https://github.com/oblador/react-native-vector-icons", + "expo": true + }, + { + "githubUrl": "https://github.com/idibidiart/react-native-responsive-grid", + "expo": true + }, + { + "githubUrl": "https://github.com/24ark/react-native-step-indicator", + "expo": true + }, + { + "githubUrl": "https://github.com/jacklam718/react-native-popup-dialog", + "expo": true + }, + { + "githubUrl": "https://github.com/react-native-community/react-native-drawer-layout", + "expo": true + }, + { + "githubUrl": "https://github.com/n4kz/react-native-material-textfield", + "expo": true + }, + { "githubUrl": "https://github.com/maxs15/react-native-modalbox", "expo": true }, + { + "githubUrl": "https://github.com/react-native-community/react-native-modal", + "expo": true + }, + { + "githubUrl": "https://github.com/react-native-training/react-native-elements", + "expo": true + }, + { + "githubUrl": "https://github.com/FaridSafi/react-native-gifted-chat", + "expo": true + }, + { + "githubUrl": "https://github.com/react-native-community/react-native-tab-view", + "expo": true + }, + { + "githubUrl": "https://github.com/bgryszko/react-native-circular-slider", + "expo": true + }, + { + "githubUrl": "https://github.com/archriss/react-native-snap-carousel", + "expo": true + }, + { + "githubUrl": "https://github.com/mmazzarolo/react-native-modal-datetime-picker", + "expo": true + }, + { + "githubUrl": "https://github.com/magicismight/react-native-root-siblings", + "expo": true + }, + { + "githubUrl": "https://github.com/expo/react-native-action-sheet", + "npmPkg": "@expo/react-native-action-sheet", + "expo": true + }, + { "githubUrl": "https://github.com/PeelTechnologies/react-native-tcp" }, + { "githubUrl": "https://github.com/naoufal/react-native-speech" }, + { "githubUrl": "https://github.com/EstebanFuentealba/react-native-share" }, + { "githubUrl": "https://github.com/aakashns/react-native-dialogs" }, + { "githubUrl": "https://github.com/oblador/react-native-keychain" }, + { "githubUrl": "https://github.com/joeferraro/react-native-cookies" }, + { "githubUrl": "https://github.com/doefler/react-native-social-share" }, + { "githubUrl": "https://github.com/innoveit/react-native-ble-manager" }, + { "githubUrl": "https://github.com/chirag04/react-native-mail" }, + { "githubUrl": "https://github.com/cnjon/react-native-pdf-view" }, + { "githubUrl": "https://github.com/kayla-tech/react-native-card-io" }, + { "githubUrl": "https://github.com/Kerumen/react-native-awesome-card-io" }, + { "githubUrl": "https://github.com/tolu360/react-native-google-places" } +] diff --git a/package.json b/package.json index 0fa0c4ae..554a851f 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "express": "^4.14.0", "isomorphic-fetch": "^2.2.1", "jsonfile": "^3.0.0", + "lodash": "^4.17.4", "next": "^2.1.1", "next-redux-wrapper": "^1.0.0", "next-routes": "^1.0.24", diff --git a/scripts/build-and-score-data.js b/scripts/build-and-score-data.js index 4f89f003..c9591d73 100644 --- a/scripts/build-and-score-data.js +++ b/scripts/build-and-score-data.js @@ -2,6 +2,7 @@ import 'isomorphic-fetch'; import path from 'path'; import fs from 'fs'; import jsonfile from 'jsonfile'; +import _ from 'lodash'; import fetchGithubData from './fetch-github-data'; import calculateScore from './calculate-score'; import fetchReadmeImages from './fetch-readme-images'; @@ -16,7 +17,7 @@ const USE_DEBUG_REPOS = false; // Loads the Github API results from disk rather than hitting the API each time. // The first run will hit the API if raw-github-results.json doesn't exist yet. -const LOAD_GITHUB_RESULTS_FROM_DISK = false; +const LOAD_GITHUB_RESULTS_FROM_DISK = true; const GITHUB_RESULTS_PATH = path.join('scripts', 'raw-github-results.json'); const JSON_OPTIONS = { @@ -25,37 +26,26 @@ const JSON_OPTIONS = { const buildAndScoreData = async () => { console.log('** Loading data from Github'); - let { expo, incompatible } = await loadRepositoryDataAsync(); + let data = await loadRepositoryDataAsync(); console.log('\n** Scraping images from README'); - expo = await Promise.all( - expo.map(repo => fetchReadmeImages(repo, repo.urls.repo)) - ); - - incompatible = await Promise.all( - incompatible.map(repo => fetchReadmeImages(repo, repo.urls.repo)) - ); + data = await Promise.all(data.map(d => fetchReadmeImages(d, d.githubUrl))); console.log('\n** Loading download stats from npm'); - expo = await Promise.all(expo.map(repo => fetchNpmData(repo, repo.pkg))); - - incompatible = await Promise.all( - incompatible.map(repo => fetchNpmData(repo, repo.pkg)) + data = await Promise.all( + data.map(d => fetchNpmData(d, d.npmPkg, d.githubUrl)) ); // Calculate score console.log('\n** Calculating scores'); - expo = expo.map(calculateScore); - incompatible = incompatible.map(calculateScore); + data = data.map(calculateScore); - const jsonData = { - expo, - incompatible, - }; + const expo = _.filter(data, d => d.expo); + const incompatible = _.filter(data, d => !d.expo); return jsonfile.writeFile( path.resolve('build', 'data.json'), - jsonData, + { expo, incompatible }, JSON_OPTIONS, err => { if (err) { @@ -81,26 +71,17 @@ async function loadRepositoryDataAsync() { result = jsonfile.readFileSync(GITHUB_RESULTS_PATH); console.log('Loaded Github results from disk, skipped API calls'); } else { - let expo = await Promise.all(data.expo.map(fetchGithubData)); - let incompatible = await Promise.all( - data.incompatible.map(fetchGithubData) - ); - result = { expo, incompatible }; + result = await Promise.all(data.map(fetchGithubData)); if (LOAD_GITHUB_RESULTS_FROM_DISK) { await new Promise((resolve, reject) => { - jsonfile.writeFile( - GITHUB_RESULTS_PATH, - { expo, incompatible }, - JSON_OPTIONS, - err => { - if (err) { - reject(err); - } else { - resolve(); - } + jsonfile.writeFile(GITHUB_RESULTS_PATH, result, JSON_OPTIONS, err => { + if (err) { + reject(err); + } else { + resolve(); } - ); + }); }); console.log('Saved Github results from disk'); } diff --git a/scripts/calculate-score.js b/scripts/calculate-score.js index f7a71f77..10f1cb8b 100644 --- a/scripts/calculate-score.js +++ b/scripts/calculate-score.js @@ -1,53 +1,55 @@ -const calculateScore = repo => { - repo.score = 0; +const calculateScore = data => { + let { github } = data; + let score = 0; - const daysAgo = getDaysAgo(repo.stats.updatedAt); + const daysAgo = getDaysAgo(github.stats.updatedAt); if (daysAgo <= 30) { - repo.score += 15; + score += 15; } else if (daysAgo <= 60) { - repo.score += 10; + score += 10; } else if (daysAgo <= 90) { - repo.score += 5; + score += 5; } - if (repo.stats.hasIssues) { - repo.score += 10; + if (github.stats.hasIssues) { + score += 10; } - if (repo.stats.hasWiki) { - repo.score += 10; + if (github.stats.hasWiki) { + score += 10; } - if (repo.stats.hasPages) { - repo.score += 5; + if (github.stats.hasPages) { + score += 5; } - if (repo.stats.hasDownloads) { - repo.score += 10; + if (github.stats.hasDownloads) { + score += 10; } - if (repo.stats.hasTopics) { - repo.score += 10; + if (github.stats.hasTopics) { + score += 10; } - if (repo.stats.watchers > 10) { - repo.score += 5; + if (github.stats.watchers > 10) { + score += 5; } - if (repo.stats.forks > 5) { - repo.score += 10; + if (github.stats.forks > 5) { + score += 10; } - if (repo.stats.stars >= 2500) { - repo.score += 20; - } else if (repo.stats.stars >= 500) { - repo.score += 15; - } else if (repo.stats.stars >= 100) { - repo.score += 10; + if (github.stats.stars >= 2500) { + score += 20; + } else if (github.stats.stars >= 500) { + score += 15; + } else if (github.stats.stars >= 100) { + score += 10; } - return repo; + data.score = score; + return data; }; const getDaysAgo = date => { diff --git a/scripts/fetch-github-data.js b/scripts/fetch-github-data.js index bdb17b1c..08b528ba 100644 --- a/scripts/fetch-github-data.js +++ b/scripts/fetch-github-data.js @@ -3,16 +3,8 @@ import { GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET } from '../secrets.json'; const API = 'https://api.github.com'; -const fetchGithubData = async urlOrObj => { - let url, pkg; - if (typeof urlOrObj === 'string') { - url = urlOrObj; - let parts = url.split('/'); - pkg = parts[parts.length - 1]; - } else { - url = urlOrObj.github; - pkg = urlOrObj.pkg; - } +const fetchGithubData = async data => { + let url = data.githubUrl; const requestUrl = createRequestUrl(url); const response = await fetch(requestUrl, { @@ -22,10 +14,12 @@ const fetchGithubData = async urlOrObj => { }, }); let json = await response.json(); - let result = createRepoDataWithResponse(json); - result.pkg = pkg; - return result; + + return { + ...data, + github: result, + }; }; const createRepoDataWithResponse = json => { diff --git a/scripts/fetch-npm-data.js b/scripts/fetch-npm-data.js index 557e2abf..888e7982 100644 --- a/scripts/fetch-npm-data.js +++ b/scripts/fetch-npm-data.js @@ -1,13 +1,19 @@ import 'isomorphic-fetch'; -const urlForPackage = pkgName => { - return `https://api.npmjs.org/downloads/point/last-month/${pkgName}`; +const urlForPackage = npmPkg => { + return `https://api.npmjs.org/downloads/point/last-month/${npmPkg}`; }; -const fetchNpmData = async (data, pkgName) => { +const fetchNpmData = async (data, npmPkg, githubUrl) => { + if (!npmPkg) { + let parts = githubUrl.split('/'); + npmPkg = parts[parts.length - 1]; + data.npmPkg = npmPkg; + } + try { - console.log(urlForPackage(pkgName)); - let response = await fetch(urlForPackage(pkgName)); + console.log(urlForPackage(npmPkg)); + let response = await fetch(urlForPackage(npmPkg)); let downloadData = await response.json(); return { diff --git a/yarn.lock b/yarn.lock index 46a58c86..cf37740c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1711,14 +1711,14 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" -domelementtype@1, domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domelementtype@^1.3.0: +domelementtype@1, domelementtype@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + domhandler@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"