ZeroCN

Zero standardized zod schema.

Usage

Install package

pnpm dlx shadcn@latest add https://zerocn.zeroopensource.org/r/zero-schema.json

Install package (workspace)

pnpm --filter=$WORKSPACE shadcn add https://zerocn.zeroopensource.org/r/zero-schema.json

Import and use

import { ZeroSchema } from "@/lib/zero-schema";
import { z } from "zod";

const inputs = ZeroSchema.pick({
  email: true
  password: true
});

const inputs2 = z.object({
  email: ZeroSchema.shape.email,
  password: ZeroSchema.shape.password,
});

type email = ZeroSchema["email"];

const parsedInputs = inputs.parse({ email: "[email protected]", password: "123" })

Supported types

https://github.com/zeroopensource/zero-zerocn/blob/main/packages/zero-zerocn/src/registry/new-york/items/zero-schema/zero-schema.ts

zero-schema.ts
import { z } from "zod";

export const ZeroSchemaPrimitives = z.object({
  // #region env
  /** NODE_ENV ref: https://nextjs.org/docs/pages/guides/environment-variables */
  NODE_ENV: z.enum(["development", "test", "staging", "production"]),
  PORT: z.coerce.number(),
  /** LOG_LEVEL ref: https://github.com/pinojs/pino */
  LOG_LEVEL: z.enum([
    "trace",
    "debug",
    "info",
    "warn",
    "error",
    "fatal",
    "silent",
  ]),
  /** DATABASE ref: https://orm.drizzle.team/docs/tutorials/drizzle-with-vercel-edge-functions */
  DATABASE_URL: z.string(),
  /** DATABASE ref: https://orm.drizzle.team/docs/tutorials/drizzle-with-vercel-edge-functions */
  DATABASE_AUTH_TOKEN: z.string().optional(),
  /** BETTER_AUTH ref: https://www.better-auth.com/docs/installation */
  BETTER_AUTH_URL: z.string(),
  /** BETTER_AUTH ref: https://www.better-auth.com/docs/installation */
  BETTER_AUTH_SECRET: z.string(),
  /** https://www.better-auth.com/docs/plugins/polar */
  POLAR_ACCESS_TOKEN: z.string(),
  /** https://nodemailer.com/usage */
  SMTP_HOST: z.string().optional(),
  SMTP_PORT: z.coerce.number().optional(),
  SMTP_SERVICE: z.string(),
  SMTP_PASSWORD: z.string(),
  SMTP_NAME: z.string(),
  SMTP_EMAIL: z.string(),
  // #endregion

  // #region date types
  date: z.iso.date(),
  time: z.iso.time(),
  dateTime: z.iso.datetime(),
  /** timeZone IANA ref: https://github.com/date-fns/date-fns/blob/main/scripts/test/tzIANA.ts */
  timeZone: z.string(),
  // #endregion

  summary: z.string(),
  location: z.string(),
  /** recurrence ref: http://tools.ietf.org/html/rfc5545#section-3.8.5 */
  recurrence: z.array(z.string()),
  email: z.email(),
  password: z.string().min(1, { message: "Password required" }),
  newPassword: z
    .string()
    .min(8, "Password must be at least 8 characters long")
    .max(128, "Password must be at most 128 characters long")
    .regex(/[a-z]/, "Password must include at least one lowercase letter")
    .regex(/[A-Z]/, "Password must include at least one uppercase letter")
    .regex(/[0-9]/, "Password must include at least one number")
    .regex(
      /[^a-zA-Z0-9]/,
      "Password must include at least one special character"
    )
    // biome-ignore lint/performance/useTopLevelRegex: Intentional
    .refine((val) => !/\s/.test(val), "Password must not contain spaces"),
});
export type ZeroSchemaPrimitives = z.infer<typeof ZeroSchemaPrimitives>;

export const NewConfirmedPasswordSchema = z
  .object({
    newPassword: ZeroSchemaPrimitives.shape.newPassword,
    confirmPassword: z.string(),
  })
  .refine((data) => data.newPassword === data.confirmPassword, {
    message: "Passwords do not match",
    path: ["confirmPassword"],
  });

/**
  googleCalendarEvent ref: 
  https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/gapi.calendar
  https://developers.google.com/workspace/calendar/api/v3/reference/events
  */
export const GoogleCalendarEventSchema = z.object({
  summary: ZeroSchemaPrimitives.shape.summary,
  location: ZeroSchemaPrimitives.shape.location.optional(),
  recurrence: ZeroSchemaPrimitives.shape.recurrence,
  start: z.xor([
    ZeroSchemaPrimitives.pick({
      date: true,
      timeZone: true,
    }),
    ZeroSchemaPrimitives.pick({
      dateTime: true,
      timeZone: true,
    }),
  ]),
  end: z.xor([
    ZeroSchemaPrimitives.pick({
      date: true,
      timeZone: true,
    }),
    ZeroSchemaPrimitives.pick({
      dateTime: true,
      timeZone: true,
    }),
  ]),
  attendees: z.array(
    z.object({
      email: z.email(),
    })
  ),
});

export const BookSchema = z.object({});

export const AudioSchema = z.object({});

export const VideoSchema = z.object({});

export const BlogPostSchema = z.object({});

export const BookingSchema = z.object({});

export const ZeroSchema = z.object({
  ...ZeroSchemaPrimitives.shape,
  newConfirmedPassword: NewConfirmedPasswordSchema,
  googleCalendarEvent: GoogleCalendarEventSchema,
});
export type ZeroSchema = z.infer<typeof ZeroSchema>;

On this page