mirror of
https://github.com/uetchy/namae.git
synced 2025-03-16 12:10:32 +09:00
feat: support Docker Hub
This commit is contained in:
parent
09f2755410
commit
ad6052c29a
1
.gitignore
vendored
1
.gitignore
vendored
@ -99,3 +99,4 @@ typings/
|
||||
|
||||
.now
|
||||
.vercel
|
||||
.sentryclirc
|
||||
|
@ -6,7 +6,9 @@ export default async function handler(
|
||||
req: VercelRequest,
|
||||
res: VercelResponse
|
||||
): Promise<void> {
|
||||
const { query } = req.query;
|
||||
const { query, existIf = '404' } = req.query;
|
||||
|
||||
const availableStatus = (existIf as string).split(',').map((s) => s.trim());
|
||||
|
||||
if (!query || typeof query !== 'string') {
|
||||
return sendError(res, new Error('no query given'));
|
||||
@ -18,7 +20,7 @@ export default async function handler(
|
||||
|
||||
try {
|
||||
const response = await fetch(`https://${query}`);
|
||||
const availability = response.status === 404;
|
||||
const availability = availableStatus.includes(response.status.toString());
|
||||
send(res, { availability });
|
||||
} catch (err: any) {
|
||||
if ((err as any).code === 'ENOTFOUND') {
|
||||
|
@ -51,7 +51,8 @@
|
||||
"youtube": "YouTube",
|
||||
"hexpm": "Hex",
|
||||
"fly": "Fly.io",
|
||||
"productHunt": "Product Hunt"
|
||||
"productHunt": "Product Hunt",
|
||||
"docker": "Docker Hub"
|
||||
},
|
||||
"showMore": "show more",
|
||||
"try": "How about this?",
|
||||
|
@ -3,29 +3,31 @@ import { useTranslation } from 'react-i18next';
|
||||
import { DiHeroku } from 'react-icons/di';
|
||||
import {
|
||||
FaAws,
|
||||
FaCloudflare,
|
||||
FaDocker,
|
||||
FaFirefoxBrowser,
|
||||
FaFly,
|
||||
FaGithub,
|
||||
FaGithubAlt,
|
||||
FaGitlab,
|
||||
// FaInstagram,
|
||||
FaJsSquare,
|
||||
FaProductHunt,
|
||||
FaPython,
|
||||
FaReddit,
|
||||
FaSlack,
|
||||
FaTwitter,
|
||||
FaCloudflare,
|
||||
FaFirefoxBrowser,
|
||||
FaYoutube,
|
||||
FaProductHunt,
|
||||
FaFly,
|
||||
} from 'react-icons/fa';
|
||||
import { IoIosBeer, IoMdAppstore } from 'react-icons/io';
|
||||
import { IoIosBeer } from 'react-icons/io';
|
||||
import { MdDomain } from 'react-icons/md';
|
||||
import { RiBuilding2Fill, RiChromeFill, RiNpmjsFill } from 'react-icons/ri';
|
||||
import { SiDeno, SiElixir } from 'react-icons/si';
|
||||
import {
|
||||
SiAppstore,
|
||||
SiArchlinux,
|
||||
SiDebian,
|
||||
SiDeno,
|
||||
SiElixir,
|
||||
SiFirebase,
|
||||
SiRubygems,
|
||||
SiRust,
|
||||
@ -41,37 +43,38 @@ const supportedProviders: Record<string, React.ReactNode> = {
|
||||
domains: <MdDomain />,
|
||||
github: <FaGithub />,
|
||||
gitlab: <FaGitlab />,
|
||||
slack: <FaSlack />,
|
||||
productHunt: <FaProductHunt />,
|
||||
githubSearch: <FaGithubAlt />,
|
||||
nta: <RiBuilding2Fill />,
|
||||
twitter: <FaTwitter />,
|
||||
reddit: <FaReddit />,
|
||||
youtube: <FaYoutube />,
|
||||
docker: <FaDocker />,
|
||||
homebrew: <IoIosBeer />,
|
||||
archlinux: <SiArchlinux />,
|
||||
debian: <SiDebian />,
|
||||
ubuntu: <SiUbuntu />,
|
||||
npm: <RiNpmjsFill />,
|
||||
rust: <SiRust />,
|
||||
pypi: <FaPython />,
|
||||
rust: <SiRust />,
|
||||
rubygems: <SiRubygems />,
|
||||
hexpm: <SiElixir />,
|
||||
ocaml: <OcamlIcon />,
|
||||
archlinux: <SiArchlinux />,
|
||||
ubuntu: <SiUbuntu />,
|
||||
debian: <SiDebian />,
|
||||
reddit: <FaReddit />,
|
||||
// instagram: <FaInstagram />,
|
||||
slack: <FaSlack />,
|
||||
fly: <FaFly />,
|
||||
heroku: <DiHeroku />,
|
||||
now: <NowIcon />,
|
||||
heroku: <DiHeroku />,
|
||||
netlify: <NetlifyIcon />,
|
||||
cloudflare: <FaCloudflare />,
|
||||
s3: <FaAws />,
|
||||
firebase: <SiFirebase />,
|
||||
jsorg: <FaJsSquare />,
|
||||
modland: <SiDeno />,
|
||||
productHunt: <FaProductHunt />,
|
||||
githubSearch: <FaGithubAlt />,
|
||||
appStore: <SiAppstore />,
|
||||
// playStore: <IoMdAppstore />,
|
||||
firefoxAddons: <FaFirefoxBrowser />,
|
||||
chromeWebStore: <RiChromeFill />,
|
||||
nta: <RiBuilding2Fill />,
|
||||
};
|
||||
|
||||
const Welcome: React.FC = () => {
|
||||
|
@ -83,6 +83,7 @@ class NotFoundError extends Error {
|
||||
export const DedicatedAvailability: React.FC<{
|
||||
name: string;
|
||||
query?: string;
|
||||
args?: Record<string, string>;
|
||||
message?: string;
|
||||
messageIfTaken?: string;
|
||||
service: string;
|
||||
@ -94,6 +95,7 @@ export const DedicatedAvailability: React.FC<{
|
||||
}> = ({
|
||||
name,
|
||||
query = undefined,
|
||||
args = {},
|
||||
message = '',
|
||||
messageIfTaken = undefined,
|
||||
service,
|
||||
@ -105,7 +107,8 @@ export const DedicatedAvailability: React.FC<{
|
||||
}) => {
|
||||
const increaseCounter = useStoreActions((actions) => actions.stats.add);
|
||||
const response = useFetch(
|
||||
`/api/services/${service}/${encodeURIComponent(query || name)}`
|
||||
`/api/services/${service}/${encodeURIComponent(query || name)}` +
|
||||
new URLSearchParams(args).toString()
|
||||
) as Response;
|
||||
|
||||
if (response.error) {
|
||||
|
@ -6,6 +6,7 @@ import AppStoreCard from './providers/AppStore';
|
||||
import ChromeWebStoreCard from './providers/ChromeWebStore';
|
||||
import CloudflareCard from './providers/Cloudflare';
|
||||
import CratesioCard from './providers/Cratesio';
|
||||
import DockerCard from './providers/Docker';
|
||||
import DomainCard from './providers/Domains';
|
||||
import FirebaseCard from './providers/Firebase';
|
||||
import FirefoxAddonsCard from './providers/FirefoxAddons';
|
||||
@ -23,7 +24,7 @@ import NetlifyCard from './providers/Netlify';
|
||||
import NpmCard from './providers/Npm';
|
||||
import NtaCard from './providers/Nta';
|
||||
import OcamlCard from './providers/Ocaml';
|
||||
import PlayStoreCard from './providers/PlayStore';
|
||||
// import PlayStoreCard from './providers/PlayStore';
|
||||
import ProductHuntCard from './providers/ProductHunt';
|
||||
import PypiCard from './providers/PyPI';
|
||||
import RubyGemsCard from './providers/RubyGems';
|
||||
@ -64,6 +65,7 @@ const Index: React.FC<{ query: string }> = ({ query }) => {
|
||||
<Section>
|
||||
<Title>{t('section.package')}</Title>
|
||||
<Cards>
|
||||
<DockerCard query={query} />
|
||||
<HomebrewCard query={query} />
|
||||
<LinuxCard query={query} />
|
||||
<NpmCard query={query} />
|
||||
|
33
src/components/cards/providers/Docker.tsx
Normal file
33
src/components/cards/providers/Docker.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaDocker } from 'react-icons/fa';
|
||||
import { normalize } from '../../../util/text';
|
||||
|
||||
import { Card, DedicatedAvailability, Repeater } from '../core';
|
||||
|
||||
const DockerCard: React.FC<{ query: string }> = ({ query }) => {
|
||||
const { t } = useTranslation();
|
||||
const normalizedQuery = normalize(query, { allowUnderscore: false });
|
||||
const lowerCase = normalizedQuery.toLowerCase();
|
||||
|
||||
const names = [lowerCase];
|
||||
|
||||
return (
|
||||
<Card title={t('providers.docker')}>
|
||||
<Repeater items={names}>
|
||||
{(name) => (
|
||||
<DedicatedAvailability
|
||||
name={name}
|
||||
query={`hub.docker.com/v2/orgs/${name}`}
|
||||
service="existence"
|
||||
message="Go to Docker Hub"
|
||||
link={`https://hub.docker.com/orgs/${name}`}
|
||||
icon={<FaDocker />}
|
||||
/>
|
||||
)}
|
||||
</Repeater>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default DockerCard;
|
@ -5,7 +5,7 @@ import XHR from 'i18next-xhr-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const TRANSLATION_VERSION = '19';
|
||||
const TRANSLATION_VERSION = '20';
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
|
Loading…
x
Reference in New Issue
Block a user