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 // checks: z.number().default(0),
59 })
60 .nullish(),
61 })
62 .transform((val) => {
63 return {
64 ...val,
65 limits: limitsSchema.parse({
66 ...allPlans[val.plan].limits,
67 /**
68 * override the default plan limits
69 * allows us to set custom limits for a workspace
70 */
71 ...val.limits,
72 }),
73 };
74 });
75
76export const insertWorkspaceSchema = createSelectSchema(workspace);
77
78export type Workspace = z.infer<typeof selectWorkspaceSchema>;
79export type WorkspacePlan = z.infer<typeof workspacePlanSchema>;
80export type WorkspaceRole = z.infer<typeof workspaceRoleSchema>;