void-hexagonal-architecture

Enforces ports-and-adapters architecture with function-parameter injection and domain-owned interfaces in TypeScript projects.

Updated May 29, 2026
One-click install
npx skills add https://github.com/voidcorp-core/void-harness --skill void-hexagonal-architecture-voidcorp-core
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: void-hexagonal-architecture
Source: https://github.com/voidcorp-core/void-harness/tree/main/packages/core/skills/void-hexagonal-architecture
Command: npx skills add https://github.com/voidcorp-core/void-harness --skill void-hexagonal-architecture-voidcorp-core

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Codebases drift as business logic leaks into framework code, database layers, and third-party SDK calls, making the domain untestable and infrastructure expensive to swap. This Skill defines where every piece of code belongs—domain, use-case, adapter, or infrastructure—and enforces a one-way dependency direction so the domain never depends on the outside world. ## Core Features & Use Cases - Ports and adapters placement rules: Domain owns behavior-named port interfaces, thin adapters translate to concrete technologies (Drizzle, Stripe, Resend) at the edge, and use-cases orchestrate ports with no I/O of their own. - Function-parameter injection: Dependencies are passed as a typed deps parameter instead of DI containers, keeping the call graph visible with zero runtime magic. - In-memory adapter testing pattern: Every port ships an in-memory adapter so use-case tests run without mocking frameworks or real infrastructure. - Use Case: When adding a checkout flow, place the orchestration in services/checkout.ts taking OrdersPort, PaymentPort, and ClockPort as injected deps, implement Drizzle and Stripe adapters at the edge, and test with in-memory adapters—while the companion hook blocks any domain-to-infrastructure import. ## Quick Start Ask the agent to add a new use-case such as "add a checkout flow with payment and order persistence" and it will place the domain logic, ports, and adapters according to the hexagonal rules.

Frequently Asked Questions about void-hexagonal-architecture

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I structure a TypeScript project with hexagonal architecture?

Split code into domain/ (entities and value objects), services/ (use-cases orchestrating ports), adapters/ (port implementations for DB and external APIs), and infrastructure/ (raw SDK and Drizzle config). The domain owns port interfaces and never imports outward layers.

How do I do dependency injection without a DI container in TypeScript?

Pass dependencies as a typed deps parameter to each use-case function, then compose concrete adapters at the framework boundary. This replaces containers like tsyringe or inversify with zero runtime cost and a fully visible call graph.

How do I test use-cases without a mocking framework?

Give every port an in-memory adapter co-located in production code, then inject those adapters in tests. The in-memory shape matches production exactly, so tests exercise real orchestration logic without mocks or databases.

When should I not use CQRS or event sourcing with ports and adapters?

CQRS is only justified when read scale or read shape diverges enough to warrant duplicate models, and event sourcing only when an audit or temporal log is required. Both are rejected as defaults and reintroducing either requires an explicit architecture decision record.

Why is importing infrastructure from the domain layer a problem?

It reverses the dependency direction, coupling business rules to a specific database or SDK and making the domain untestable in isolation. The companion boundary-direction-check hook greps and blocks domain-to-infrastructure imports on every commit.