fix: add health fields to /api/tools/search response
The search endpoint was missing importHealth, executionHealth, healthCheckError, and lastHealthCheck fields in the response. This caused the playground (which uses search-registry tool) to not receive health data for displaying broken tool badges. Added all four health fields to the tool mapping in the search response. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f6812b2267
commit
0e907338ed
6 changed files with 84 additions and 117 deletions
|
|
@ -153,6 +153,10 @@ export async function GET(request: Request) {
|
|||
exportName: tool.exportName,
|
||||
description: tool.description,
|
||||
qualityScore: tool.qualityScore,
|
||||
importHealth: tool.importHealth,
|
||||
executionHealth: tool.executionHealth,
|
||||
healthCheckError: tool.healthCheckError,
|
||||
lastHealthCheck: tool.lastHealthCheck,
|
||||
package: {
|
||||
npmPackageName: tool.package.npmPackageName,
|
||||
npmVersion: tool.package.npmVersion,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { Space_Grotesk, Space_Mono } from 'next/font/google';
|
||||
import { AppFooter } from '../components/AppFooter';
|
||||
import { ThemeProvider } from '../components/providers/ThemeProvider';
|
||||
import './globals.css';
|
||||
|
||||
|
|
@ -40,7 +41,10 @@ export default function RootLayout({
|
|||
enableSystem={true}
|
||||
disableTransitionOnChange={false}
|
||||
>
|
||||
{children}
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<div className="flex-1">{children}</div>
|
||||
<AppFooter />
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -74,10 +74,10 @@ async function getHomePageData() {
|
|||
export default async function HomePage(): Promise<React.ReactElement> {
|
||||
const data = await getHomePageData();
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<>
|
||||
<AppHeader />
|
||||
|
||||
<main className="flex-1">
|
||||
<main>
|
||||
{/* Hero Section - Dithered Design */}
|
||||
<HeroSection stats={data.stats} />
|
||||
|
||||
|
|
@ -205,41 +205,6 @@ export default async function HomePage(): Promise<React.ReactElement> {
|
|||
</Container>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="py-8 border-t border-border bg-surface">
|
||||
<Container size="xl" padding="lg">
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<p className="text-sm text-foreground-secondary">© 2025 TPMJS. All rights reserved.</p>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<a
|
||||
href="mailto:thomasalwyndavis@gmail.com"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<span className="text-border">·</span>
|
||||
<a
|
||||
href="https://github.com/tpmjs/tpmjs"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<span className="text-border">·</span>
|
||||
<a
|
||||
href="https://twitter.com/tpmjs"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</footer>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,18 +245,34 @@ export default function ToolSearchPage(): React.ReactElement {
|
|||
{tool.package.npmPackageName}
|
||||
</div>
|
||||
</div>
|
||||
{tool.package.npmRepository && (
|
||||
<a
|
||||
href={tool.package.npmRepository.url
|
||||
.replace('git+', '')
|
||||
.replace('.git', '')}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
<Icon icon="externalLink" size="sm" />
|
||||
</a>
|
||||
)}
|
||||
{tool.package.npmRepository &&
|
||||
(() => {
|
||||
// Clean up repository URL
|
||||
let repoUrl = tool.package.npmRepository.url;
|
||||
|
||||
// Remove git+ prefix
|
||||
repoUrl = repoUrl.replace(/^git\+/, '');
|
||||
|
||||
// Remove .git suffix
|
||||
repoUrl = repoUrl.replace(/\.git$/, '');
|
||||
|
||||
// Convert git:// to https://
|
||||
repoUrl = repoUrl.replace(/^git:\/\//, 'https://');
|
||||
|
||||
// Convert ssh URLs to https
|
||||
repoUrl = repoUrl.replace(/^git@github\.com:/, 'https://github.com/');
|
||||
|
||||
return (
|
||||
<a
|
||||
href={repoUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
<Icon icon="externalLink" size="sm" />
|
||||
</a>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
<CardDescription>{tool.description}</CardDescription>
|
||||
</CardHeader>
|
||||
|
|
|
|||
41
apps/web/src/components/AppFooter.tsx
Normal file
41
apps/web/src/components/AppFooter.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
'use client';
|
||||
|
||||
import { Container } from '@tpmjs/ui/Container/Container';
|
||||
|
||||
export function AppFooter(): React.ReactElement {
|
||||
return (
|
||||
<footer className="py-8 border-t border-border bg-surface">
|
||||
<Container size="xl" padding="lg">
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<p className="text-sm text-foreground-secondary">© 2025 TPMJS. All rights reserved.</p>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<a
|
||||
href="mailto:thomasalwyndavis@gmail.com"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
<span className="text-border">·</span>
|
||||
<a
|
||||
href="https://github.com/tpmjs/tpmjs"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<span className="text-border">·</span>
|
||||
<a
|
||||
href="https://twitter.com/tpmjs_registry"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-foreground-secondary hover:text-foreground transition-colors"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { cn } from '@tpmjs/utils/cn';
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { prism, vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import type { CodeBlockProps } from './types';
|
||||
import {
|
||||
|
|
@ -10,70 +10,6 @@ import {
|
|||
codeBlockCopyButtonVariants,
|
||||
} from './variants';
|
||||
|
||||
// Custom light theme with better contrast
|
||||
const customLightTheme = {
|
||||
'code[class*="language-"]': {
|
||||
color: '#24292e',
|
||||
fontFamily: 'Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace',
|
||||
fontSize: '1em',
|
||||
textAlign: 'left',
|
||||
whiteSpace: 'pre',
|
||||
wordSpacing: 'normal',
|
||||
wordBreak: 'normal',
|
||||
wordWrap: 'normal',
|
||||
lineHeight: '1.5',
|
||||
tabSize: '4',
|
||||
hyphens: 'none',
|
||||
},
|
||||
'pre[class*="language-"]': {
|
||||
color: '#24292e',
|
||||
fontFamily: 'Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace',
|
||||
fontSize: '1em',
|
||||
textAlign: 'left',
|
||||
whiteSpace: 'pre',
|
||||
wordSpacing: 'normal',
|
||||
wordBreak: 'normal',
|
||||
wordWrap: 'normal',
|
||||
lineHeight: '1.5',
|
||||
tabSize: '4',
|
||||
hyphens: 'none',
|
||||
padding: '1em',
|
||||
margin: '0.5em 0',
|
||||
overflow: 'auto',
|
||||
},
|
||||
comment: { color: '#6a737d', fontStyle: 'italic' },
|
||||
prolog: { color: '#6a737d' },
|
||||
doctype: { color: '#6a737d' },
|
||||
cdata: { color: '#6a737d' },
|
||||
punctuation: { color: '#24292e' },
|
||||
property: { color: '#005cc5' },
|
||||
tag: { color: '#22863a' },
|
||||
boolean: { color: '#005cc5' },
|
||||
number: { color: '#005cc5' },
|
||||
constant: { color: '#005cc5' },
|
||||
symbol: { color: '#005cc5' },
|
||||
deleted: { color: '#b31d28' },
|
||||
selector: { color: '#22863a' },
|
||||
'attr-name': { color: '#6f42c1' },
|
||||
string: { color: '#032f62' },
|
||||
char: { color: '#032f62' },
|
||||
builtin: { color: '#005cc5' },
|
||||
inserted: { color: '#22863a' },
|
||||
operator: { color: '#d73a49' },
|
||||
entity: { color: '#6f42c1' },
|
||||
url: { color: '#032f62' },
|
||||
variable: { color: '#e36209' },
|
||||
atrule: { color: '#d73a49' },
|
||||
'attr-value': { color: '#032f62' },
|
||||
function: { color: '#6f42c1' },
|
||||
'class-name': { color: '#6f42c1' },
|
||||
keyword: { color: '#d73a49' },
|
||||
regex: { color: '#032f62' },
|
||||
important: { color: '#d73a49', fontWeight: 'bold' },
|
||||
bold: { fontWeight: 'bold' },
|
||||
italic: { fontStyle: 'italic' },
|
||||
};
|
||||
|
||||
/**
|
||||
* CodeBlock component
|
||||
*
|
||||
|
|
@ -134,7 +70,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
|
|||
<div className={codeBlockCodeVariants({ size })} data-language={normalizedLanguage}>
|
||||
<SyntaxHighlighter
|
||||
language={normalizedLanguage}
|
||||
style={theme === 'dark' ? oneDark : oneLight}
|
||||
style={theme === 'dark' ? vscDarkPlus : prism}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
|
@ -145,6 +81,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
|
|||
codeTagProps={{
|
||||
style: {
|
||||
fontFamily: 'inherit',
|
||||
color: '#24292e', // Darker text color for better contrast
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue