## 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/` - `@customer-portal/domain/toolkit` - **BFF-only (integration/infrastructure)**: - `@customer-portal/domain//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/` | `import { Invoice } from "@customer-portal/domain/billing"` | | BFF provider adapters | `...//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//**` (anything deeper than the module entrypoint) - `@customer-portal/domain//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/`, don’t import a deeper file. - If it’s provider-specific, use `@customer-portal/domain//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/`): normalized domain types/models, schemas, provider-agnostic helpers. - **Providers entrypoint** (`...//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 `...//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`