Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
/**
|
|
* Pure plan-cohort classifiers (no $lib) — mirrors billing A1 PAYG vs Legacy vs Growth.
|
|
* Used by admin-plan-permissions and unit tests.
|
|
*/
|
|
|
|
export function isLegacyPlanNamePure(name: string | null | undefined): boolean {
|
|
const n = (name ?? "").trim().toLowerCase();
|
|
if (!n) return false;
|
|
if (n === "legacy") return true;
|
|
if (n.includes("a1 slovenija")) return true;
|
|
if (n === "a1" || n.startsWith("a1 ") || n.startsWith("a1-") || n.startsWith("a1_")) return true;
|
|
return false;
|
|
}
|
|
|
|
export type PlanCohortFlags = {
|
|
name: string;
|
|
is_custom?: boolean;
|
|
is_legacy?: boolean;
|
|
};
|
|
|
|
/** Restricted Legacy matrix (processing off). */
|
|
export function isRestrictedLegacyPlan(plan: PlanCohortFlags | null | undefined): boolean {
|
|
if (!plan) return false;
|
|
if (plan.is_legacy === true) return true;
|
|
const n = (plan.name ?? "").trim().toLowerCase();
|
|
if (n === "legacy") return true;
|
|
if (plan.is_custom) return false;
|
|
return isLegacyPlanNamePure(plan.name);
|
|
}
|
|
|
|
/** A1* PAYG client deal (processing on; stores/marketing/integrations off). */
|
|
export function isA1PaygPlanPure(plan: PlanCohortFlags | null | undefined): boolean {
|
|
if (!plan) return false;
|
|
if (plan.is_legacy === true) return false;
|
|
if (!plan.is_custom) return false;
|
|
const n = (plan.name ?? "").trim().toLowerCase();
|
|
if (n === "legacy") return false;
|
|
return isLegacyPlanNamePure(plan.name);
|
|
}
|
|
|
|
export function isA1PaygDeniedKey(key: string): boolean {
|
|
if (
|
|
key === "dashboard.etl_gaps" ||
|
|
key === "dashboard.store_reconnect" ||
|
|
key === "dashboard.migrated_checklist"
|
|
) {
|
|
return true;
|
|
}
|
|
return key.startsWith("stores.") || key.startsWith("marketing.") || key.startsWith("integrations.");
|
|
}
|
|
|
|
/** Resolve whether a feature is ON by default for the named cohort. */
|
|
export function defaultAllowsFeature(
|
|
plan: PlanCohortFlags,
|
|
key: string,
|
|
opts?: { freeOff?: ReadonlySet<string>; starterOff?: ReadonlySet<string>; legacyAllow?: ReadonlySet<string> }
|
|
): boolean {
|
|
if (isRestrictedLegacyPlan(plan)) {
|
|
if (opts?.legacyAllow) return opts.legacyAllow.has(key);
|
|
// Fallback for audit keys when allowlist not provided.
|
|
if (key === "processing.monitor" || key.startsWith("stores.") || key.startsWith("marketing.") || key.startsWith("integrations.") || key.startsWith("support.")) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
if (isA1PaygPlanPure(plan)) {
|
|
return !isA1PaygDeniedKey(key);
|
|
}
|
|
const n = (plan.name ?? "").trim().toLowerCase();
|
|
if (n === "free" && opts?.freeOff?.has(key)) return false;
|
|
if ((n === "starter" || n === "plus") && opts?.starterOff?.has(key)) return false;
|
|
return true;
|
|
}
|