Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 15 additions & 21 deletions competitor-analysis/app/api/scrape-pricing/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextRequest } from 'next/server';
import type { DetailLevel, PricingTier, CompetitorPricing } from '@/types';
import { TinyFish } from '@tiny-fish/sdk';
import { TinyFish, EventType, RunStatus } from '@tiny-fish/sdk';

interface Competitor {
id: string;
Expand Down Expand Up @@ -361,14 +361,11 @@ async function scrapePricingPage(
browser_profile: 'lite',
});

for await (const rawEvent of stream) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const event: any = rawEvent;

for await (const event of stream) {
// Capture streaming URL and send update
if (event.streamingUrl && !streamingUrl) {
streamingUrl = event.streamingUrl;
console.log(`[Scrape] ${competitor.name} got streamingUrl:`, streamingUrl);
if (event.type === EventType.STREAMING_URL && !streamingUrl) {
streamingUrl = event.streaming_url;
console.log(`[Scrape] ${competitor.name} got streaming_url:`, streamingUrl);
await sendEvent({
type: 'competitor_streaming',
competitor: competitor.name,
Expand All @@ -378,24 +375,26 @@ async function scrapePricingPage(
});
}

// Forward step updates (keep old heuristics)
if (event.type === 'STEP' || event.purpose || event.action) {
const stepMessage = event.purpose || event.action || event.message || 'Processing...';
// Forward step updates
if (event.type === EventType.PROGRESS) {
await sendEvent({
type: 'competitor_step',
competitor: competitor.name,
id: competitor.id,
step: stepMessage,
step: event.purpose,
timestamp: Date.now(),
});
}

// Handle completion
if (event.type === 'COMPLETE' && event.status === 'COMPLETED') {
const rawResult = event.resultJson ?? event.result ?? {};
// Handle completion. A failed run arrives as COMPLETE with a non-COMPLETED
// status; there is no separate error event.
if (event.type === EventType.COMPLETE) {
if (event.status !== RunStatus.COMPLETED) {
throw new Error(event.error?.message || 'Extraction failed');
}

// Transform to new schema
const transformedData = transformToNewSchema(rawResult, competitor.name, competitor.url);
const transformedData = transformToNewSchema(event.result ?? {}, competitor.name, competitor.url);

finalResult = {
company: competitor.name,
Expand All @@ -414,11 +413,6 @@ async function scrapePricingPage(
});
break;
}

// Handle errors
if (event.type === 'ERROR' || event.status === 'FAILED') {
throw new Error(event.message || 'Extraction failed');
}
}

return finalResult;
Expand Down