fortify-schema
Version:
TypeScript interface-like schema validation system that's easier to use than Zod
347 lines (289 loc) • 12.7 kB
Markdown
# Fortify Schema - Real-World Examples
This document provides production-ready schema examples for common use cases, demonstrating practical applications of Fortify Schema.
## Basic Examples
### User Schema
```typescript
import { Interface } from 'fortify-schema';
const UserSchema = Interface({
id: "positive", // Positive integer ID
email: "email", // Email format
username: "string(3,20)", // Username with length constraints
age: "int(13,120)?", // Optional age with range
role: "user|admin|moderator", // Role options
isActive: "boolean", // Active status
createdAt: "date", // Creation date
});
// Usage
const result = UserSchema.safeParse({
id: 1,
email: "john@example.com",
username: "johndoe",
role: "=user",
isActive: true,
createdAt: new Date()
});
if (result.success) {
console.log('✓ Valid:', result.data);
} else {
console.log('✗ Errors:', result.errors);
}
```
### API Response Schema
```typescript
const APIResponseSchema = Interface({
success: "boolean", // Success flag
status: "int(100,599)", // HTTP status code
data: "any?", // Optional data
errors: "string[]?", // Optional error messages
timestamp: "date", // Response timestamp
requestId: "uuid", // Request ID
});
// Usage
const apiResult = APIResponseSchema.safeParse(response);
if (apiResult.success) {
console.log('✓ API Response:', apiResult.data);
} else {
console.log('✗ Errors:', apiResult.errors);
}
```
## Enterprise Examples
### E-commerce Product Schema
```typescript
const ProductSchema = Interface({
// Basic information
id: "uuid", // UUID identifier
sku: "string(/^[A-Z]{3}-\\d{4}$/)", // SKU format (e.g., ABC-1234)
name: "string(1,100)", // Product name
description: "string(,2000)?", // Optional description
// Pricing
price: "number(0.01,)", // Minimum $0.01
originalPrice: "number(0.01,)?", // Optional original price
discount: "float(0,100)?", // Optional discount percentage
currency: Make.const("USD"), // Fixed currency
// Inventory
stock: "int(0,)", // Non-negative stock count
lowStockThreshold: "int(1,)?", // Optional low stock alert
// Categories
category: Make.union("electronics", "clothing", "books", "home"), // Category options
subcategory: "string?", // Optional subcategory
tags: "string[](,20)?", // Optional tags
// Media
images: "url[](1,10)", // 1-10 images
videos: "url[](,3)?", // Optional, max 3 videos
// Attributes
weight: "number(0,)?", // Optional weight
dimensions: {
length: "number(0,)", // Length
width: "number(0,)", // Width
height: "number(0,)" // Height
},
// Status
isActive: "boolean", // Active status
isFeatured: "boolean?", // Optional featured flag
publishedAt: "date?", // Optional publish date
});
```
### User Profile Management
```typescript
const UserProfileSchema = Interface({
// Identity
id: "uuid", // UUID identifier
email: "email", // Email format
username: "string(3,30)", // Username with length constraints
// Personal information
firstName: "string(1,50)", // First name
lastName: "string(1,50)", // Last name
displayName: "string(1,100)?", // Optional display name
bio: "string(,500)?", // Optional bio
// Contact
phone: "string(/^\\+?[1-9]\\d{1,14}$/)?", // Optional international phone
website: "url?", // Optional website
location: {
country: "string(2,2)", // ISO country code
city: "string(1,100)?", // Optional city
timezone: "string?" // Optional timezone
},
// Preferences
settings: {
theme: Make.union("light", "dark", "auto"), // Theme options
language: "string(2,5)", // Language code
notifications: {
email: "boolean", // Email notifications
push: "boolean", // Push notifications
sms: "boolean" // SMS notifications
},
privacy: {
profileVisible: "boolean", // Profile visibility
showEmail: "boolean", // Show email
showPhone: "boolean" // Show phone
}
},
// Social
socialLinks: {
twitter: "string(/^@[a-zA-Z0-9_]{1,15}$/)?", // Optional Twitter handle
linkedin: "url?", // Optional LinkedIn URL
github: "string(/^[a-zA-Z0-9-]{1,39}$/)?", // Optional GitHub username
},
// Metadata
avatar: "url?", // Optional avatar
coverImage: "url?", // Optional cover image
tags: "string[](,20)?", // Optional tags
interests: "string[](,50)?", // Optional interests
// System
role: Make.union("user", "premium", "admin", "moderator"), // Role options
status: Make.union("active", "inactive", "suspended", "pending"), // Status options
emailVerified: "boolean", // Email verification status
phoneVerified: "boolean", // Phone verification status
// Timestamps
createdAt: "date", // Creation date
updatedAt: "date", // Last updated
lastLoginAt: "date?", // Optional last login
emailVerifiedAt: "date?" // Optional email verification date
});
```
## Schema Transformation Examples
### API Versioning
```typescript
import { Mod } from 'fortify-schema';
const BaseUserSchema = Interface({
id: "uuid", // UUID identifier
email: "email", // Email format
name: "string", // Name
createdAt: "date" // Creation date
});
// V1 API: Basic fields
const UserV1Schema = Mod.pick(BaseUserSchema, ["id", "email", "name"]);
// V2 API: Add timestamps
const UserV2Schema = Mod.extend(UserV1Schema, {
createdAt: "date", // Creation date
updatedAt: "date" // Last updated
});
// V3 API: Add profile information
const UserV3Schema = Mod.extend(UserV2Schema, {
profile: {
avatar: "url?", // Optional avatar
bio: "string(,500)?" // Optional bio
},
preferences: {
theme: Make.union("light", "dark") // Theme options
}
});
```
### Form Validation
```typescript
const RegistrationSchema = Interface({
email: "email", // Email format
password: "string(8,)", // Minimum 8 characters
confirmPassword: "string(8,)", // Minimum 8 characters
firstName: "string(1,50)", // First name
lastName: "string(1,50)", // Last name
agreeToTerms: Make.const(true), // Must be true
newsletter: "boolean?" // Optional newsletter subscription
});
const LoginSchema = Mod.pick(RegistrationSchema, ["email", "password"]);
const PasswordResetSchema = Interface({
email: "email", // Email format
token: "string(/^[a-zA-Z0-9]{32}$/)", // 32-character token
newPassword: "string(8,)", // Minimum 8 characters
confirmPassword: "string(8,)" // Minimum 8 characters
});
const ProfileUpdateSchema = Mod.partial(
Mod.omit(RegistrationSchema, ["password", "confirmPassword", "agreeToTerms"])
);
```
## API Integration Examples
### REST API Schemas
```typescript
const GetUserResponseSchema = Interface({
success: "boolean", // Success flag
data: UserProfileSchema, // User profile data
meta: {
requestId: "uuid", // Request ID
timestamp: "date", // Response timestamp
version: Make.const("1.0") // API version
}
});
const CreateUserRequestSchema = Mod.omit(UserProfileSchema, [
"id", "createdAt", "updatedAt", "lastLoginAt"
]);
const UpdateUserRequestSchema = Mod.partial(CreateUserRequestSchema);
const GetUsersResponseSchema = Interface({
success: "boolean", // Success flag
data: UserProfileSchema.array(), // Array of users
pagination: {
page: "int(1,)", // Current page
limit: "int(1,100)", // Items per page
total: "int(0,)", // Total items
hasNext: "boolean", // Has next page
hasPrev: "boolean" // Has previous page
},
meta: {
requestId: "uuid", // Request ID
timestamp: "date" // Response timestamp
}
});
```
### GraphQL Integration
```typescript
const GraphQLUserSchema = Interface({
id: "uuid", // UUID identifier
email: "email", // Email format
profile: {
firstName: "string", // First name
lastName: "string", // Last name
avatar: "url?" // Optional avatar
},
posts: {
id: "uuid", // Post ID
title: "string", // Post title
content: "string", // Post content
publishedAt: "date?" // Optional publish date
}.array(),
followers: "int(0,)", // Follower count
following: "int(0,)" // Following count
});
const GetUserQuerySchema = Interface({
id: "uuid", // User ID
includeProfile: "boolean?", // Include profile data
includePosts: "boolean?", // Include posts
postsLimit: "int(1,50)?" // Optional post limit
});
```
## Security & Validation Examples
### Input Sanitization
```typescript
const SecureInputSchema = Interface({
title: "string(/^[a-zA-Z0-9\\s\\-_.,!?]{1,100}$/)", // Prevent XSS
searchQuery: "string(/^[a-zA-Z0-9\\s]{1,50}$/)", // Prevent SQL injection
filename: "string(/^[a-zA-Z0-9._-]{1,255}$/)", // File upload validation
fileType: Make.union("image/jpeg", "image/png", "image/gif", "application/pdf"), // Allowed file types
fileSize: "int(1,10485760)", // Max 10MB
requestsPerMinute: "int(1,100)", // Rate limiting
clientIP: "string(/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/)" // IP validation
});
```
### Authentication Schemas
```typescript
const JWTPayloadSchema = Interface({
sub: "uuid", // Subject (user ID)
iat: "int(1,)", // Issued at
exp: "int(1,)", // Expires at
aud: "string", // Audience
iss: "string", // Issuer
scope: "string[]", // Permissions
role: Make.union("user", "admin", "service") // Role options
});
const AuthRequestSchema = Interface({
email: "email", // Email format
password: "string(1,)", // Non-empty password
rememberMe: "boolean?", // Optional remember me
captcha: "string(/^[a-zA-Z0-9]{6}$/)?" // Optional 6-char captcha
});
const RefreshTokenSchema = Interface({
refreshToken: "string(/^[a-zA-Z0-9+/]{40,}={0,2}$/)", // Base64 token
deviceId: "uuid?" // Optional device ID
});
```
---
**Related Resources**
[Complete Documentation](./README.md) | [Quick Reference](./QUICK-REFERENCE.md)