## Import Hygiene Guide (Domain)

### Principles

- **No deep imports**: internal file layout is not part of the contract.
- **Barrels define the public API**: if it’s not exported from the entrypoint, it’s not public.
- **Providers are integration-only**: Portal must never import provider adapters/types.

### Allowed import levels

- **Default (Portal + BFF)**:
  - `@customer-portal/domain/<module>`
  - `@customer-portal/domain/toolkit`
- **BFF-only (integration/infrastructure)**:
  - `@customer-portal/domain/<module>/providers`

### Domain-internal helpers (for domain code only)

Sometimes provider helpers need to be shared across multiple domain mappers **without**
becoming part of the public contract (and without enabling deep imports).

In those cases, keep the helpers in a stable internal location (e.g.
`packages/domain/common/providers/whmcs-utils/`) and import them via **relative imports**
from within `packages/domain/**`.

- **Allowed**: inside `packages/domain/**` only
- **Never**: imported from `apps/**`
- **Purpose**: share provider-only helpers (parsing, encoding/serialization, provider quirks)
  across multiple domain mappers while keeping the app-facing API surface clean.

## Quick Reference

| Context                 | Import Pattern                     | Example                                                             |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------- |
| Portal/BFF domain types | `@customer-portal/domain/<module>` | `import { Invoice } from "@customer-portal/domain/billing"`         |
| BFF provider adapters   | `.../<module>/providers`           | `import { Whmcs } from "@customer-portal/domain/billing/providers"` |
| Toolkit utilities       | `@customer-portal/domain/toolkit`  | `import { Formatting } from "@customer-portal/domain/toolkit"`      |

## Architecture Diagram

```mermaid
graph TD
    subgraph Portal [Portal App]
        PC[PortalComponents]
    end

    subgraph BFF [BFF App]
        BC[BFFControllers]
        BI[BFFIntegrations]
    end

    subgraph Domain [Domain Package]
        DM[ModuleEntrypoints]
        DP[ProviderEntrypoints]
        DT[Toolkit]
    end

    PC -->|allowed| DM
    PC -->|allowed| DT
    PC -.->|BLOCKED| DP

    BC -->|allowed| DM
    BC -->|allowed| DT
    BI -->|allowed| DM
    BI -->|allowed| DP
    BI -->|allowed| DT
```

### Never

- `@customer-portal/domain/<module>/**` (anything deeper than the module entrypoint)
- `@customer-portal/domain/<module>/providers/**` (anything deeper than `/providers`)
- `apps/portal/**` importing any `@customer-portal/domain/*/providers`

### Rule of thumb

Import from the **highest stable entrypoint** that contains what you need.

- If it exists in `@customer-portal/domain/<module>`, don’t import a deeper file.
- If it’s provider-specific, use `@customer-portal/domain/<module>/providers` (BFF-only).
- If it’s cross-domain utility, use `@customer-portal/domain/toolkit`.

### When to create a new explicit entrypoint (instead of deep-importing)

Create/adjust exports when:

- The symbol is used in 2+ apps (Portal + BFF), or many call sites.
- The symbol is part of a workflow that should remain stable (pagination, formatting, shared validation helpers).

Where to export it:

- **Module root** (`@customer-portal/domain/<module>`): normalized domain types/models, schemas, provider-agnostic helpers.
- **Providers entrypoint** (`.../<module>/providers`): provider adapters, mapper/query builder logic, raw provider shapes (if truly needed).
- **Toolkit** (`@customer-portal/domain/toolkit`): shared utilities (`Formatting`, `Validation`, `Typing` namespaces).

### Naming conventions

- **Module root**: `Invoice`, `invoiceSchema`, `validateOrderBusinessRules`
- **Providers**: `Whmcs`, `Salesforce`, `Freebit` namespaces; raw shapes should be obviously integration-only.

### PR checklist

- No `@customer-portal/domain/*/*` imports (except exact `.../<module>/providers` in BFF).
- Portal has **zero** `.../providers` imports.
- No wildcard subpath exports added to `packages/domain/package.json#exports`.

## Validation

After changes:

1. Run `pnpm lint`
2. Run `pnpm type-check`
3. Run `pnpm build`
