From 84fb52d71afb7e9e1f210f3d610bdc28e84a36e4 Mon Sep 17 00:00:00 2001 From: Yasuaki Uechi Date: Wed, 31 Jul 2019 00:18:58 +0900 Subject: [PATCH] feat: add js.org and homebrew provider --- src/App.js | 14 ++++-- src/components/Card.js | 82 ++++++++++++++++++++-------------- src/components/GithubCard.js | 11 ++--- src/components/HomebrewCard.js | 36 +++++++++++++++ src/components/JsOrgCard.js | 31 +++++++++++++ src/components/NpmCard.js | 13 +++--- src/components/TwitterCard.js | 11 ++--- src/services/github.js | 9 ++-- src/services/jsorg.js | 29 ++++++++++++ src/services/twitter.js | 11 ++--- 10 files changed, 183 insertions(+), 64 deletions(-) create mode 100644 src/components/HomebrewCard.js create mode 100644 src/components/JsOrgCard.js create mode 100644 src/services/jsorg.js diff --git a/src/App.js b/src/App.js index 206b118..5b1d06d 100644 --- a/src/App.js +++ b/src/App.js @@ -5,6 +5,8 @@ import { CardHolder } from './components/Card' import GithubCard from './components/GithubCard' import TwitterCard from './components/TwitterCard' import NpmCard from './components/NpmCard' +import JsOrgCard from './components/JsOrgCard' +import HomebrewCard from './components/HomebrewCard' import './App.css' const GlobalStyle = createGlobalStyle` @@ -36,14 +38,16 @@ export default function App() { /> {query && query.length > 0 ? ( - + Result for {query} + + - + ) : null} ) @@ -61,11 +65,13 @@ const Input = styled.input` } ` -const SearchResult = styled.div` +const Result = styled.div` margin-top: 40px; ` -const ResultHeader = styled.h4` +const ResultHeader = styled.div` padding-left: 20px; margin-bottom: 20px; + font-size: 1.2rem; + font-weight: bold; ` diff --git a/src/components/Card.js b/src/components/Card.js index d06406d..8b160ae 100644 --- a/src/components/Card.js +++ b/src/components/Card.js @@ -2,6 +2,53 @@ import React, { Suspense } from 'react' import styled from 'styled-components' import { BarLoader } from 'react-spinners' +export function Card({ children }) { + return ( + + + }>{children} + + + ) +} + +export const CardTitle = styled.div` + font-size: 0.8rem; + font-weight: bold; + margin-bottom: 15px; +` + +export const CardHolder = styled.div` + display: flex; + flex-direction: column; +` + +export function AvailabilityCell({ + name, + availability, + url, + prefix = '', + suffix = '', + icon, +}) { + return ( + + {icon} + + + {prefix} + {availability ? ( + {name} + ) : ( + {name} + )} + {suffix} + + + + ) +} + class ErrorBoundary extends React.Component { constructor(props) { super(props) @@ -23,22 +70,7 @@ class ErrorBoundary extends React.Component { } } -export function Card({ children }) { - return ( - - - }>{children} - - - ) -} - -export const CardHolder = styled.div` - display: flex; - flex-direction: column; -` - -export const CardWrapper = styled.div` +const CardWrapper = styled.div` margin-bottom: 40px; padding: 20px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.2); @@ -63,21 +95,3 @@ const Item = styled.span` color: inherit; } ` - -export function AvailabilityCell({ name, availability, url, prefix, icon }) { - return ( - - {icon} - - - {prefix} - {availability ? ( - {name} - ) : ( - {name} - )} - - - - ) -} diff --git a/src/components/GithubCard.js b/src/components/GithubCard.js index 544f78c..13a43b5 100644 --- a/src/components/GithubCard.js +++ b/src/components/GithubCard.js @@ -1,9 +1,9 @@ import React from 'react' import useFetch from 'fetch-suspense' -import { Card, AvailabilityCell } from './Card' +import { Card, CardTitle, AvailabilityCell } from './Card' import { FaGithub } from 'react-icons/fa' -function GithubPanel({ name }) { +function Availability({ name }) { const response = useFetch(`/availability/github/${name}`) if (response.error) { @@ -14,9 +14,9 @@ function GithubPanel({ name }) { } - url="https://github.com/" + url={`https://github.com/${name}`} prefix="github.com/" + icon={} /> ) } @@ -24,7 +24,8 @@ function GithubPanel({ name }) { export default function GithubCard({ name }) { return ( - + GitHub + ) } diff --git a/src/components/HomebrewCard.js b/src/components/HomebrewCard.js new file mode 100644 index 0000000..ef6aa23 --- /dev/null +++ b/src/components/HomebrewCard.js @@ -0,0 +1,36 @@ +import React from 'react' +import useFetch from 'fetch-suspense' +import { Card, CardTitle, AvailabilityCell } from './Card' +import { IoIosBeer } from 'react-icons/io' + +function Availability({ name }) { + const response = useFetch( + `https://formulae.brew.sh/api/formula/${name}.json`, + null, + { metadata: true } + ) + + if (response.status !== 404 && response.status !== 200) { + throw new Error(`Homebrew: ${response.statusText}`) + } + + const availability = response.status === 404 + + return ( + } + /> + ) +} + +export default function HomebrewCard({ name }) { + return ( + + Homebrew + + + ) +} diff --git a/src/components/JsOrgCard.js b/src/components/JsOrgCard.js new file mode 100644 index 0000000..c3d9aaf --- /dev/null +++ b/src/components/JsOrgCard.js @@ -0,0 +1,31 @@ +import React from 'react' +import useFetch from 'fetch-suspense' +import { Card, CardTitle, AvailabilityCell } from './Card' +import { FaJsSquare } from 'react-icons/fa' + +function Availability({ name }) { + const response = useFetch(`/availability/jsorg/${name}`) + + if (response.error) { + throw new Error(`Twitter: ${response.error}`) + } + + return ( + } + /> + ) +} + +export default function JsOrgCard({ name }) { + return ( + + js.org + + + ) +} diff --git a/src/components/NpmCard.js b/src/components/NpmCard.js index 5f0f082..f448906 100644 --- a/src/components/NpmCard.js +++ b/src/components/NpmCard.js @@ -1,9 +1,9 @@ import React from 'react' import useFetch from 'fetch-suspense' -import { Card, AvailabilityCell } from './Card' +import { Card, CardTitle, AvailabilityCell } from './Card' import { FaNpm } from 'react-icons/fa' -function NpmPanel({ name }) { +function Availability({ name }) { const response = useFetch(`/availability/npm/${name}`) if (response.error) { @@ -15,9 +15,9 @@ function NpmPanel({ name }) { } - url="https://www.npmjs.com/package/" + url={`https://www.npmjs.com/package/${name}`} prefix="npmjs.com/package/" + icon={} /> - + + npm + ) } diff --git a/src/components/TwitterCard.js b/src/components/TwitterCard.js index 00e0e0e..cd7d2a7 100644 --- a/src/components/TwitterCard.js +++ b/src/components/TwitterCard.js @@ -1,9 +1,9 @@ import React from 'react' import useFetch from 'fetch-suspense' -import { Card, AvailabilityCell } from './Card' +import { Card, CardTitle, AvailabilityCell } from './Card' import { FaTwitter } from 'react-icons/fa' -function TwitterPanel({ name }) { +function Availability({ name }) { const response = useFetch(`/availability/twitter/${name}`) if (response.error) { @@ -14,9 +14,9 @@ function TwitterPanel({ name }) { } - url="https://twitter.com/" + url={`https://twitter.com/${name}`} prefix="twitter.com/" + icon={} /> ) } @@ -24,7 +24,8 @@ function TwitterPanel({ name }) { export default function TwitterCard({ name }) { return ( - + Twitter + ) } diff --git a/src/services/github.js b/src/services/github.js index c0f90f7..6b314b6 100644 --- a/src/services/github.js +++ b/src/services/github.js @@ -1,9 +1,8 @@ const fetch = require('isomorphic-unfetch') -async function getGitHubAvailability(name) { - const githubURL = 'https://github.com' - const response = await fetch(`${githubURL}/${encodeURIComponent(name)}`) - return response.status === 404 +async function getAvailability(name) { + const response = await fetch(`https://github.com/${encodeURIComponent(name)}`) + return response.status !== 200 } module.exports = async (req, res) => { @@ -14,7 +13,7 @@ module.exports = async (req, res) => { } try { - const availability = await getGitHubAvailability(name) + const availability = await getAvailability(name) res.json({ availability }) } catch (err) { res.status(400).json({ error: err.message }) diff --git a/src/services/jsorg.js b/src/services/jsorg.js new file mode 100644 index 0000000..99d5af5 --- /dev/null +++ b/src/services/jsorg.js @@ -0,0 +1,29 @@ +const fetch = require('isomorphic-unfetch') + +async function getAvailability(name) { + try { + const response = await fetch(`https://${encodeURIComponent(name)}.js.org`) + return response.status !== 200 + } catch (err) { + if (err.code === 'ENOTFOUND') { + return true + } else { + throw new Error(err.message) + } + } +} + +module.exports = async (req, res) => { + const name = req.query.name + + if (!name) { + return res.status(400).json({ error: 'no query given' }) + } + + try { + const availability = await getAvailability(name) + res.json({ availability }) + } catch (err) { + res.status(400).json({ error: err.message }) + } +} diff --git a/src/services/twitter.js b/src/services/twitter.js index c342b40..60b6888 100644 --- a/src/services/twitter.js +++ b/src/services/twitter.js @@ -1,9 +1,10 @@ const fetch = require('isomorphic-unfetch') -async function getTwitterAvailability(name) { - const twitterURL = 'https://twitter.com' - const response = await fetch(`${twitterURL}/${encodeURIComponent(name)}`) - return response.status === 404 +async function getAvailability(name) { + const response = await fetch( + `https://twitter.com/${encodeURIComponent(name)}` + ) + return response.status !== 200 } module.exports = async (req, res) => { @@ -14,7 +15,7 @@ module.exports = async (req, res) => { } try { - const availability = await getTwitterAvailability(name) + const availability = await getAvailability(name) res.json({ availability }) } catch (err) { res.status(400).json({ error: err.message })