Health Monitor API
Complete API reference for @25xcodes/llmfeed-health-monitor.
Format Support
Full health monitoring with validation is available for LLMFeed JSON format. The crawler can fetch llm.txt files but validation requires JSON feeds.
Functions
crawlFeed
Crawl and validate a single feed.
async function crawlFeed(
url: string,
storage?: FeedStorage,
options?: CrawlOptions
): Promise<CrawlResult>Parameters:
url- Feed URL to crawlstorage- Optional storage backendoptions- Crawl options
Options:
interface CrawlOptions {
timeout?: number // Request timeout in ms (default: 10000)
validateSignature?: boolean // Verify signatures (default: true)
followRedirects?: boolean // Follow redirects (default: true)
userAgent?: string // Custom User-Agent
}Returns: Promise<CrawlResult>
interface CrawlResult {
url: string
feedId: string
status: 'healthy' | 'degraded' | 'unhealthy'
crawledAt: string
responseTime: number
httpStatus: number
structureValid: boolean
signatureValid: boolean
feed: LLMFeed | null
errors: string[]
contentHash: string
}Example:
import { crawlFeed, MemoryStorage } from '@25xcodes/llmfeed-health-monitor'
const storage = new MemoryStorage()
// Crawl LLMFeed JSON (full validation support)
const result = await crawlFeed(
'https://example.com/.well-known/llmfeed.json',
storage,
{ timeout: 5000 }
)
console.log('Status:', result.status)
console.log('Response time:', result.responseTime, 'ms')crawlFeeds
Crawl multiple feeds concurrently.
async function crawlFeeds(
urls: string[],
storage?: FeedStorage,
options?: CrawlOptions & { concurrency?: number }
): Promise<CrawlResult[]>Parameters:
urls- Array of feed URLsstorage- Optional storage backendoptions- Crawl options plus concurrency
Example:
import { crawlFeeds, MemoryStorage } from '@25xcodes/llmfeed-health-monitor'
const storage = new MemoryStorage()
// Crawl multiple LLMFeed JSON files
const results = await crawlFeeds([
'https://example1.com/llmfeed.json',
'https://example2.com/llmfeed.json',
'https://example3.com/llmfeed.json'
], storage, {
concurrency: 3,
timeout: 10000
})
for (const result of results) {
console.log(`${result.url}: ${result.status}`)
}generateReport
Generate health reports in various formats.
async function generateReport(options: ReportOptions): Promise<string>Options:
interface ReportOptions {
storage: FeedStorage
format: 'json' | 'html' | 'markdown'
outputPath?: string
title?: string
includeHistory?: boolean
}Returns: Promise<string> - The generated report content
Example:
import { generateReport, MemoryStorage } from '@25xcodes/llmfeed-health-monitor'
const storage = new MemoryStorage()
// Generate HTML report
const html = await generateReport({
storage,
format: 'html',
outputPath: './report.html',
title: 'Daily Health Report'
})
// Generate JSON report
const json = await generateReport({
storage,
format: 'json'
})
const data = JSON.parse(json)
console.log('Healthy feeds:', data.summary.healthy)Utility Functions
normalizeUrl
Normalize a feed URL for consistent storage.
function normalizeUrl(url: string): stringExample:
import { normalizeUrl } from '@25xcodes/llmfeed-health-monitor'
normalizeUrl('example.com/llmfeed.json')
// => 'https://example.com/llmfeed.json'
normalizeUrl('http://EXAMPLE.COM/llmfeed.json')
// => 'https://example.com/llmfeed.json'generateFeedId
Generate a stable ID for a feed URL.
function generateFeedId(url: string): stringExample:
import { generateFeedId } from '@25xcodes/llmfeed-health-monitor'
const id = generateFeedId('https://example.com/llmfeed.json')
// => 'example-com-llmfeed-json'checkMetaOptOut
Check HTML content for opt-out meta tags.
function checkMetaOptOut(html: string): booleanExample:
import { checkMetaOptOut } from '@25xcodes/llmfeed-health-monitor'
const html = '<meta name="llmfeed-optout" content="true">'
const hasOptOut = checkMetaOptOut(html) // truecheckFeedOptOut
Check feed content for opt-out signals.
function checkFeedOptOut(feed: unknown): booleanExample:
import { checkFeedOptOut } from '@25xcodes/llmfeed-health-monitor'
const feed = { meta: { optOut: true } }
const hasOptOut = checkFeedOptOut(feed) // trueStorage Classes
MemoryStorage
In-memory storage for testing and single runs.
class MemoryStorage implements FeedStorage {
constructor()
save(result: CrawlResult): Promise<void>
get(feedId: string): Promise<CrawlResult | null>
getAll(): Promise<CrawlResult[]>
getHistory(feedId: string, limit?: number): Promise<CrawlResult[]>
clear(): Promise<void>
}Example:
import { MemoryStorage } from '@25xcodes/llmfeed-health-monitor'
const storage = new MemoryStorage()
// Use with crawlFeed
await crawlFeed(url, storage)
// Get all results
const results = await storage.getAll()
// Get history for a specific feed
const history = await storage.getHistory('example-com-llm-txt', 10)
// Clear all data
await storage.clear()Custom Storage
Implement FeedStorage for custom backends.
interface FeedStorage {
save(result: CrawlResult): Promise<void>
get(feedId: string): Promise<CrawlResult | null>
getAll(): Promise<CrawlResult[]>
getHistory(feedId: string, limit?: number): Promise<CrawlResult[]>
}Example: SQLite Storage
import type { FeedStorage, CrawlResult } from '@25xcodes/llmfeed-health-monitor'
import Database from 'better-sqlite3'
class SQLiteStorage implements FeedStorage {
private db: Database.Database
constructor(dbPath: string) {
this.db = new Database(dbPath)
this.init()
}
private init() {
this.db.exec(`
CREATE TABLE IF NOT EXISTS crawl_results (
id INTEGER PRIMARY KEY,
feed_id TEXT NOT NULL,
url TEXT NOT NULL,
status TEXT NOT NULL,
crawled_at TEXT NOT NULL,
data JSON NOT NULL
)
`)
}
async save(result: CrawlResult): Promise<void> {
this.db.prepare(`
INSERT INTO crawl_results (feed_id, url, status, crawled_at, data)
VALUES (?, ?, ?, ?, ?)
`).run(
result.feedId,
result.url,
result.status,
result.crawledAt,
JSON.stringify(result)
)
}
async get(feedId: string): Promise<CrawlResult | null> {
const row = this.db.prepare(`
SELECT data FROM crawl_results
WHERE feed_id = ?
ORDER BY crawled_at DESC
LIMIT 1
`).get(feedId)
return row ? JSON.parse(row.data) : null
}
async getAll(): Promise<CrawlResult[]> {
const rows = this.db.prepare(`
SELECT DISTINCT feed_id, data FROM crawl_results
WHERE crawled_at = (
SELECT MAX(crawled_at) FROM crawl_results c2
WHERE c2.feed_id = crawl_results.feed_id
)
`).all()
return rows.map(r => JSON.parse(r.data))
}
async getHistory(feedId: string, limit = 100): Promise<CrawlResult[]> {
const rows = this.db.prepare(`
SELECT data FROM crawl_results
WHERE feed_id = ?
ORDER BY crawled_at DESC
LIMIT ?
`).all(feedId, limit)
return rows.map(r => JSON.parse(r.data))
}
}Types
CrawlResult
interface CrawlResult {
url: string
feedId: string
status: 'healthy' | 'degraded' | 'unhealthy'
crawledAt: string
responseTime: number
httpStatus: number
structureValid: boolean
signatureValid: boolean
feed: LLMFeed | null
errors: string[]
contentHash: string
}CrawlOptions
interface CrawlOptions {
timeout?: number
validateSignature?: boolean
followRedirects?: boolean
userAgent?: string
}ReportOptions
interface ReportOptions {
storage: FeedStorage
format: 'json' | 'html' | 'markdown'
outputPath?: string
title?: string
includeHistory?: boolean
}FeedStorage
interface FeedStorage {
save(result: CrawlResult): Promise<void>
get(feedId: string): Promise<CrawlResult | null>
getAll(): Promise<CrawlResult[]>
getHistory(feedId: string, limit?: number): Promise<CrawlResult[]>
}