/** * Extracted data from a webpage */ type ExtractedData = Record; /** * Recipe Field Definition * Describes a trackable field that the recipe extracts */ interface RecipeField { /** Field type for formatting and comparison */ type: 'string' | 'number' | 'boolean' | 'currency' | 'url' | 'date'; /** Human-readable label */ label: string; /** Description of what this field represents */ description?: string; /** Is this a primary field shown by default? */ primary?: boolean; /** Should changes to this field be ignored? (noise filtering) */ noise?: boolean; /** Currency code for currency fields */ currency?: string; } /** * Default Alert Condition * Pre-configured alert triggers users can enable */ interface DefaultAlert { /** Unique identifier for this alert type */ id: string; /** Human-readable label */ label: string; /** Description of when this triggers */ description: string; /** Condition expression (e.g., "price < previous.price") */ when: string; /** Icon for UI display */ icon?: string; } /** * Rich example with metadata for better UX */ interface RecipeExample { /** The URL to track */ url: string; /** Human-readable title */ title: string; /** Optional subtitle (e.g., price, status) */ subtitle?: string; /** Optional image/logo URL */ image?: string; } /** * Recipe Metadata * Information about the recipe for catalog/discovery */ interface RecipeMeta { /** Recipe slug (unique identifier) */ slug: string; /** Display name */ name: string; /** Short description */ description: string; /** Long description for recipe page */ longDescription?: string; /** Icon URL or emoji */ icon: string; /** Category slug */ category: RecipeCategory; /** Tags for search/filtering */ tags?: string[]; /** GitHub usernames of maintainers */ maintainers: string[]; /** When recipe was added */ createdAt?: string; /** Last update date */ updatedAt?: string; /** Rich examples with titles and metadata */ richExamples: RecipeExample[]; } /** * Recipe Definition * Complete recipe including metadata, matching, fields, and extraction */ interface Recipe { /** Recipe metadata */ meta: RecipeMeta; /** URL matching - regex or function */ match: RegExp | ((url: string) => boolean); /** Fields this recipe extracts */ fields: Record; /** Pre-configured alert conditions */ defaultAlerts?: DefaultAlert[]; /** Extract data from HTML */ extract: (html: string, url: string) => Promise; /** Optional: Transform URL before fetching (e.g., to API endpoint) */ transformUrl?: (url: string) => string; /** Optional: Custom headers for fetch */ headers?: Record; /** Optional: Requires JavaScript rendering */ requiresJs?: boolean; } /** * Helper to define a recipe with proper typing */ declare function defineRecipe(recipe: Recipe): Recipe; /** * Recipe Categories */ declare const RECIPE_CATEGORIES: { readonly ecommerce: { readonly name: "E-commerce"; readonly icon: "🛒"; readonly description: "Price drops, stock alerts, and deal tracking"; }; readonly developer: { readonly name: "Developer"; readonly icon: "💻"; readonly description: "GitHub releases, package updates, and changelogs"; }; readonly jobs: { readonly name: "Jobs"; readonly icon: "💼"; readonly description: "Job postings and career page updates"; }; readonly social: { readonly name: "Social"; readonly icon: "📱"; readonly description: "Social media profiles and content"; }; readonly news: { readonly name: "News"; readonly icon: "📰"; readonly description: "News sites, blogs, and publications"; }; readonly finance: { readonly name: "Finance"; readonly icon: "📈"; readonly description: "Stock prices, SEC filings, and financial data"; }; readonly status: { readonly name: "Status Pages"; readonly icon: "🟢"; readonly description: "Service status and incident monitoring"; }; readonly entertainment: { readonly name: "Entertainment"; readonly icon: "🎬"; readonly description: "Movies, TV shows, games, and media"; }; readonly travel: { readonly name: "Travel"; readonly icon: "✈️"; readonly description: "Flight prices, hotel rates, and travel deals"; }; readonly government: { readonly name: "Government"; readonly icon: "🏛️"; readonly description: "Government sites, permits, and public data"; }; readonly other: { readonly name: "Other"; readonly icon: "🌐"; readonly description: "Miscellaneous websites"; }; }; type RecipeCategory = keyof typeof RECIPE_CATEGORIES; /** * Shared helper functions for recipe extraction */ /** * Extract meta tags from HTML */ declare function extractMetaTags(html: string): Record; /** * Extract JSON-LD structured data from HTML */ declare function extractJsonLd(html: string): any[]; /** * Parse price string to number */ declare function parsePrice(priceStr: string | undefined | null): number | undefined; /** * Extract first matching regex group */ declare function extractFirst(html: string, regex: RegExp): string | undefined; /** * Extract all matching regex groups */ declare function extractAll(html: string, regex: RegExp): string[]; /** * Decode HTML entities */ declare function decodeHtmlEntities(text: string): string; /** * Parse abbreviated numbers (e.g., "1.2k", "45.6k", "1.2M") */ declare function parseAbbreviatedNumber(str: string): number; /** * Clean whitespace from text */ declare function cleanText(text: string): string; /** * Extract domain from URL */ declare function extractDomain(url: string): string; interface ValidationError { recipe: string; field: string; message: string; severity: 'error' | 'warning'; } interface ValidationResult { valid: boolean; errors: ValidationError[]; warnings: ValidationError[]; } /** * Validates a single recipe for completeness and correctness */ declare function validateRecipe(recipe: Recipe): ValidationResult; /** * Validates all recipes and checks for cross-recipe issues */ declare function validateAllRecipes(recipes: Recipe[]): ValidationResult; /** * Tests that extract function works without crashing */ declare function testExtractFunction(recipe: Recipe, html: string, url: string): Promise<{ success: boolean; data?: Record; error?: string; }>; declare const amazonRecipe: Recipe; declare const ebayRecipe: Recipe; declare const githubRecipe: Recipe; declare const hackernewsRecipe: Recipe; declare const npmRecipe: Recipe; declare const redditRecipe: Recipe; declare const twitterRecipe: Recipe; declare const youtubeRecipe: Recipe; declare const genericRecipe: Recipe; /** * All available recipes (excluding generic) */ declare const recipes: Recipe[]; /** * All recipes including generic fallback */ declare const allRecipes: Recipe[]; /** * Get recipe by slug */ declare function getRecipeBySlug(slug: string): Recipe | undefined; /** * Get recipe for a URL */ declare function getRecipeForUrl(url: string): Recipe; /** * Client-safe example with metadata */ interface ClientRecipeExample { url: string; title: string; subtitle?: string; image?: string; } /** * Client-safe recipe data (no functions, serializable) * Use this to send recipe data to the browser */ interface ClientRecipe { slug: string; name: string; description: string; icon: string; category: string; tags: string[]; /** Rich examples with titles and metadata */ richExamples: ClientRecipeExample[]; /** Regex source string for URL matching */ matchPattern: string | null; fields: Array<{ key: string; label: string; type: string; primary: boolean; }>; defaultAlerts: Array<{ id: string; label: string; description: string; when: string; icon?: string; }>; } /** * Convert a recipe to client-safe format */ declare function toClientRecipe(recipe: Recipe): ClientRecipe; /** * Get all recipes in client-safe format */ declare function getClientRecipes(): ClientRecipe[]; /** * Get client-safe generic recipe */ declare function getClientGenericRecipe(): ClientRecipe; export { type ClientRecipe, type ClientRecipeExample, type DefaultAlert, type ExtractedData, RECIPE_CATEGORIES, type Recipe, type RecipeCategory, type RecipeExample, type RecipeField, type RecipeMeta, type ValidationError, type ValidationResult, allRecipes, amazonRecipe, cleanText, decodeHtmlEntities, defineRecipe, ebayRecipe, extractAll, extractDomain, extractFirst, extractJsonLd, extractMetaTags, genericRecipe, getClientGenericRecipe, getClientRecipes, getRecipeBySlug, getRecipeForUrl, githubRecipe, hackernewsRecipe, npmRecipe, parseAbbreviatedNumber, parsePrice, recipes, redditRecipe, testExtractFunction, toClientRecipe, twitterRecipe, validateAllRecipes, validateRecipe, youtubeRecipe };