barsa 29ad4236d6 Enhance development scripts and update package dependencies
- Added a new script command `dev:studio` to facilitate studio management in development.
- Updated the Prisma dependency in BFF package to version 6.16.0 for improved features and bug fixes.
- Refactored Dockerfiles for BFF and Portal to enhance health check mechanisms during startup.
- Removed deprecated WhmcsApiMethodsService to streamline the integration services.
- Cleaned up various components and services in the SIM management module for better maintainability and clarity.
2025-12-02 18:56:38 +09:00
..

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

  1. 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");
    
  2. 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();
    
  3. 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:

  1. Validation functions → Move to common/validation.ts
  2. Utility functions → Keep in or move to toolkit/
  3. Business logic → Move to domain-specific validation.ts files

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/
  • Ask: "Does this transform or extract data?"

    • YES → It's a utility → Use toolkit/
    • NO → Might be validation → Use common/validation.ts