Files
songs2vid/lib/entitlements.ts
T

62 lines
1.9 KiB
TypeScript

import { Plan } from "@prisma/client";
import { getPlanLimits } from "./plans";
import { hasProFeatures } from "./edition";
import {
requiresArtTrackLayoutEntitlement,
type LayoutSettings,
} from "./layout";
import {
PREMIUM_REQUIRED_CODE,
requiresCustomWatermarkEntitlement,
type WatermarkSettings,
} from "./watermark";
export class PremiumRequiredError extends Error {
readonly code = PREMIUM_REQUIRED_CODE;
readonly status = 403;
constructor(message: string) {
super(message);
this.name = "PremiumRequiredError";
}
}
export function assertCustomWatermarkAllowed(plan: Plan, settings: WatermarkSettings) {
if (!requiresCustomWatermarkEntitlement(settings)) return;
if (getPlanLimits(plan).customWatermark || hasProFeatures(plan)) return;
throw new PremiumRequiredError(
"Custom watermark, typography, logo overlay, and position controls require Pro.",
);
}
export function assertArtTrackLayoutAllowed(plan: Plan, settings: LayoutSettings) {
if (!requiresArtTrackLayoutEntitlement(settings)) return;
if (getPlanLimits(plan).artTrackLayouts || hasProFeatures(plan)) return;
throw new PremiumRequiredError(
"Blurred backgrounds and art-track layout templates require Pro.",
);
}
export function assertPerItemImagesAllowed(
plan: Plan,
sharedImagePath: string,
itemImagePaths: Array<string | null | undefined>,
) {
const unique = new Set(
itemImagePaths
.map((p) => (p && p.trim() ? p.trim() : sharedImagePath))
.filter(Boolean),
);
// More than one distinct cover in the batch → Pro
if (unique.size <= 1) return;
if (getPlanLimits(plan).perItemImages || hasProFeatures(plan)) return;
throw new PremiumRequiredError(
"Matching a unique image to each audio file requires Pro. Free plan uses one shared cover image.",
);
}
export function premiumRequiredResponse(message: string) {
return {
error: message,
code: PREMIUM_REQUIRED_CODE,
};
}