CodebaseSrc
Lib
Reusable utilities, configuration, and metaprogramming patterns used across the application. No dependencies on domain or adapters.
Shared Libraries (lib/)
Reusable utilities, configuration, and metaprogramming patterns used across the application. No dependencies on domain or adapters.
Modules
Type Factories
branded-types.ts- Generic factory for creating type-safe branded types with validationerror-factory.ts- Generic factory for creating custom error classes with structured data
Validation & Parsing
validation.ts- Input validation utilities (Unicode normalization, XSS protection, address validation)validation-builder.ts- Chainable validation builder pattern for composable rulesenv-parser.ts- Type-safe environment variable parser with validators
Configuration & Infrastructure
config.ts- Application configuration from environment variableslogger.ts- Structured logging implementation (console-based, implements LoggerPort)coordinates.ts- Geographic coordinate validation and utilitiesformatting.ts- Locale-aware formatting utilities (dates, numbers, currency, percentages)utils.ts- Tailwind CSS class merging utility (cn)
Key Patterns
Branded Types Factory
Create type-safe branded types to prevent string confusion:
const EmailFactory = createBrandedTypeFactory("Email", {
validate: (value: string) => {
if (!value.includes("@")) throw new Error("Invalid email");
},
normalize: (value: string) => value.toLowerCase().trim(),
});
type Email = typeof EmailFactory.__type;
const email = EmailFactory.create("user@example.com");
Error Factory
Eliminate error class boilerplate:
const CustomError = createCustomError<"CustomError", { code: number }>({
name: "CustomError",
messageBuilder: (data) => `Error ${data.code}: Something went wrong`,
});
throw new CustomError({ code: 404 });
Validation Builder
Compose validation rules fluently:
const validateUsername = validate<string>()
.notEmpty("Username required")
.minLength(3)
.maxLength(20)
.matchPattern(/^[a-z0-9_]+$/i, "Alphanumeric and underscore only")
.build();
const result = validateUsername("john_doe");
if (!result.valid) {
console.error(result.error);
}
Environment Parser
Type-safe environment variables with defaults and validation:
const port = parseEnv("PORT", {
default: 3000,
parser: envParsers.number,
validator: (n) => n > 0 && n < 65536,
});
const features = parseEnv("FEATURES", {
default: [],
parser: envParsers.array,
});
Configuration Structure
config.ts exports typed configuration object:
export const config = {
app: {
name: string;
port: number;
nodeEnv: "development" | "production" | "test";
},
njApi: {
baseUrl: string;
timeoutMs: number;
retryEnabled: boolean;
maxRetries: number;
},
cache: {
enabled: boolean;
maxEntries: number;
ttlDays: number;
},
logging: {
level: "debug" | "info" | "warn" | "error";
}
};
Logging
Structured logging with context:
import { logger } from "./lib/logger";
logger.info("Address geocoded", {
address: "123 Main St",
municipality: "Newark",
score: 95,
});
logger.error("API request failed", {
url: "https://api.example.com",
error: error.message,
});
Testing
All lib utilities have 100% test coverage:
branded-types.test.ts- Type guard validation, normalizationenv-parser.test.ts- All parser types, validators, error casesvalidation-builder.test.ts- All validator methods, chaining, edge casesvalidation.test.ts- Input validation, security checkscoordinates.test.ts- Coordinate validationconfig.test.ts- Configuration loading
Design Principles
- Zero Dependencies: Lib has no dependencies on domain or adapters
- Pure Functions: Utilities are side-effect free (except logging)
- Type Safety: TypeScript types with generics
- Reusability: Generic patterns applicable beyond this project
- Testability: Isolated, easily testable functions