15await runMigrations();
1617// API routes
18app.route('/api/recipes', recipesRoutes);
19app.route('/api/parse', parseRoutes);
2021// Health check endpoint
22app.get('/api/health', (c) => {
23return c.json({ status: 'ok', timestamp: new Date().toISOString() });
24});
2526// Test delete endpoint
27app.get('/api/test-delete', async (c) => {
28try {
29const { createRecipe, deleteRecipe, getAllRecipes } = await import('./database/queries.ts');
cardamonRecipeView.tsx1 match
34const handleDelete = async () => {
35try {
36const response = await fetch(`/api/recipes/${recipe.id}`, {
37method: 'DELETE'
38});
cardamonRecipeList.tsx1 match
48const handleDelete = async (recipeId: number) => {
49try {
50const response = await fetch(`/api/recipes/${recipeId}`, {
51method: 'DELETE'
52});
33setState(prev => ({ ...prev, loading: true, error: null }));
34try {
35const response = await fetch('/api/recipes');
36const data = await response.json();
37
cardamonrecipes.ts20 matches
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import type { Recipe, RecipeFilters, ApiResponse } from "../../shared/types.ts";
3import {
4createRecipe,
2829const recipes = await getAllRecipes(filters);
30return c.json({ success: true, data: recipes } as ApiResponse<Recipe[]>);
31} catch (error) {
32console.error('Error fetching recipes:', error);
33return c.json({ success: false, error: 'Failed to fetch recipes' } as ApiResponse, 500);
34}
35});
40const id = parseInt(c.req.param('id'));
41if (isNaN(id)) {
42return c.json({ success: false, error: 'Invalid recipe ID' } as ApiResponse, 400);
43}
4445const recipe = await getRecipeById(id);
46if (!recipe) {
47return c.json({ success: false, error: 'Recipe not found' } as ApiResponse, 404);
48}
4950return c.json({ success: true, data: recipe } as ApiResponse<Recipe>);
51} catch (error) {
52console.error('Error fetching recipe:', error);
53return c.json({ success: false, error: 'Failed to fetch recipe' } as ApiResponse, 500);
54}
55});
65success: false,
66error: 'Missing required fields: title, ingredients, and steps are required'
67} as ApiResponse, 400);
68}
6972success: false,
73error: 'At least one ingredient is required'
74} as ApiResponse, 400);
75}
7679success: false,
80error: 'At least one cooking step is required'
81} as ApiResponse, 400);
82}
8384const recipe = await createRecipe(recipeData);
85return c.json({ success: true, data: recipe } as ApiResponse<Recipe>, 201);
86} catch (error) {
87console.error('Error creating recipe:', error);
88return c.json({ success: false, error: 'Failed to create recipe' } as ApiResponse, 500);
89}
90});
95const id = parseInt(c.req.param('id'));
96if (isNaN(id)) {
97return c.json({ success: false, error: 'Invalid recipe ID' } as ApiResponse, 400);
98}
99102const recipe = await updateRecipe(id, updates);
103if (!recipe) {
104return c.json({ success: false, error: 'Recipe not found' } as ApiResponse, 404);
105}
106107return c.json({ success: true, data: recipe } as ApiResponse<Recipe>);
108} catch (error) {
109console.error('Error updating recipe:', error);
110return c.json({ success: false, error: 'Failed to update recipe' } as ApiResponse, 500);
111}
112});
117const id = parseInt(c.req.param('id'));
118if (isNaN(id)) {
119return c.json({ success: false, error: 'Invalid recipe ID' } as ApiResponse, 400);
120}
121122const deleted = await deleteRecipe(id);
123if (!deleted) {
124return c.json({ success: false, error: 'Recipe not found' } as ApiResponse, 404);
125}
126127return c.json({ success: true, data: { deleted: true } } as ApiResponse);
128} catch (error) {
129console.error('Error deleting recipe:', error);
130return c.json({ success: false, error: 'Failed to delete recipe' } as ApiResponse, 500);
131}
132});
38}
3940export interface ApiResponse<T = any> {
41success: boolean;
42data?: T;
2021- **Frontend**: React with TypeScript, TailwindCSS
22- **Backend**: Hono API framework
23- **Database**: SQLite for recipe storage
24- **AI**: OpenAI GPT-4 for intelligent recipe parsing
35โ โ โโโ recipes.ts # Recipe CRUD operations
36โ โ โโโ parse.ts # Recipe parsing endpoints
37โ โโโ index.ts # Main API entry point
38โโโ frontend/
39โ โโโ components/
48```
4950## API Endpoints
5152- `POST /api/parse/url` - Parse recipe from URL
53- `POST /api/parse/pdf` - Parse recipe from PDF
54- `POST /api/parse/image` - Parse recipe from image
55- `GET /api/recipes` - Get all recipes
56- `POST /api/recipes` - Save a recipe
57- `GET /api/recipes/:id` - Get specific recipe
58- `PUT /api/recipes/:id` - Update recipe
59- `DELETE /api/recipes/:id` - Delete recipe
6061## Usage
5Generated using Val.town
67Relies on the Zoomin Software bundle API to fetch the data using the JSON API, and then pluck and render the HTML part.
1export default async function (req: Request): Promise<Response> {
2try {
3const response = await fetch("https://help-be.zerto.com/api/bundle/Lifecycle.Matrix.HTML/page/product_version_lifecycle_matrix_for_zerto.html");
4
5if (!response.ok) {
Loudaily_lineup_scheduler.tsx24 matches
22}
2324export interface YahooAPIConfig {
25access_token: string;
26refresh_token: string;
99}
100101// Initialize Yahoo Fantasy API client
102const yahooAPI = new YahooFantasyAPIClient(tokenData, this.tokenStorage, userId);
103104// Get user's leagues
105const leagues = await yahooAPI.getUserLeagues(userId);
106console.log(`๐๏ธ Found ${leagues.length} leagues for user ${userId}`);
107111112// Get user's team in this league
113const teamKey = await yahooAPI.getTeamKey(userId, league.league_id);
114if (!teamKey) {
115throw new Error(`Could not find team key for league ${league.league_id}`);
117118// Schedule pitchers for today
119const scheduleResult = await this.schedulePitchersForTeam(yahooAPI, teamKey, date);
120121results.leagues_processed.push({
139}
140141private async schedulePitchersForTeam(yahooAPI: YahooFantasyAPIClient, teamKey: string, date: Date) {
142// Get today's probable pitchers from MLB API
143const probablePitchers = await this.getTodaysProbablePitchers(date);
144console.log(`๐ฏ Found ${probablePitchers.length} probable pitchers for ${date.toDateString()}`);
145146// Get current team roster
147const roster = await yahooAPI.getTeamRoster(teamKey);
148console.log(`๐ฅ Team roster has ${roster.length} players`);
149166for (const change of optimization.changes) {
167try {
168await yahooAPI.setPlayerPosition(teamKey, change.playerId, change.newPosition);
169results.pitchers_scheduled.push(change.playerId);
170results.changes_made.push(change);
186): Promise<Array<{ name: string; team: string; game_time?: string }>> {
187try {
188// Call MLB Stats API for probable pitchers
189const dateStr = date.toISOString().split("T")[0];
190const response = await fetch(
191`https://statsapi.mlb.com/api/v1/schedule?sportId=1&date=${dateStr}&hydrate=probablePitcher`,
192);
193194if (!response.ok) {
195throw new Error(`MLB API error: ${response.status}`);
196}
197440}
441442// Simplified Yahoo Fantasy API client for Val.town
443class YahooFantasyAPIClient {
444private config: YahooAPIConfig;
445private baseUrl = "https://fantasysports.yahooapis.com/fantasy/v2";
446private tokenStorage: LouTokenStorage;
447private userId: string;
448449constructor(config: YahooAPIConfig, tokenStorage: LouTokenStorage, userId: string) {
450this.config = config;
451this.tokenStorage = tokenStorage;
465private async refreshAccessToken(): Promise<void> {
466try {
467const response = await fetch("https://api.login.yahoo.com/oauth2/get_token", {
468method: "POST",
469headers: {
551552if (!retryResponse.ok) {
553throw new Error(`Yahoo API error after refresh: ${retryResponse.status} ${retryResponse.statusText}`);
554}
555558559if (!response.ok) {
560throw new Error(`Yahoo API error: ${response.status} ${response.statusText}`);
561}
562744await this.ensureValidToken();
745746// Yahoo Fantasy API requires XML for roster changes
747const dateStr = new Date().toISOString().split("T")[0];
748776if (!response.ok) {
777const responseText = await response.text();
778console.error(`โ Yahoo API error response: ${responseText}`);
779throw new Error(`Failed to set player position: ${response.status} ${response.statusText}`);
780}
796797// Store results in Val.town's blob storage for history
798await fetch("https://api.val.town/v1/blob/scheduler_results", {
799method: "POST",
800headers: {