51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import "server-only";
|
|
|
|
import { z } from "zod";
|
|
|
|
const featurePricingSchema = z.object({
|
|
feature_key: z.string(),
|
|
model_tier: z.enum(["standard", "premium", "internal"]),
|
|
credit_cost: z.number().int().positive(),
|
|
version: z.number().int().positive(),
|
|
});
|
|
|
|
type PricingClient = {
|
|
rpc(rpcName: string, args: Record<string, unknown>): PromiseLike<{
|
|
data: unknown;
|
|
error: { message: string } | null;
|
|
}>;
|
|
};
|
|
|
|
export class FeaturePricingError extends Error {
|
|
readonly code: string;
|
|
|
|
constructor(code: string) {
|
|
super(`Feature pricing failed: ${code}`);
|
|
this.name = "FeaturePricingError";
|
|
this.code = code;
|
|
}
|
|
}
|
|
|
|
export type FeaturePricing = z.infer<typeof featurePricingSchema>;
|
|
|
|
export async function resolveFeaturePricing(
|
|
accounting: PricingClient,
|
|
featureKey: FeaturePricing["feature_key"],
|
|
modelId: string,
|
|
): Promise<FeaturePricing> {
|
|
try {
|
|
const { data, error } = await accounting.rpc("resolve_feature_pricing", {
|
|
p_feature_key: featureKey,
|
|
p_model_id: modelId,
|
|
});
|
|
const row = Array.isArray(data) ? data[0] : data;
|
|
const parsed = featurePricingSchema.safeParse(row);
|
|
if (error) throw new FeaturePricingError(error.message);
|
|
if (!parsed.success) throw new FeaturePricingError("feature_pricing_invalid_response");
|
|
return parsed.data;
|
|
} catch (error) {
|
|
if (error instanceof FeaturePricingError) throw error;
|
|
throw new FeaturePricingError(error instanceof Error ? error.message : "feature_pricing_unavailable");
|
|
}
|
|
}
|