Build Elevate

Utilities

Zod validation schemas and TypeScript types for authentication and form validation across the monorepo

Utilities Package

The @workspace/utils package provides Zod validation schemas and TypeScript types used across all applications and packages in the monorepo. It's focused on authentication workflows and form validation.

Overview

  • Package: @workspace/utils
  • Location: packages/utils
  • Type Safety: Full TypeScript support
  • Validation: Zod schemas for runtime type checking
  • Date Handling: date-fns for formatting and calculations

Architecture

The utilities package:

  • Centralizes Validation - Single source of truth for auth validation schemas
  • Provides Type Definitions - Type-safe form values inferred from schemas
  • Date Handling - Re-exports from date-fns for formatting and calculations
  • Enables Code Reuse - Modular, composable validation logic
  • Maintains Consistency - Shared validation across all applications

Project Structure

packages/utils/
├── src/
│   ├── helpers/              # Utility functions
│   │   ├── string.ts         # String manipulation (capitalize, truncate, isEmpty)
│   │   ├── number.ts         # Number operations (clamp, round)
│   │   ├── date.ts           # Date helpers (re-exports from date-fns)
│   │   └── index.ts          # Helper exports
│   ├── schemas/              # Zod validation schemas
│   │   ├── auth.ts           # Authentication schemas (email, password, signup, signin, etc.)
│   │   └── index.ts          # Schema exports
│   ├── types/                # TypeScript type definitions
│   │   ├── auth.ts           # Authentication types (inferred from schemas)
│   │   └── index.ts          # Type exports
│   └── index.ts              # Package entry point
├── package.json              # Dependencies and scripts
└── tsconfig.json             # TypeScript configuration

Usage

Importing Utilities

Import specific utilities by category:

// Date helpers (re-exported from date-fns)
import { formatDate, formatDistanceToNow } from "@workspace/utils";

// Validation schemas
import {
  emailSchema,
  passwordSchema,
  signUpSchema,
  signInSchema,
} from "@workspace/utils/schemas";

// Types
import type {
  SignUpFormValues,
  SignInFormValues,
} from "@workspace/utils/types";

Helper Functions

The package includes basic helper functions for string manipulation and number operations (capitalize, truncate, isEmpty, clamp, round). For most use cases, the validation schemas below are the primary focus.

Date Helpers

All date helpers are re-exported from date-fns:

import {
  formatDate,
  formatDistanceToNow,
  formatDuration,
  intervalToDuration,
} from "@workspace/utils/helpers";

// Format a date
const date = new Date("2024-03-23");
formatDate(date); // "Mar 23, 2024" (default format)

// Get relative time
const pastDate = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000);
formatDistanceToNow(pastDate); // "2 days ago"

// Format a duration
formatDuration({ hours: 2, minutes: 30 }); // "2h 30m"

// Calculate interval between dates
intervalToDuration({ start: date1, end: date2 });

Validation Schemas

All validation schemas are defined in packages/utils/src/schemas/auth.ts and focused on authentication workflows.

Available Schemas

The following schemas are available for common authentication flows:

SchemaPurpose
emailSchemaValidate email addresses
passwordSchemaValidate password strength (minimum 8 characters)
nameSchemaValidate user names (3-100 characters)
signUpSchemaComplete sign-up form (email, password, name)
signInSchemaLogin form (email, password)
setPasswordSchemaSet new password with confirmation
changePasswordSchemaChange password with current password verification
updateProfileSchemaUpdate user profile information
deleteAccountSchemaConfirm account deletion
forgotPasswordSchemaRequest password reset
resetPasswordSchemaReset password with token

Usage Examples

import { signUpSchema, signInSchema } from "@workspace/utils/schemas";

// Sign up validation
const signUpResult = signUpSchema.safeParse({
  email: "user@example.com",
  password: "SecurePass123!",
  name: "John Doe",
});

if (!signUpResult.success) {
  console.error("Validation errors:", signUpResult.error.flatten());
}

// Sign in validation
const signInResult = signInSchema.safeParse({
  email: "user@example.com",
  password: "MyPassword123!",
});

if (signInResult.success) {
  const { email, password } = signInResult.data;
}

Common Patterns

TypeScript Types

All types are inferred from Zod schemas using z.infer<typeof schema>:

import { signUpSchema } from "@workspace/utils/schemas";
import type { SignUpFormValues } from "@workspace/utils/types";

// Type-safe form handling
function handleSignUp(data: SignUpFormValues) {
  // data is guaranteed to match schema
  // TypeScript knows: data.name, data.email, data.password all exist
  console.log(data.name, data.email, data.password);
}

// Use the schema to validate and get typed data
const result = signUpSchema.safeParse(userInput);
if (result.success) {
  handleSignUp(result.data); // result.data is typed as SignUpFormValues
}

Available types match their corresponding schemas: SignUpFormValues, SignInFormValues, SetPasswordFormValues, ChangePasswordFormValues, etc.

Use Type-Safe Parsing

Always use safeParse for user input:

// ✓ Good - Handle errors gracefully
import { emailSchema } from "@workspace/utils/schemas";

const result = emailSchema.safeParse(userInput);
if (!result.success) {
  return { error: result.error.flatten() };
}

// ✗ Bad - parse() throws on invalid data
const email = emailSchema.parse(userInput);

Leverage Tree-Shaking

Import from subpaths when possible:

// ✓ Good - Only imported if used
import { signUpSchema } from "@workspace/utils/schemas";
import type { SignUpFormValues } from "@workspace/utils/types";

// ✗ Bad - Imports entire utils package
import * as utils from "@workspace/utils";

Compose Schemas

Build complex schemas from simpler ones:

import { z } from "zod";
import { emailSchema, passwordSchema } from "@workspace/utils/schemas";

const authSchema = z.object({
  email: emailSchema,
  password: passwordSchema,
  rememberMe: z.boolean().optional(),
});

Create Custom Helpers

Extend package with domain-specific helpers:

import { capitalize } from "@workspace/utils";

// App-specific helper
export function formatUserName(first: string, last: string) {
  return `${capitalize(first)} ${capitalize(last)}`;
}

Troubleshooting

Type Errors

If TypeScript can't find types, ensure @workspace/utils is installed:

pnpm install
pnpm check-types

Schema Validation Failures

Check schema requirements carefully:

import { emailSchema, passwordSchema } from "@workspace/utils/schemas";

// Email must be valid format
const emailResult = emailSchema.safeParse("invalid-email");

// Password has minimum requirements
const pwdResult = passwordSchema.safeParse("short");

Missing Utilities

Check the source for available utilities:

ls packages/utils/src/helpers/

Key Scripts

CommandPurpose
pnpm devWatch mode for development
pnpm buildBuild package for production
pnpm lintCheck code quality

For additional utilities or to request new helpers, check the source code in packages/utils/src/ or open an issue on GitHub.

On this page