Initial commit

This commit is contained in:
ada
2026-05-25 05:47:28 +00:00
commit 4d6495ffda
97 changed files with 13403 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# Source Directory
This is the root of the application source code.
## Structure
The current codebase still contains an older layer-first layout.
The preferred direction for new work is the context-first structure described in the docs:
- **`contexts/`**: first-class bounded contexts
- **`workflows/`**: top-level cross-context orchestration
- **`shared/`**: tiny ubiquitous primitives only
- **`tasks/`**: optional cross-context workflow steps
Legacy folders such as `domain/`, `policies/`, `adapters/`, `registries/`, and `layers/` may still exist during the transition.
Treat them as migration residue rather than the target architecture.
For detailed documentation, see [docs/reference/directory-layout.md](../docs/reference/directory-layout.md).
+16
View File
@@ -0,0 +1,16 @@
# Platform Adapters
**Content**: Infrastructure implementations of domain interfaces.
## Rules
1. **Implementation**: Implements the interfaces defined in `src/domain/interfaces/`.
2. **Impure**: Contains the actual I/O (SQL, Fetch, File System).
3. **Dumb**: Should not contain business rules. Just executes the command.
## Example
```typescript
export const StripeAdapter = Layer.succeed(PaymentRepo, {
charge: (amount) => ...
})
```
+21
View File
@@ -0,0 +1,21 @@
# Domain Interfaces
**Content**: Service Contracts (Ports).
## Rules
1. **Definition**: Define the capability using `Context.Tag`.
2. **No Implementation**: Do not include implementation details (SQL, HTTP calls) here.
3. **Naming**: Use names describing the *capability*, not the tool (e.g., `PaymentRepo`, not `StripeClient`).
## Example
```typescript
import { Context, Effect } from "effect"
export class PaymentRepo extends Context.Tag("PaymentRepo")<
PaymentRepo,
{
readonly charge: (amount: number) => Effect.Effect<void, PaymentError>
}
>() {}
```
+20
View File
@@ -0,0 +1,20 @@
# Domain Models
**Content**: Data Schemas (Types) and Pure Logic.
## Rules
1. **Co-location**: Define the Schema and the pure functions that operate on it in the same file.
2. **Purity**: Functions here must be 100% pure. No side effects.
3. **Scope**: Functions here should primarily operate on the entity defined in the file.
## Example (`Cart.ts`)
```typescript
import { Schema } from "@effect/schema"
export const Cart = Schema.Struct({ ... })
export type Cart = Schema.Schema.Type<typeof Cart>
// Pure Logic
export const isEmpty = (cart: Cart): boolean => cart.items.length === 0
```
+3
View File
@@ -0,0 +1,3 @@
import { Layer } from "effect";
export const MainLayer = Layer.empty;
+18
View File
@@ -0,0 +1,18 @@
# Layers (Dependency Injection)
**Content**: Static Application Wiring.
## Usage
Construct the final application layers here. This is where you decide:
"In Production, use Postgres. In Test, use InMemory."
## Example
```typescript
// Main.layer.ts
export const MainLayer = Layer.mergeAll(
PostgresLive,
StripeLive,
// ...
)
```
+11
View File
@@ -0,0 +1,11 @@
# Generic Libraries
**Content**: Internal tools with NO domain knowledge.
## Usage
Put things here that you could theoretically publish to npm as a standalone package.
- Neo4j Client wrappers
- Custom Git utilities
- Date formatting helpers (generic)
If it imports anything from `src/domain`, it does NOT belong here.
+17
View File
@@ -0,0 +1,17 @@
# Policies
**Content**: Business Rules and Decision Logic.
## Rules
1. **Purity**: Must be pure.
2. **Context**: Can accept multiple entities and configuration to make a decision.
3. **Output**: Returns a Result or a Decision (Enum/Strategy), not a side effect.
## Example
```typescript
export type PaymentStrategy = 'RETAIL' | 'WHOLESALE'
export const determinePaymentStrategy = (amount: number): PaymentStrategy =>
amount < 1000 ? 'RETAIL' : 'WHOLESALE'
```
+14
View File
@@ -0,0 +1,14 @@
# Registries
**Content**: Dynamic Runtime Selection Logic.
## Usage
Use this ONLY when you need to select an implementation at runtime based on data (Strategy Pattern).
For static wiring (e.g., "Always use Postgres in Prod"), use `src/layers/`.
## Example
```typescript
export const getPaymentAdapter = (strategy: 'RETAIL' | 'WHOLESALE') =>
strategy === 'RETAIL' ? StripeAdapter : BankAdapter
```
+18
View File
@@ -0,0 +1,18 @@
# Workflows
**Content**: Orchestration Scripts (Transaction Scripts).
## Rules
1. **Orchestration**: Calls Domain Interfaces, Policies, and other Workflows.
2. **Impure**: This is where side effects happen (via the Interfaces).
3. **Composition**: Use `Effect.gen` to compose steps linearly.
## Example
```typescript
export const checkout = (cart: Cart) => Effect.gen(function*(_) {
const strategy = Policy.determinePaymentStrategy(cart.total)
const paymentSvc = yield* _(PaymentRegistry.get(strategy))
yield* _(paymentSvc.charge(cart.total))
})
```