Inline Neon dynamic import in all Vercel serverless functions
Browse filesRemove _db.ts shared helper — Vercel bundles each function separately
so shared imports can fail. Each endpoint now does its own dynamic
import('@neondatabase/serverless').
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
frontend/api/health.ts
CHANGED
|
@@ -1,27 +1,14 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
| 7 |
const result = await sql`SELECT count(*) as n FROM pipeline_runs`
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
res.setHeader('Access-Control-Allow-Origin', '*')
|
| 11 |
-
res.json({
|
| 12 |
-
status: 'ok',
|
| 13 |
-
service: 'market-intelligence-agent',
|
| 14 |
-
version: '1.0.0',
|
| 15 |
-
pipeline_data: hasData,
|
| 16 |
-
source: 'neon',
|
| 17 |
-
})
|
| 18 |
} catch (e: any) {
|
| 19 |
-
res.json({
|
| 20 |
-
status: 'ok',
|
| 21 |
-
service: 'market-intelligence-agent',
|
| 22 |
-
version: '1.0.0',
|
| 23 |
-
pipeline_data: false,
|
| 24 |
-
source: 'neon-error',
|
| 25 |
-
})
|
| 26 |
}
|
| 27 |
}
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.json({ status: 'ok', pipeline_data: false, error: 'no DATABASE_URL' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
const result = await sql`SELECT count(*) as n FROM pipeline_runs`
|
| 10 |
+
res.json({ status: 'ok', pipeline_data: Number(result[0]?.n) > 0, runs: Number(result[0]?.n), source: 'neon' })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
} catch (e: any) {
|
| 12 |
+
res.json({ status: 'ok', pipeline_data: false, error: e.message })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
}
|
| 14 |
}
|
frontend/api/market-prices.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
const prices = await sql`
|
| 8 |
SELECT DISTINCT ON (mandi_id, commodity_id)
|
| 9 |
run_id, mandi_id, commodity_id, date, source, price_rs,
|
|
@@ -12,10 +15,9 @@ export default async function handler(req: VercelRequest, res: VercelResponse) {
|
|
| 12 |
ORDER BY mandi_id, commodity_id, created_at DESC
|
| 13 |
`
|
| 14 |
|
| 15 |
-
// Enrich with mandi/commodity names from config
|
| 16 |
const enriched = prices.map((p: any) => ({
|
| 17 |
mandi_id: p.mandi_id,
|
| 18 |
-
mandi_name: p.mandi_id,
|
| 19 |
commodity_id: p.commodity_id,
|
| 20 |
commodity_name: p.commodity_id,
|
| 21 |
price_rs: p.price_rs,
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.status(500).json({ error: 'DATABASE_URL not set' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
+
|
| 10 |
const prices = await sql`
|
| 11 |
SELECT DISTINCT ON (mandi_id, commodity_id)
|
| 12 |
run_id, mandi_id, commodity_id, date, source, price_rs,
|
|
|
|
| 15 |
ORDER BY mandi_id, commodity_id, created_at DESC
|
| 16 |
`
|
| 17 |
|
|
|
|
| 18 |
const enriched = prices.map((p: any) => ({
|
| 19 |
mandi_id: p.mandi_id,
|
| 20 |
+
mandi_name: p.mandi_id,
|
| 21 |
commodity_id: p.commodity_id,
|
| 22 |
commodity_name: p.commodity_id,
|
| 23 |
price_rs: p.price_rs,
|
frontend/api/pipeline-runs.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
| 7 |
const runs = await sql`
|
| 8 |
SELECT run_id, started_at, finished_at, status, duration_sec,
|
| 9 |
total_cost_usd, mandis_count, commodities_count, step_results
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.status(500).json({ error: 'DATABASE_URL not set' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
const runs = await sql`
|
| 10 |
SELECT run_id, started_at, finished_at, status, duration_sec,
|
| 11 |
total_cost_usd, mandis_count, commodities_count, step_results
|
frontend/api/pipeline-stats.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
const runs = await sql`
|
| 9 |
SELECT run_id, started_at, status, duration_sec, total_cost_usd,
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.status(500).json({ error: 'DATABASE_URL not set' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
|
| 10 |
const runs = await sql`
|
| 11 |
SELECT run_id, started_at, status, duration_sec, total_cost_usd,
|
frontend/api/price-forecast.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
| 7 |
const forecasts = await sql`
|
| 8 |
SELECT DISTINCT ON (mandi_id, commodity_id, horizon_days)
|
| 9 |
run_id, mandi_id, commodity_id, forecast_date, horizon_days,
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.status(500).json({ error: 'DATABASE_URL not set' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
const forecasts = await sql`
|
| 10 |
SELECT DISTINCT ON (mandi_id, commodity_id, horizon_days)
|
| 11 |
run_id, mandi_id, commodity_id, forecast_date, horizon_days,
|
frontend/api/sell-recommendations.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
| 2 |
-
import { getDb } from './_db'
|
| 3 |
|
| 4 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 5 |
try {
|
| 6 |
-
const
|
|
|
|
|
|
|
|
|
|
| 7 |
const recs = await sql`
|
| 8 |
SELECT DISTINCT ON (farmer_id)
|
| 9 |
run_id, farmer_id, commodity_id, best_mandi_id, best_timing,
|
|
|
|
| 1 |
import type { VercelRequest, VercelResponse } from '@vercel/node'
|
|
|
|
| 2 |
|
| 3 |
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
| 4 |
try {
|
| 5 |
+
const dbUrl = process.env.DATABASE_URL
|
| 6 |
+
if (!dbUrl) return res.status(500).json({ error: 'DATABASE_URL not set' })
|
| 7 |
+
const { neon } = await import('@neondatabase/serverless')
|
| 8 |
+
const sql = neon(dbUrl)
|
| 9 |
const recs = await sql`
|
| 10 |
SELECT DISTINCT ON (farmer_id)
|
| 11 |
run_id, farmer_id, commodity_id, best_mandi_id, best_timing,
|