- Changed TypeScript target and library settings in tsconfig files to align with ESNext standards. - Updated pnpm version in GitHub workflows for better dependency management. - Modified Dockerfile to reflect the updated pnpm version. - Adjusted import statements across various domain modules to include file extensions for consistency and compatibility. - Cleaned up TypeScript configuration files for improved clarity and organization.
Domain Toolkit
Utility functions and helpers for the domain layer. This package contains utilities only, not validation.
Purpose
The toolkit provides pure utility functions for common operations like:
- String manipulation
- Date/time formatting
- Currency formatting
- URL parsing and manipulation
- Type guards and assertions
Important: For validation functions (e.g., isValidEmail, isValidUuid), use packages/domain/common/validation.ts instead.
Structure
toolkit/
├── formatting/ # Formatting utilities
│ ├── currency.ts # Currency formatting (e.g., formatCurrency)
│ ├── date.ts # Date formatting (e.g., formatDate, formatRelativeTime)
│ ├── phone.ts # Phone number formatting
│ └── text.ts # Text manipulation (e.g., truncate, capitalize)
│
├── typing/ # Type utilities
│ ├── assertions.ts # Type assertions (e.g., assertNonNull)
│ ├── guards.ts # Type guards (e.g., isString, isNumber)
│ └── helpers.ts # Type helper functions
│
└── validation/ # Validation utilities (NOT validation itself)
├── email.ts # Email utilities (getEmailDomain, normalizeEmail)
├── url.ts # URL utilities (ensureProtocol, getHostname)
├── string.ts # String utilities (isEmpty, hasMinLength)
└── helpers.ts # Validation helpers (sanitizePagination, isInRange)
Important Distinction: Validation vs Utilities
❌ Validation (NOT in toolkit)
Validation determines if input is valid or invalid:
// These are VALIDATION functions → Use common/validation.ts
isValidEmail(email) // Returns true/false
isValidUuid(id) // Returns true/false
isValidUrl(url) // Returns true/false
validateUrlOrThrow(url) // Throws if invalid
Location: packages/domain/common/validation.ts
✅ Utilities (IN toolkit)
Utilities transform, extract, or manipulate data:
// These are UTILITY functions → Use toolkit
getEmailDomain(email) // Extracts domain from email
normalizeEmail(email) // Lowercases and trims
ensureProtocol(url) // Adds https:// if missing
getHostname(url) // Extracts hostname
Location: packages/domain/toolkit/
Usage Examples
Formatting
import { formatCurrency, formatDate } from "@customer-portal/domain/toolkit/formatting";
const price = formatCurrency(1000, "JPY"); // "¥1,000"
const date = formatDate(new Date()); // "2025-10-08"
Type Guards
import { isString, isNumber } from "@customer-portal/domain/toolkit/typing";
if (isString(value)) {
// TypeScript knows value is string here
console.log(value.toUpperCase());
}
URL Utilities
import { ensureProtocol, getHostname } from "@customer-portal/domain/toolkit/validation/url";
const fullUrl = ensureProtocol("example.com"); // "https://example.com"
const host = getHostname("https://example.com/path"); // "example.com"
Email Utilities
import { getEmailDomain, normalizeEmail } from "@customer-portal/domain/toolkit/validation/email";
const domain = getEmailDomain("user@example.com"); // "example.com"
const normalized = normalizeEmail(" User@Example.COM "); // "user@example.com"
When to Use What
| Task | Use | Example |
|---|---|---|
| Validate email format | common/validation.ts |
isValidEmail(email) |
| Extract email domain | toolkit/validation/email.ts |
getEmailDomain(email) |
| Validate URL format | common/validation.ts |
isValidUrl(url) |
| Add protocol to URL | toolkit/validation/url.ts |
ensureProtocol(url) |
| Format currency | toolkit/formatting/currency.ts |
formatCurrency(amount, "JPY") |
| Format date | toolkit/formatting/date.ts |
formatDate(date) |
Best Practices
-
Use validation functions for validation
// ✅ Good import { isValidEmail } from "@customer-portal/domain/common/validation"; if (!isValidEmail(email)) throw new Error("Invalid email"); // ❌ Bad - don't write custom validation if (!email.includes("@")) throw new Error("Invalid email"); -
Use utility functions for transformations
// ✅ Good import { normalizeEmail } from "@customer-portal/domain/toolkit/validation/email"; const clean = normalizeEmail(email); // ❌ Bad - don't duplicate utility logic const clean = email.trim().toLowerCase(); -
Don't mix validation and utilities
// ❌ Bad - mixing concerns function processEmail(email: string) { if (!email.includes("@")) return null; // Validation return email.toLowerCase(); // Utility } // ✅ Good - separate concerns import { isValidEmail } from "@customer-portal/domain/common/validation"; import { normalizeEmail } from "@customer-portal/domain/toolkit/validation/email"; function processEmail(email: string) { if (!isValidEmail(email)) return null; return normalizeEmail(email); }
Migration Notes
If you're refactoring existing code:
- Validation functions → Move to
common/validation.ts - Utility functions → Keep in or move to
toolkit/ - Business logic → Move to domain-specific
validation.tsfiles
Related Documentation
- Validation Patterns Guide - How to implement validation
- Domain Layer Design - Overall domain architecture
- Common Validation - Validation functions
Questions?
If you're unsure whether something belongs in toolkit or common/validation:
-
Ask: "Does this determine if input is valid/invalid?"
- YES → It's validation → Use
common/validation.ts - NO → It's a utility → Use
toolkit/
- YES → It's validation → Use
-
Ask: "Does this transform or extract data?"
- YES → It's a utility → Use
toolkit/ - NO → Might be validation → Use
common/validation.ts
- YES → It's a utility → Use