File size: 3,883 Bytes
88c4c60 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import { NextResponse } from "next/server";
import { getPricing, updatePricing, resetPricing, resetAllPricing } from "@/lib/localDb.js";
import { getDefaultPricing } from "@/shared/constants/pricing.js";
/**
* GET /api/pricing
* Get current pricing configuration (merged user + defaults)
*/
export async function GET() {
try {
const pricing = await getPricing();
return NextResponse.json(pricing);
} catch (error) {
console.error("Error fetching pricing:", error);
return NextResponse.json(
{ error: "Failed to fetch pricing" },
{ status: 500 }
);
}
}
/**
* PATCH /api/pricing
* Update pricing configuration
* Body: { provider: { model: { input: number, output: number, cached: number, ... } } }
*/
export async function PATCH(request) {
try {
const body = await request.json();
// Validate body structure
if (typeof body !== "object" || body === null) {
return NextResponse.json(
{ error: "Invalid pricing data format" },
{ status: 400 }
);
}
// Validate pricing structure
for (const [provider, models] of Object.entries(body)) {
if (typeof models !== "object" || models === null) {
return NextResponse.json(
{ error: `Invalid pricing for provider: ${provider}` },
{ status: 400 }
);
}
for (const [model, pricing] of Object.entries(models)) {
if (typeof pricing !== "object" || pricing === null) {
return NextResponse.json(
{ error: `Invalid pricing for model: ${provider}/${model}` },
{ status: 400 }
);
}
// Validate pricing fields
const validFields = ["input", "output", "cached", "reasoning", "cache_creation"];
for (const [key, value] of Object.entries(pricing)) {
if (!validFields.includes(key)) {
return NextResponse.json(
{ error: `Invalid pricing field: ${key} for ${provider}/${model}` },
{ status: 400 }
);
}
if (typeof value !== "number" || isNaN(value) || value < 0) {
return NextResponse.json(
{ error: `Invalid pricing value for ${key} in ${provider}/${model}: must be non-negative number` },
{ status: 400 }
);
}
}
}
}
const updatedPricing = await updatePricing(body);
return NextResponse.json(updatedPricing);
} catch (error) {
console.error("Error updating pricing:", error);
return NextResponse.json(
{ error: "Failed to update pricing" },
{ status: 500 }
);
}
}
/**
* DELETE /api/pricing
* Reset pricing to defaults
* Query params: ?provider=xxx&model=yyy (optional)
*/
export async function DELETE(request) {
try {
const { searchParams } = new URL(request.url);
const provider = searchParams.get("provider");
const model = searchParams.get("model");
if (provider && model) {
// Reset specific model
await resetPricing(provider, model);
} else if (provider) {
// Reset entire provider
await resetPricing(provider);
} else {
// Reset all pricing
await resetAllPricing();
}
const pricing = await getPricing();
return NextResponse.json(pricing);
} catch (error) {
console.error("Error resetting pricing:", error);
return NextResponse.json(
{ error: "Failed to reset pricing" },
{ status: 500 }
);
}
}
/**
* GET /api/pricing/defaults
* Get default pricing configuration
*/
export async function GET_DEFAULTS() {
try {
const defaultPricing = getDefaultPricing();
return NextResponse.json(defaultPricing);
} catch (error) {
console.error("Error fetching default pricing:", error);
return NextResponse.json(
{ error: "Failed to fetch default pricing" },
{ status: 500 }
);
}
} |