Openstatus www.openstatus.dev
at main 94 lines 3.0 kB view raw
1import { FREE_FLY_REGIONS } from "@openstatus/regions"; 2import { z } from "zod"; 3import { monitorPeriodicitySchema, monitorRegionSchema } from "../constants"; 4 5// REMINDER: this is not a database table but just a schema for the limits of the plan 6// default values are set to the free plan limits 7 8export const limitsSchema = z.object({ 9 version: z.undefined(), 10 /** 11 * Monitor limits 12 */ 13 monitors: z.number().prefault(1), 14 "synthetic-checks": z.number().prefault(30), // monthly limits 15 periodicity: monitorPeriodicitySchema.array().prefault(["10m", "30m", "1h"]), 16 "multi-region": z.boolean().prefault(true), 17 "max-regions": z.number().prefault(6), 18 "data-retention": z 19 .enum(["14 days", "3 months", "12 months", "24 months"]) 20 .prefault("14 days"), 21 regions: monitorRegionSchema.array().prefault(FREE_FLY_REGIONS), 22 "private-locations": z.boolean().prefault(false), 23 screenshots: z.boolean().prefault(false), 24 "response-logs": z.boolean().prefault(false), 25 otel: z.boolean().prefault(false), 26 /** 27 * Status page limits 28 */ 29 "status-pages": z.number().prefault(1), 30 "page-components": z.number().prefault(3), 31 maintenance: z.boolean().prefault(true), 32 "monitor-values-visibility": z.boolean().prefault(true), 33 "status-subscribers": z.boolean().prefault(false), 34 "custom-domain": z.boolean().prefault(false), 35 "password-protection": z.boolean().prefault(false), 36 "email-domain-protection": z.boolean().prefault(false), // add-on but required in limits 37 "white-label": z.boolean().prefault(false), 38 /** 39 * Notification limits 40 */ 41 42 notifications: z.boolean().prefault(true), 43 pagerduty: z.boolean().prefault(false), 44 opsgenie: z.boolean().prefault(false), 45 whatsapp: z.boolean().prefault(false), 46 sms: z.boolean().prefault(false), 47 "sms-limit": z.number().prefault(0), 48 "notification-channels": z.number().prefault(1), 49 50 /** 51 * Collaboration limits 52 */ 53 members: z.literal("Unlimited").or(z.number()).prefault(1), 54 "audit-log": z.boolean().prefault(false), 55}); 56 57export type Limits = z.infer<typeof limitsSchema>; 58 59// 60 61const priceSchema = z.object({ 62 USD: z.number(), 63 EUR: z.number(), 64 INR: z.number(), 65}); 66 67export type Price = z.infer<typeof priceSchema>; 68 69export const addons = [ 70 "email-domain-protection", 71 "white-label", 72 "status-pages", 73] as const satisfies Partial<keyof Limits>[]; 74 75export const addonsSchema = z.partialRecord( 76 z.enum(addons), 77 z.object({ 78 price: priceSchema, 79 }), 80) satisfies z.ZodType<Partial<Record<keyof Limits, { price: Price }>>>; 81 82export type Addons = z.infer<typeof addonsSchema>; 83 84/** 85 * Enforces that addon keys in Limits must be set to false in plan configs 86 * (since addons can only be enabled by purchasing them) 87 */ 88export type PlanLimits = { 89 [K in keyof Limits]: K extends keyof Addons 90 ? Limits[K] extends boolean 91 ? false // Force addon boolean fields to false 92 : Limits[K] // Non-boolean fields stay as-is 93 : Limits[K]; // Non-addon fields stay as-is 94};