Openstatus
www.openstatus.dev
1import { createSelectSchema } from "drizzle-zod";
2import { z } from "zod";
3
4import { allPlans } from "../plan/config";
5import { limitsSchema } from "../plan/schema";
6import { workspacePlans, workspaceRole } from "./constants";
7import { workspace } from "./workspace";
8
9export const workspacePlanSchema = z.enum(workspacePlans);
10export const workspaceRoleSchema = z.enum(workspaceRole);
11
12/**
13 * Workspace schema with limits and plan
14 */
15export const selectWorkspaceSchema = createSelectSchema(workspace)
16 .extend({
17 limits: z.string().transform((val) => {
18 try {
19 const parsed = JSON.parse(val);
20
21 // Only validate properties that are actually present in the parsed object
22 // This avoids triggering .prefault() for missing properties
23 const validated: Record<string, unknown> = {};
24 const limitsShape = limitsSchema.shape;
25
26 for (const key in parsed) {
27 if (key in limitsShape) {
28 // Validate only the properties that exist in the parsed object
29 const propertySchema = limitsShape[key as keyof typeof limitsShape];
30 const result = propertySchema.safeParse(parsed[key]);
31 if (result.success) {
32 validated[key] = result.data;
33 } else {
34 console.warn(`Invalid value for limits.${key}:`, result.error);
35 // Skip invalid properties instead of failing entirely
36 }
37 }
38 // Unknown properties are ignored
39 }
40
41 return validated;
42 } catch (error) {
43 console.error("Error parsing limits:", error);
44 return {};
45 }
46 }),
47 plan: z
48 .enum(workspacePlans)
49 .nullable()
50 .prefault("free")
51 .transform((val) => val ?? "free"),
52 // REMINDER: workspace usage
53 usage: z
54 .object({
55 monitors: z.number().prefault(0),
56 notifications: z.number().prefault(0),
57 pages: z.number().prefault(0),
58 pageComponents: z.number().prefault(0),
59 // checks: z.number().default(0),
60 })
61 .nullish(),
62 })
63 .transform((val) => {
64 return {
65 ...val,
66 limits: limitsSchema.parse({
67 ...allPlans[val.plan].limits,
68 /**
69 * override the default plan limits
70 * allows us to set custom limits for a workspace
71 */
72 ...val.limits,
73 }),
74 };
75 });
76
77export const insertWorkspaceSchema = createSelectSchema(workspace);
78
79export type Workspace = z.infer<typeof selectWorkspaceSchema>;
80export type WorkspacePlan = z.infer<typeof workspacePlanSchema>;
81export type WorkspaceRole = z.infer<typeof workspaceRoleSchema>;