- Added a new script to check domain imports, promoting better import hygiene across the codebase. - Refactored multiple domain index files to remove unnecessary type re-exports, streamlining the module structure. - Expanded documentation on import patterns and validation processes to provide clearer guidance for developers. - Included an architecture diagram to illustrate the relationships between the Portal, BFF, and Domain packages.
3.5 KiB
3.5 KiB
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
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
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,Typingnamespaces).
Naming conventions
- Module root:
Invoice,invoiceSchema,validateOrderBusinessRules - Providers:
Whmcs,Salesforce,Freebitnamespaces; raw shapes should be obviously integration-only.
PR checklist
- No
@customer-portal/domain/*/*imports (except exact.../<module>/providersin BFF). - Portal has zero
.../providersimports. - No wildcard subpath exports added to
packages/domain/package.json#exports.
Validation
After changes:
- Run
pnpm lint - Run
pnpm type-check - Run
pnpm build